You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中如何通过数组查询参数构造NoSQL注入?

Flask中构造MongoDB NoSQL注入的问题解答

Flask完全支持构造MongoDB NoSQL注入,你遇到的问题只是参数解析方式的差异,而非语言本身限制——NoSQL注入本质是应用将用户可控输入直接作为查询条件使用,和开发语言无关,Python/Flask、NodeJS、PHP等都可能存在这类漏洞。

问题原因

Flask的request.args默认会将URL参数解析为扁平的键值对,不会自动识别name["$ne"]这种格式的嵌套结构。当你访问http://localhost:3214/get_test?name["$ne"]=test时,实际拿到的参数键是字符串"name['$ne']",而非嵌套的name.$ne,所以用request.args.get("name")会返回None。

解决方法:手动解析嵌套参数

要实现预期的嵌套查询结构,你需要手动解析参数键,将类似name[$ne]的格式转换为MongoDB可识别的嵌套字典。示例代码如下:

from flask import Flask, request
from pymongo import MongoClient

app = Flask(__name__)
client = MongoClient("mongodb://localhost:27017/")
db = client["test_db"]
collection = db["test_col"]

def parse_nested_query(args):
    query = {}
    for raw_key, value in args.items():
        # 处理形如key[operator]的参数格式
        if "[" in raw_key and "]" in raw_key:
            main_field, op = raw_key.split("[", 1)
            op = op.rstrip("]")
            # 构建嵌套查询条件
            if main_field not in query:
                query[main_field] = {}
            query[main_field][op] = value
        else:
            query[raw_key] = value
    return query

@app.route("/get_test")
def get_test():
    # 解析用户传入的参数为MongoDB查询格式
    user_query = parse_nested_query(request.args)
    # 直接将用户查询传入MongoDB(这就是存在注入风险的写法)
    result = collection.find_one(user_query)
    return str(result) if result else "No data found"

if __name__ == "__main__":
    app.run(port=3214)

当你访问http://localhost:3214/get_test?name[$ne]=test时,parse_nested_query会生成{'name': {'$ne': 'test'}},直接传入find_one后,就会返回所有name不等于test的文档——这就是典型的NoSQL注入场景。

补充说明

  • request.args.to_dict()同样返回扁平结构,无法直接得到嵌套字典,必须手动处理。
  • mongo-query-manager这类库通常需要特定的参数格式配合,手动解析反而更直接可控。
  • 实际开发中绝对禁止直接将用户输入作为MongoDB查询条件,必须对输入进行过滤、验证,或使用参数化查询方式避免注入风险。

内容的提问来源于stack exchange,提问作者Dump Eldor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:55:19