MongoDB无SQL注入但存在查询注入,根源在于Python代码将未校验的用户输入直接拼入查询字典;必须对所有外部输入做类型/结构校验、禁用$where/$regex/$expr等高危操作符、使用bson模块防护、严格管控连接权限。

MongoDB 本身不解析 SQL 式字符串,所以没有传统 SQL 注入,但只要 Python 代码把用户输入直接拼进查询字典,就等于给攻击者开了后门——这不是数据库问题,是你的 find()、findOne() 或 update_one() 调用方式错了。
别让 user_input 直接进 query dict
常见错误写法:db.users.find({"username": request.json.get("username")})。攻击者传 {"$ne": ""},就能绕过登录校验。
- 所有外部输入(
request.args、request.json、request.form)必须先做类型和结构校验,再进查询 - 字符串字段绝不能接受 dict / list / None;数字字段必须用
int()或float()显式转换并捕获异常 - 用
isinstance(value, str)比type(value) == str更安全,避免被伪造类型绕过 - 禁止对未清洗的输入调用
json.loads()—— 这可能触发原型污染或栈溢出
禁用高危操作符:$where、$regex、$expr
$where 允许执行任意 JavaScript,$regex 若不转义可导致 DoS 或信息泄露,$expr 可组合任意表达式——三者都不该接收原始用户输入。
- 搜索场景要用
$regex?先转义特殊字符:re.escape(q),再套进{"name": {"$regex": escaped_q, "$options": "i"}} - 绝对不要写
{"$where": "this.password == '" + password + "'"}这类拼接 - 用 PyMongo 时,检查是否启用了
allow_disk_use=False(防止 $where 大量读磁盘) - MongoDB 6.0+ 默认禁用
$where,但旧版本或自定义配置可能仍开启,需确认mongod启动参数不含--javascriptEnabled
用 PyMongo 的 bson 模块做基础防护
bson 提供了轻量级校验能力,比如 bson.ObjectId() 可防 ObjectId 注入,bson.regex.Regex() 可封装可控正则。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 查用户 ID?用
try: ObjectId(user_id) except InvalidId: abort(400) - 构造正则查询?用
Regex(pattern=escaped_q, flags="i"),而不是手拼 dict - 避免手动构造
{"$in": user_list}—— 先验证user_list是字符串列表,且每个元素长度 ≤ 64 -
bson.encode()不用于防御,但bson.decode()若用于解析用户上传的 BSON 文件,必须设options=bson.CodecOptions(document_class=OrderedDict)防止对象注入
连接与权限层面不能省
即使代码层全防住了,裸奔的 MongoDB 实例仍可能被扫端口直接拖库。
立即学习“Python免费学习笔记(深入)”;
- 启动
mongod时必须加--auth,且首次连接后立即创建管理员用户,禁用admin数据库空密码 - 应用连接串里明确指定
authSource=admin和最小权限数据库,例如mongodb://user:pass@host/db?authSource=admin - 生产环境关闭
bind_ip=127.0.0.1,配合防火墙只放行应用服务器 IP - 定期检查
db.system.users.find(),删掉无用账号;禁用root角色,改用readWrite+ 自定义角色
Motor 或 Beanie,它们的 .find() 方法仍会原样转发 dict 查询——框架不替你防注入,只帮你发请求。

















