xiaohongshu-xs-reverse
⚠️ 免责声明:本文仅用于安全研究与技术交流,请勿将相关技术用于非法用途。恶意使用相关技术造成的一切后果由使用者自行承担。
目标站点:https://www.xiaohongshu.com/explore
概述
小红书 Web 端在多数 API 请求中都携带 X-S 请求头进行签名校验。简单来说,服务端会验证请求头中的 X-S 是否合法,如果不合法就直接拒绝请求。本文会完整记录这个签名机制的分析过程,从环境模拟到算法还原,再到用 Python 调用生成签名并发起请求,一步步带你实现自动生成 X-S。
逆向入口定位
想要找到签名逻辑,第一步就是定位加密函数在代码中的位置。打开目标站点,按以下步骤操作:
- 进入小红书探索页,打开浏览器开发者工具(F12),切换到 Network 面板。
- 筛选
XHR/Fetch请求,随便滚动页面触发一些加载,找到带有X-S请求头的接口,例如首页 feed 接口/api/sns/web/v1/homefeed。 - 在 Sources 面板中,全局搜索
X-s或X-S字符串,一般会在一些请求拦截器中找到赋值的地方。 - 更直接的方法是使用
XHR/fetch Breakpoints:在 Sources 面板右侧的 XHR/fetch Breakpoints 中添加一个过滤条件,比如/api/sns/web/v1/homefeed,这样在请求发出前就会自动断下。然后通过调用栈一路向上回溯,就能找到签名生成的逻辑。
💡 小技巧:如果搜索
X-S字符串太多,可以尝试搜索XYS_前缀,这是最终签名的固定开头,极大概率直接定位到核心加密函数。
经过跟踪分析,会发现签名逻辑大致隐藏在一个巨大的 Webpack 打包文件里,并且函数名通常被混淆。我们需要做的就是将关键的加密逻辑剥离出来,在 Node.js 环境中复现。
核心签名流程分析
1. 签名生成步骤
通过断点调试和代码反混淆,梳理出 X-S 的完整生成流程:
- 拼接字符串:将 API 路径(如
/api/sns/web/v1/homefeed)与请求参数的 JSON 字符串拼接在一起。 - 计算 MD5:对上一步得到的字符串取 MD5 摘要。
- 调用 mnsv2 算法:将原始拼接字符串和 MD5 值传入一个名为
mnsv2的自定义函数,生成核心签名(signature)。 - 组装签名对象:把版本号、平台、操作系统、上一步得到的签名等组合成一个固定结构的对象。
- 编码输出:将签名对象转为 JSON 字符串,经过 UTF-8 编码和自定义 Base64 编码,最后加上
XYS_前缀,得到最终的X-S值。
2. 关键数据结构
最终参与编码的对象结构大致如下:
整个签名过程用一句话概括就是:“参数拼起来算 MD5,再丢给 mnsv2 生成核心签名,最后用自定义 Base64 包装一下。”
关键代码实现
1. 浏览器环境模拟
小红书的前端代码会对代码运行环境进行校验(比如检查 navigator 的属性),我们要在 Node.js 中实现纯算法,就必须提前补全这些全局对象。通过 Proxy 和类继承等手段,可以“骗过”原代码,让它在 Node 环境下依然正常运行。
注意:
mnsv2函数里具体用了哪些环境属性,需要根据你的逆向结果去补,并不是固定不变的。上面的代码只是一个示例框架。
2. 核心签名函数
有了补好的环境,就可以运行剥离出来的加密代码了。下面是一个简化的主逻辑示例,实际使用中你需要把逆向出的 mnsv2 函数完整搬过来。
3. 辅助编码函数
小红书使用的 Base64 是自定义字典,不是标准 Base64,需要在逆向时提取对应字符表。下面是一个根据常见模式编写的示例,注意把 keyStr 替换成你逆向到的具体字符串。
端到端调用示例
为了方便实际使用,我们可以把 Node.js 脚本封装成一个签名服务,然后用 Python 调起脚本获取签名,再携带签名去请求接口。
1. Node.js 签名脚本(xiaohongshu_sign.js)
将上面的环境补全代码、mnsv2 函数以及生成函数整合到一个文件中,结尾输出 JSON 格式的 X-s:
2. Python 调用脚本
通过 subprocess 调用 Node.js,获取返回值后发起请求。同时别忘记填入自己的 Cookie。
关键注意事项
- 环境模拟要精确:
mnsv2算法内部一般会访问navigator.userAgent、screen.width等属性,漏掉任何一个都会导致签名计算错误。 - JSON 序列化顺序:
JSON.stringify对不同顺序的键值对输出结果可能不一样,务必保证与浏览器端完全一致。通常逆向时可以 HookJSON.stringify来观察原始参数。 - Base64 自定义字典:不要使用 Node.js 原生的
Buffer.toString('base64'),必须使用逆向出的自定义字典实现。 - 版本号与算法更新:
x0版本、mnsv2函数可能随着站点的升级而变化,需要做好长期维护的准备。
总结
小红书 Web 端的 X-S 签名通过“环境校验 + 多层编码 + 自定义算法”的组合来提高构造请求的门槛。还原的关键点在于:
- 通过浏览器断点定位加密入口;
- 补全 Node.js 所需的浏览器环境;
- 抠出并改写
mnsv2核心函数; - 正确处理参数拼接顺序和自定义 Base64 编码。
一旦完成上述步骤,就可以在本地稳定生成合法签名,并结合 Python 等语言实现自动化数据采集。希望这篇笔记能为大家在类似逆向分析中提供思路。

