
本仓库是我对 CVE-2025-55182(也称为 React2Shell 漏洞)的研究。仓库由两个主要部分组成:stand 和 exploit。
关于此安全漏洞的一些信息:
该漏洞基本上是缺乏用户输入验证。但事情并没有那么简单 =)
React Client 部分和 React Server 部分使用 React Flight Protocol 来交换数据。这里有一个很好的演讲,可以帮助你快速熟悉它。
React Flight Protocol 消息块示例:
{
"0": (None, '["$1"]'),
"1": (None, '{"object":"fruit","name":"$2:fruitName"}'),
"2": (None, '{"fruitName":"cherry"}'),
}
RFP 的块可以通过 $ 运算符相互引用。当这些块随后在服务器上反序列化时,这些链接会被解析。这里的一个关键点是,我们可以通过它访问对象原型。
通过操纵原型,我们可以强制 V8 await 我们的 .then()。最终的 payload 可能如下所示:
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"return foo; ",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
我不会深入探讨这条 gadget 链实际上是如何工作的,如果你想了解更多,可以阅读 Moritz Sanft 撰写的精彩分析:这里。
如果你想更深入地研究这个缺陷,还可以查看补丁前后的 GitHub 版本对比。
我创建了一个简单的 react/next.js 应用,它使用了(参见 stand/package.json):
"dependencies": {
"next": "16.0.6",
"react": "19.2.0",
"react-dom": "19.2.0"
},
只是一个用 create-next-app 创建的包含文本内容的简单页面:
要启动它,请在 stand 目录下运行:
docker compose up --build -d
然后在浏览器中访问 http://localhost:3000。
利用过程很直接。我们只需通过 POST 请求将特制的 RFP 块连同 payload 发送到服务器即可。参见 exploit/src/main.py。它还包含一个简单的检查,用于判断服务器是否存在漏洞:它会尝试运行 whoami 命令,如果超时,则服务器很可能使用了已修补的版本。
你可以在 exploit/resource/chunk.json 中看到 RFP payload。
在运行 exploit 之前,别忘了设置 netcat 监听器,并更新 exploit/resource/config.toml 中的主机和端口,以获得反向 shell。
祝 Pwn 愉快!
向发现该漏洞的 Lachlan Davidson、找到优秀 gadget 的 maple,以及分享 PoC 并撰写精彩分析的 Moritz Sanft 致以崇高敬意。
由 I3r1h0n 制作。