NoSQL注入失效因不走SQL解析器,参数化查询对MongoDB等无效;须白名单校验字段、强制类型转换、禁用动态key,并用jsonschema约束结构,$regex和排序字段需严格过滤。

为什么直接套用SQL注入防护思路会失效
因为 NoSQL 注入不走 SQL 解析器,sqlalchemy 的参数化查询、cursor.execute("SELECT * FROM u WHERE name = %s", [user_input]) 这套机制对 MongoDB、Redis 等完全无效。MongoDB 的 find({name: request.args.get("q")}) 表面上像“拼接”,实际是 Python 字典构造——攻击者传入 {"$ne": ""} 这类 JSON-like 输入,就能绕过登录校验。关键不是“字符串要不要转义”,而是“用户输入是否被当作查询结构的一部分”。
在 PyMongo 中禁止将原始请求直接喂给 find() 或 update_one()
这是最常见也最危险的写法。只要用户能控制字典的 key 或 value 类型(比如把字符串变成嵌套 dict),就等于把查询逻辑交给了客户端。
实操建议:
- 永远用白名单校验字段名:只允许
["username", "email", "status"]这类已知安全字段出现在查询条件中,拒绝$where、$regex、$gt等操作符 key - 对值做类型强制:比如
user_id必须是ObjectId,用ObjectId(user_input)包裹并捕获InvalidId异常;手机号必须匹配^\d{11}$,否则直接 400 - 禁用动态 key 构造:不要写
{request.args.get("field"): value},改用 if/elif 显式分支,例如if field == "email": query = {"email": {"$regex": f"^{re.escape(value)}$"}}
用 jsonschema 对整个查询参数做结构约束
比手写 if 更可靠,尤其当接口支持复合查询(如 ?q={"status":"active","created_after":"2024-01-01"})时,靠正则或字符串判断极易漏掉深层操作符。
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
示例片段:
schema = {
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["active", "inactive"]},
"created_after": {"type": "string", "format": "date"},
},
"additionalProperties": False, # 关键:禁止 $ne、$or 等意外字段
}
验证后得到的 cleaned_query 才能进 collection.find()。注意:additionalProperties: False 必须设,否则攻击者加个 "$or": [...] 就绕过了。
警惕看似安全的“字符串拼接”场景:正则与排序字段
比如 collection.find({"name": {"$regex": user_input}}),即使 user_input 是纯字符串,也可能含 .* 或 ^ 导致性能崩塌或信息泄露;又如 sort=[(request.args.get("sort_by"), 1)],若未限制 sort_by 只能是 "created_at" 或 "score",攻击者可传 "email" 并配合索引暴力猜字段内容。
实操要点:
-
$regex值必须经re.escape()处理,且明确限定锚点(如^${escaped}$) - 排序字段用枚举映射:
SORT_MAP = {"newest": ("created_at", -1), "score": ("score", -1)},不在其中的一律忽略 - 所有涉及用户控制查询结构的地方,都要问一句:“这个输入会不会让数据库执行非预期的操作?”
真正难防的从来不是语法层面的注入,而是业务逻辑层面对“查询意图”的误判——比如允许按任意字段模糊搜索,却没意识到 password_hash 字段也可能被扫出来。

















