本文目录导读:

可以,但有限度。
Bandit 是一个针对 Python 代码的静态分析工具,它主要检查源代码中是否存在模式上不安全的调用,对于 SQL 注入,它能够检测出最明显、最经典的写法,但对复杂或动态拼接的情况则无能为力。
Bandit 检测 SQL 注入的原理
Bandit 通过模式匹配来查找代码中使用了某些特定的、已知容易导致 SQL 注入的函数或方法。
它会检查你是否:
- 直接使用字符串格式化或字符串拼接来构建 SQL 查询。
- 使用了不安全的数据库驱动方法(如
raw_input、cursor.execute配合拼接字符串)。
典型能检测到的例子:
# Bandit 会报 B608: hardcoded SQL expression
def unsafe_query(user_input):
query = "SELECT * FROM users WHERE name = '%s'" % user_input # 字符串格式化
cursor.execute(query)
# 或者
query = f"SELECT * FROM users WHERE name = '{user_input}'" # f-string
cursor.execute(query)
它会报错为:
B608: Test for SQL injection
Bandit 的局限性(为什么说“有限度”)
Bandit 是静态分析,它不会实际执行代码,也不会追踪变量的数据流,以下情况它无法检测:
- 复杂拼接:变量经过多层函数传递后再组装。
- ORM 使用不当:Django ORM 的
extra()或raw()方法。 - 编码后的注入:经过 Base64、URL 编码或加密后的输入。
- 动态表名、列名:如果表名或列名也是变量拼接,Bandit 可能忽略。
- 参数化查询但忘记传参:例如只写了
cursor.execute(sql)但sql里仍有%s但没传参数(Bandit 可能误报或漏报)。
无法检测的例子:
def complex_query(user_input):
# 经过函数处理
safe_input = some_encoding(user_input)
query = "SELECT * FROM users WHERE name = '" + safe_input + "'"
# Bandit 可能不会报错,因为它无法静态分析 some_encoding 是否安全
实际使用建议
| 场景 | Bandit 表现 | 建议 |
|---|---|---|
| 直接字符串拼接 | 强 | 能检测到,可封堵最低级错误 |
| Django/Flask ORM 使用 | 弱 | 需要配合 Django 的 SECURE_SQL_INJECTION 规则或手动审查 |
| 多层调用、编码混淆 | 无效 | 需要动态分析或人工代码审计 |
| 参数化查询 | 无告警(正确写法) | 鼓励团队使用参数化查询,Bandit 不会报错 |
最佳实践:
- 先用 Bandit 做快速扫描(
bandit -r your_project/),修复它报的所有B608。 - 然后 配合 SQLAlchemy / Django ORM 参数化查询 从根源避免拼接。
- 最后 使用 动态应用安全测试 (DAST) 工具(如 sqlmap、Burp Suite)对实际运行的应用进行渗透测试。
- ✅ 能检测:直接字符串拼接、 格式化、f-string 构造 SQL 的明显案例。
- ❌ 不能检测:复杂逻辑、ORM 滥用、经过编码或函数处理后的注入。
- 🚀 :Bandit 是防 SQL 注入的第一道防线(静态代码扫描),但不能替代参数化查询和动态安全测试。