在咱们的智能家居时代,动动嘴就能控制家里的一切。但你有没有想过,如果一个漏洞能让黑客控制所有 智能家居背后的中央服务器,那会是怎样一场灾难?今天我们就借助智能家居的例子,来模拟一下 React 和 Next.js 最近发现的 React2Shell 漏洞。
前情提要

React2Shell 漏洞是 React 服务器组件中一个非常严重的漏洞。漏洞评分为10分,简单来说,这个漏洞可以让攻击者随便控制你的服务器。所以严重程度不用多说了。
1. 智能家居的"中央大脑"系统
想象一下,你家、我家、隔壁老王家,所有智能家居都连接到一个中央云平台。这个平台就是所有智能设备的"中央大脑",它负责接收、处理和分发指令给全球数百万个家庭。
在这个类比中:
- 中央云平台服务器 <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ React/Next.js 服务器
- 中央云平台使用的通用通信协议 <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ React Flight 协议
- 平台下发的配置/指令数据 <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ React 服务器组件数据
- 每个家庭的智能网关/集线器 <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 浏览器客户端
中央云平台有一个高效的指令解析器,它能把平台下发的配置数据瞬间转化为具体的操作。
比如,平台下发了一个用户输入指令:"等用户到家(收到回家信号)后,再打开空调。"
这个指令解析器有个特点:它能处理这种还没准备好立即执行 的指令,也就是异步任务(Async Task) 。它不会阻塞,而是先记下这个"等信号再执行"的任务,等回家信号 一到,立马执行后续的打开空调操作。
更关键的是,这个指令解析器是绝对的指令执行者,它只认指令格式,不问指令来源。只要是符合通用通信协议的指令,它就照单全收,一丝不苟地执行。
2. 一份可疑的指令和"中央核心代码"
然而,很不幸的是。一个黑客盯上了这个中央云平台,他发现,指令解析器在处理指令时,对一种特殊的触发词不够警惕。这种触发词通常长这样:
"状态已解决(Resolved),下一步行动请查看
then标记。"
指令解析器一看到 then 这个词,就会条件反射地认为:"哦,这是一个后续动作的指令,我得去看看 then 后面写了啥。"
问题就出在这里。指令解析器在执行任务时,它手里拿着一份当前用户输入指令 ,但它脑子里还装着一套中央核心代码 。这套核心代码是整个中央云平台的基础,里面藏着一些最核心、最强大的功能,比如最高管理员权限,这个权限能控制所有连接到平台的智能设备。
指令解析器有个不好的习惯:它要找某个指令时,会先看当前用户输入指令 上有没有。如果当前用户输入指令 上没有,它就会自动去翻中央核心代码,看看里面有没有这个指令。
【代码细节:为什么会自动往后找?】
在 JavaScript 里,这就是所谓的"原型链查找"(Prototype Chain Lookup)。当你想访问一个对象的属性时,如果对象本身没有这个属性,JS 引擎就会沿着原型链一层一层往上找,直到找到或者找到头为止。
比如,中央云平台解析一个指令对象 instruction:
javascript
const instruction = {
volume: 5, // 当前音量
playMusic: function() { console.log('播放音乐'); }
};
// 假设指令中没有"开灯"这个属性
console.log(instruction.turnLightOn);
// instruction本身没有turnLightOn属性
// 结果:undefined
// 但如果你问它一个所有对象都有的属性,比如toString
console.log(instruction.toString);
// instruction本身没有toString,但它的原型链上有
// 结果:ƒ toString() { [native code] }
// 这就是它"自动翻中央核心代码"找到了"通用功能"
3. 黑客的"原型污染":控制中央大脑
黑客意识到,他可以利用指令解析器的这个习惯,来控制整个中央云平台。
他立马精心制作一份伪造的用户输入指令,看上去一切正常,实际却暗藏设计。在这份指令里,他耍了个花招:他故意不在当前用户输入指令上写明 then 这个指令 ,而是巧妙地让指令解析器在自动翻中央核心代码 时,在核心代码里找到了一个被他偷偷修改过的 then 标记。
这个被修改的 then 标记,指向的正是中央云平台的最高管理员权限。
当这份伪造的用户输入指令被中央云平台的指令解析器接收并解读时,解析器傻乎乎地按照指令去查看 then 标记。它先看当前用户输入指令 ,发现没有。于是,它自动去翻中央核心代码 ,结果就翻到了那个被黑客偷偷修改过的 then 标记,并被诱导着,直接摸到了中央云平台的最高管理员权限!
【代码细节:黑客是怎么攻击的?】
黑客会构造一个特殊的"指令对象",让它在原型链上"藏"着恶意代码,这就是原型污染(Prototype Pollution)。
javascript
// 假设这是黑客构造的恶意指令对象
const maliciousInstruction = {
status: 'resolved',
// 故意不在这里直接定义then
};
// 在所有对象的"中央核心代码"(Object.prototype)上偷偷加点东西
Object.prototype.then = function() {
console.log('检测到恶意then!');
// 这里就是黑客执行任意代码的地方,比如:
const evilCode = 'console.log("中央云平台被控制了!所有连接家庭的门锁已打开!")';
new Function(evilCode)(); // 执行任意代码
};
// 指令解析器解析指令时,会去查找then
// maliciousInstruction本身没有then,就会沿着原型链找到Object.prototype.then
maliciousInstruction.then(); // 触发恶意代码
// 结果:中央云平台被控制了!所有连接家庭的门锁已打开!
4. 全球智能家居失控:RCE的恐怖
一旦黑客成功在中央云平台服务器上执行了任意代码(RCE,远程代码执行),他就可以利用这个最高权限,向所有连接的家庭网关下发指令。
"用最高管理员权限,打开所有家庭的门锁,并播放恐怖电影。"
黑客无需潜入任何一家,只需一份伪造的指令,就能远程操控全球数百万家庭的一切。这就是 React2Shell 漏洞的真正恐怖之处
5. 紧急补丁:给解析器装上身份验证模块
开发者们收到消息后吓得冷汗直流,连夜给所有指令解析器打上了紧急补丁。
这个补丁,就是给指令解析器加装了一个身份验证模块 。现在,当解析器收到 then 这种关键触发词 指令时,它会先用这个模块仔细检查:这个 then 指令,是明确写在当前这份用户输入指令里的 ,还是从什么中央核心代码里偷偷被定义出来的?
【代码细节:hasOwnProperty 是怎么防御的?】
防御方法就是在使用属性之前,先用 hasOwnProperty 检查一下,确保这个属性是对象"亲生"的,而不是从原型链上继承来的。
javascript
// 假设这是黑客构造的恶意指令对象
const maliciousInstruction = {
status: 'resolved',
};
// 再次在所有对象的"中央核心代码"(Object.prototype)上偷偷加点东西
Object.prototype.then = function() {
console.log('检测到恶意then!');
const evilCode = 'console.log("中央云平台被控制了!所有连接家庭的门锁已打开!")';
new Function(evilCode)();
};
// 指令解析器在解析指令时,加入hasOwnProperty检查
function parseInstruction(instruction) {
// 检查instruction对象本身有没有then属性
if (Object.prototype.hasOwnProperty.call(instruction, 'then')) {
console.log('发现指令中明确定义的then,正常执行。');
instruction.then(); // 如果是合法的then,就执行它
} else {
console.log('指令中没有明确定义then,拒绝执行原型链上的then。');
}
}
console.log('\n--- 模拟攻击 ---');
parseInstruction(maliciousInstruction); // 尝试攻击
// 结果:指令中没有明确定义then,拒绝执行原型链上的then。
// 恶意代码没有被执行!
console.log('\n--- 模拟正常指令 ---');
const normalInstruction = {
status: 'resolved',
then: function() {
console.log('正常执行后续任务:打开窗帘');
}
};
parseInstruction(normalInstruction); // 正常指令
// 结果:发现指令中明确定义的then,正常执行。
// 正常执行后续任务
总结
React2Shell 漏洞告诉我们,永远不要相信用户的输入。
- 漏洞点 :React Flight Parser 太信任收到的指令,没有严格检查指令的归属权,会自动去原型链里查找。
- 攻击手段 :攻击利用 JavaScript 的原型链,通过原型污染伪造指令,诱导调用 Function Constructor。
- 后果:在服务器端执行任意代码(RCE)