FlawOpen

flawopen.com/参考资料/FastAPI SQL 注入

FastAPI 默认会阻止 SQL 注入吗?

Python 与 API 指南
简要回答

Pydantic 会检查值是否符合声明的输入类型;它不会重写 SQL,也不会把 Python 字符串自动变成数据库参数。经过验证的 name: str 仍然是调用者提供的文本。可以把验证想成检查包裹上的标签:它确认收到的值属于哪种类型;参数绑定则像把值封装在 SQL 指令之外。保持 SQL 模板固定,并通过 SQLAlchemy 单独传递值。

FastAPI 中有风险与安全的写法

有风险:插值会改变 SQL 文本
# A string type check does not make input safe inside SQL syntax
@app.get("/users")
def get_users(name: str, db: Session = Depends(get_db)):
    query = text(f"SELECT * FROM users WHERE name = '{name}'")
    return db.execute(query).fetchall()
安全:SQLAlchemy 单独绑定该值
# :name is a bind parameter; the value is passed separately
@app.get("/users")
def get_users(name: str, db: Session = Depends(get_db)):
    query = text("SELECT * FROM users WHERE name = :name")
    return db.execute(query, {"name": name}).fetchall()

参数绑定不涵盖什么

绑定参数代表数据值,而不是表名、列名、SQL 运算符或排序方向。如果请求必须选择排序字段,应把选项映射到固定的 SQLAlchemy 列表达式白名单中;切勿将原始请求字符串拼接进 SQL。参数化也不能取代授权:限制调用者可以读取的行,并让数据库账号仅拥有该端点所需的权限。

防护检查清单

参考资料

另请参阅 SQL 注入(CWE-89):原理与各编程语言的防护方法 — flawopen.com GORM Raw SQL:防止 Go 中的 SQL 注入 转义引号足以防止 SQL Injection 吗? 使用 ORM 足以防止 SQL 注入吗? Knex.js 能防止 SQL 注入吗? MyBatis ${} 与 #{}:防止 SQL Injection MySQLi 与 PDO:安全使用预处理语句