diff --git a/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/client-side-prototype-pollution.md b/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/client-side-prototype-pollution.md index 458211c14..b9b1aa9e8 100644 --- a/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/client-side-prototype-pollution.md +++ b/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/client-side-prototype-pollution.md @@ -8,7 +8,7 @@ 此外,您还可以使用 **浏览器扩展** [**PPScan**](https://github.com/msrkp/PPScan) **自动** **扫描** 您 **访问** 的 **页面** 以查找原型污染漏洞。 -### 调试属性使用的位置 +### 调试属性的使用位置 ```javascript // Stop debugger where 'potentialGadget' property is accessed Object.defineProperty(Object.prototype, "potentialGadget", { @@ -21,12 +21,12 @@ return "test" ``` ### 找到原型污染的根本原因 -一旦通过任何工具识别出原型污染漏洞,并且代码不是过于复杂,您可以通过在 Chrome 开发者工具中搜索关键字如 `location.hash`、`decodeURIComponent` 或 `location.search` 来找到漏洞。这种方法可以帮助您准确定位 JavaScript 代码中的漏洞部分。 +一旦通过任何工具识别出原型污染漏洞,并且代码不是过于复杂,您可以通过在 Chrome 开发者工具中搜索关键词如 `location.hash`、`decodeURIComponent` 或 `location.search` 来找到漏洞。这种方法可以帮助您准确定位 JavaScript 代码中的漏洞部分。 对于更大和更复杂的代码库,发现漏洞代码的简单方法包括以下步骤: -1. 使用工具识别漏洞并获取一个旨在设置构造函数中属性的有效载荷。ppmap 提供的示例可能看起来像:`constructor[prototype][ppmap]=reserved`。 -2. 在页面上将执行的第一行 JavaScript 代码处设置断点。使用有效载荷刷新页面,在此断点处暂停执行。 +1. 使用工具识别漏洞并获取一个旨在设置构造函数中属性的有效载荷。ppmap 提供的一个示例可能看起来像:`constructor[prototype][ppmap]=reserved`。 +2. 在页面上将要执行的 JavaScript 代码的第一行设置断点。使用有效载荷刷新页面,在此断点处暂停执行。 3. 当 JavaScript 执行暂停时,在 JS 控制台中执行以下脚本。该脚本将在创建 'ppmap' 属性时发出信号,帮助定位其来源: ```javascript function debugAccess(obj, prop, debugGet = true) { @@ -46,9 +46,9 @@ origValue = val debugAccess(Object.prototype, "ppmap") ``` -4. 返回到 **Sources** 标签并选择“恢复脚本执行”。JavaScript 将继续执行,'ppmap' 属性将如预期被污染。利用提供的代码片段可以帮助识别 'ppmap' 属性被污染的确切位置。通过检查 **Call Stack**,可以观察到污染发生的不同堆栈。 +4. 返回到 **Sources** 标签并选择“Resume script execution”。JavaScript 将继续执行,'ppmap' 属性将如预期被污染。利用提供的代码片段可以帮助识别 'ppmap' 属性被污染的确切位置。通过检查 **Call Stack**,可以观察到污染发生的不同堆栈。 -在决定调查哪个堆栈时,通常有用的是针对与 JavaScript 库文件相关的堆栈,因为原型污染通常发生在这些库中。通过检查其与库文件的关联(在右侧可见,类似于提供的图像以供参考)来识别相关堆栈。在有多个堆栈的情况下,例如第 4 行和第 6 行,逻辑选择是第 4 行的堆栈,因为它代表了污染的初始发生,从而是漏洞的根本原因。点击该堆栈将引导您到易受攻击的代码。 +在决定调查哪个堆栈时,通常有用的是针对与 JavaScript 库文件相关的堆栈,因为原型污染通常发生在这些库中。通过检查其与库文件的关联(在右侧可见,类似于提供的图像)来识别相关堆栈。在有多个堆栈的情况下,例如第 4 行和第 6 行,逻辑选择是第 4 行的堆栈,因为它代表了污染的初始发生,从而是漏洞的根本原因。点击该堆栈将引导您到易受攻击的代码。 ![https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg](https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg) @@ -56,11 +56,11 @@ debugAccess(Object.prototype, "ppmap") 小工具是 **一旦发现 PP 漏洞将被滥用的代码**。 -如果应用程序很简单,我们可以 **搜索** **关键字**,如 **`srcdoc/innerHTML/iframe/createElement`** 并查看源代码,检查是否 **导致 JavaScript 执行**。有时,提到的技术可能根本找不到小工具。在这种情况下,纯源代码审查会揭示一些不错的小工具,如下面的示例。 +如果应用程序很简单,我们可以 **搜索** **关键字**,如 **`srcdoc/innerHTML/iframe/createElement`**,并查看源代码,检查是否 l**eads to javascript execution**。有时,提到的技术可能根本找不到小工具。在这种情况下,纯源代码审查会揭示一些不错的小工具,如下面的示例。 ### 示例 在 Mithil 库代码中找到 PP 小工具 -查看此写作: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/) +查看此写作:[https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/) ## 针对易受攻击库的有效负载重新编译 @@ -101,8 +101,73 @@ const node = goog.dom.safeHtmlToNode(sanitized); document.body.append(node); ``` +## 新工具与自动化 (2023–2025) + +* **Burp Suite DOM Invader (v2023.6)** – PortSwigger 添加了一个专用的 *Prototype-pollution* 标签,自动变更参数名称(例如 `__proto__`、`constructor.prototype`),并在浏览器扩展的汇点检测污染属性。当触发一个 gadget 时,DOM Invader 显示执行栈和属性被解除引用的确切行,使手动断点查找变得不必要。将其与上面已经展示的“在属性访问时中断”代码片段结合使用,可以快速从 *source → sink* 切换。 +* **protoStalker** – 一个开源的 Chrome DevTools 插件(发布于 2024),实时可视化原型链,并标记对全球危险键(如 `onerror`、`innerHTML`、`srcdoc`、`id` 等)的写入。当你只有生产包而无法对构建步骤进行插桩时非常有用。 +* **ppfuzz 2.0 (2025)** – 该工具现在支持 ES-modules、HTTP/2 和 WebSocket 端点。新的 `-A browser` 模式启动一个无头的 Chromium 实例,并通过暴力破解 DOM API 自动枚举 gadget 类(见下文部分)。 + +--- + +## 最近的原型污染 gadget 研究 (2022–2025) + +在 2023 年中,PortSwigger 研究人员发表了一篇论文,显示 *浏览器内置* 对象一旦被污染,就可以变成可靠的 XSS gadget。因为这些对象在 **每个** 页面上都存在,即使目标应用程序代码从未接触污染属性,你也可以获得执行权限。 + +示例 gadget(在所有 evergreen 浏览器 ≥ 2023-04 中有效): +```html + +``` +其他已确认在污染后有效的有用全局小工具(测试于2024-11): + +| 小工具类别 | 读取属性 | 实现的原始类型 | +|--------------|---------------|--------------------| +| `Notification` | `title` | 通过通知点击触发 `alert()` | +| `Worker` | `name` | 在专用 Worker 中执行 JS | +| `Image` | `src` | 传统的 `onerror` XSS | +| `URLSearchParams` | `toString` | 基于 DOM 的开放重定向 | + +请参阅 PortSwigger 论文以获取完整的 11 个小工具列表及关于沙箱逃逸的讨论。 + +--- + +## 突出的客户端 PP CVE(2023-2025) + +* **DOMPurify ≤ 3.0.8 – CVE-2024-45801** 攻击者可以在清理器初始化之前污染 `Node.prototype.after`,绕过 *SAFE_FOR_TEMPLATES* 配置文件,导致存储型 XSS。供应商通过使用 `Object.hasOwn()` 检查和 `Object.create(null)` 来修补内部映射。 +* **jQuery 3.6.0-3.6.3 – CVE-2023-26136 / CVE-2023-26140** `extend()` 可用于来自 `location.hash` 的构造对象,在浏览上下文中引入任意属性到 `Object.prototype`。 +* **sanitize-html < 2.8.1 (2023-10) 原型污染** 恶意属性列表如 `{"__proto__":{"innerHTML":""}}` 绕过了允许列表。 + +即使易受攻击的库 **仅存在于客户端**,结果 XSS 仍然可以通过反射参数、postMessage 处理程序或稍后呈现的存储数据进行远程利用。 + +--- + +## 现代防御措施 + +1. **尽早冻结全局原型**(理想情况下作为第一个脚本): +```javascript +Object.freeze(Object.prototype); +Object.freeze(Array.prototype); +Object.freeze(Map.prototype); +``` +请注意,这可能会破坏依赖于后期扩展的 polyfills。 +2. 使用 `structuredClone()` 而不是 `JSON.parse(JSON.stringify(obj))` 或社区的 "deepMerge" 代码片段 – 它忽略 setter/getter,并且不遍历原型链。 +3. 当您确实需要深度合并功能时,选择 **lodash ≥ 4.17.22** 或 **deepmerge ≥ 5.3.0**,它们具有内置的原型清理功能。 +4. 添加一个包含 `script-src 'self'` 和严格 nonce 的内容安全策略。虽然 CSP 不会阻止所有小工具(例如 `location` 操作),但它会阻止大多数 `innerHTML` 洗涤。 + ## 参考文献 +- [https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746](https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746) +- [https://blog.s1r1us.ninja/research/PP](https://blog.s1r1us.ninja/research/PP) +- [https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/#:\~:text=my%20challenge.-,Closure,-Closure%20Sanitizer%20has](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/) +- [https://portswigger.net/research/widespread-prototype-pollution-gadgets](https://portswigger.net/research/widespread-prototype-pollution-gadgets) +- [https://snyk.io/blog/dompurify-prototype-pollution-bypass-cve-2024-45801/](https://snyk.io/blog/dompurify-prototype-pollution-bypass-cve-2024-45801/) + - [https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746](https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746) - [https://blog.s1r1us.ninja/research/PP](https://blog.s1r1us.ninja/research/PP) - [https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/#:\~:text=my%20challenge.-,Closure,-Closure%20Sanitizer%20has](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/)