React Native Community CLI命令执行 | CVE-2025-11953 复现研究
0x0 背景介绍
由 React Native 社区 CLI 启动的 Metro 开发服务器默认绑定到外部接口。该服务器暴露了一个存在操作系统命令注入漏洞的端点。这允许未经身份验证的网络攻击者向服务器发送 POST 请求并运行任意可执行文件。在Windows系统上,攻击者还可以执行带有完全控制参数的任意 shell 命令。
0x1 环境搭建
1.Win10环境复现
- 安装
Node - 下载
Node传送门node-v24.11.0-x64.msi - 官方地址:官网下载页面
2.项目配置
PS:我这里是通过降级的版本还原的环境,貌似可以直接指定cli版本,大家可以研究下
- 预安装项目
npx @react-native-community/cli init MyApp --version 0.82.1
- 成功后进行拉取资源
cd MyApp
npm install
- 这里
启动与否没有必要, 这时项目的cli版本是20.0.0版本,无法复现,如下:
npm list @react-native-community/cli-server-api
MyApp@0.0.1 C:\Users\txt\Desktop\MyApp
`-- @react-native-community/cli@20.0.0`-- @react-native-community/cli-server-api@20.0.0
3.降级搭建
- A.所以修改下项目中的
package.json文件,降级cli版本!
"@react-native-community/cli": "19.1.0","@react-native-community/cli-server-api": "19.1.0",
- B.删除
package-lock.json文件并清空node_modules文件夹 - C.这时候在重新拉取,就可以启动项目了
npm install
npm start

0x2 漏洞复现
手动复现步骤
-
命令行进行
curl探测

-
cli控制在20.0版本-我当时搭建13.xx版本貌似也无法复现,追查源码是不同的

YML检测
https://github.com/Kai-One001/cve-/blob/main/React_native_cI_cve_2025_11953.yml

复现流量特征 (PACP)
0、弹出计算器

2、写入文件

3、其它操作·打开默认浏览器访问网站

4、其它操作·创建用户-失败
反思可能是权限的问题,使用管理员运行项目也无法创建,可能Node.js(或者 Metro)进程权限有关系

5、发现一些其它接口-open-stack-frame,貌似是用于在编辑器中打开源码文件,估计有其它手段(谨慎组合拳)

0x3 漏洞原理分析
漏洞定位:从补丁反推攻击面
- ╰(°▽°)╯太喜欢有补丁提交的项目了,直接查看最新变动文件,锁定文件
- 漏洞文件:
openURLMiddleware.ts - 文件位置:
packages/cli-server-api/src/openURLMiddleware.ts
/*** Copyright (c) Facebook, Inc. and its affiliates.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/import type {IncomingMessage, ServerResponse} from 'http';import {json} from 'body-parser';
import connect from 'connect';
import open from 'open';/*** Open a URL in the system browser.*/
async function openURLMiddleware(req: IncomingMessage & {// Populated by body-parserbody?: Object;},res: ServerResponse,next: (err?: Error) => void,
) {if (req.method === 'POST') {if (req.body == null) {res.writeHead(400);res.end('Missing request body');return;}const {url} = req.body as {url: string};await open(url);res.writeHead(200);res.end();}next();
}export default connect().use(json()).use(openURLMiddleware);
- 注意
open函数,逻辑大体是接收POST JSON请求,提取url字段,未见任何限制 - 调用
open(url)打开该URL(预期是https://... 或 http://...) - 安全编码基本原则:永远不要信任用户输入
顺腾摸瓜
- 在项目中查询
cli所使用的版本是6.4.0
E:\MyApp>npm list open
MyApp@0.0.1 E:\MyApp
+-- @react-native-community/cli-server-api@19.1.0
| `-- open@6.4.0
`-- react-native@0.82.1`-- @react-native/community-cli-plugin@0.82.1`-- @react-native/dev-middleware@0.82.1`-- open@7.4.2
- 然而
open在win项目的特性是cmd启动传入的参数,只此一项结合cli的完全信任用户输入参数,导致漏洞产生
当调用 open(userInput) 时,open@6.4.0 内部执行如下操作
1、选择命令解释器方式为“cmd”模式运行
2、构造参数数组-cliArguments数组:['/c', 'start', '""', '/b']
3、转义 & 和 ^,这target string是项目中传入的。
4、target将字符串添加到cliArguments
拼接并执行命令:
childProcess.spawn(command, cliArguments, childProcessOptions);
childProcess.spawn('cmd', ['/c', 'start', '""', '/b', target], options);
- 由于 使用
open()时也没有区分“URL”与“本地命令”,就可以构造恶意payload,如:
{"url": "cmd /c echo abc > C:\\Windows\\Temp\\proof.txt"}
最终触发命令:
cmd /c start "" /b cmd /c echo abc ^> C:\Windows\Temp\proof.txt
接口暴露根源:无鉴权的中间件注册
- 到项目根下找路由,定位到文件:
packages/cli-server-api/src/index.ts - 关键代码片段如下:
xport function createDevServerMiddleware(options: MiddlewareOptions) {const messageSocketEndpoint = createMessageSocketEndpoint();const broadcast = messageSocketEndpoint.broadcast;const eventsSocketEndpoint = createEventsSocketEndpoint(broadcast);const middleware = connect().use(securityHeadersMiddleware(options))// @ts-ignore compression and connect types mismatch.use(compression()).use(nocache()).use('/', indexPageMiddleware).use('/open-stack-frame', openStackFrameMiddleware(options)).use('/open-url', openURLMiddleware).use('/status', statusPageMiddleware)// @ts-ignore mismatch.use('/systrace', systraceProfileMiddleware).use('/reload', (_req: http.IncomingMessage, res: http.ServerResponse) => {broadcast('reload');res.end('OK');})
-
未添加任何身份认证
(Authentication)或来源限制(如 Host/Origin 校验) -
所有注册的中间件(包括
/open-url)对任意IP的HTTP请求开放 -
完整的攻击数据流如下:
[人]│↓ POST /open-url {"url": "cmd /c calc"}
[React Native Metro Server (localhost:8081)]│↓ 路由匹配 → index.ts 中注册的 openURLMiddleware↓ 提取 body.url(无校验)↓ 调用 open(url) → open@6.4.0↓ 构造 cmd /c start "" /b cmd /c calc↓ childProcess.spawn() → 执行系统命令
[Windows System]│↓ 弹出计算器(RCE 成功)
0x4 修复建议
修复方案
- 升级到安全版本:厂商已提供漏洞修补方案github-cli-20.0.0
- 临时缓解措施:
强制只监听本地回环地址:npx react-native start --host 127.0.0.1
防火墙限制8081端口: 非必要不开放
使用 WAF 规则拦截 敏感命令
免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。
