SQL注入扫描应选semgrep+SonarQube组合:semgrep抓拼接模式(需--error、排除tests/migrations、指定规则ID),SonarQube验语义上下文(须显式启用jdbc/hql安全规则并配齐binaries/sources路径)。

能,但必须选对工具、配对参数、卡准时机——用 sqlmap 直接扫 CI 构建产物会写脏数据、触发告警,根本不能进流水线;真正可落地产出的是 semgrep + SonarQube 组合,前者抓拼接模式,后者验语义上下文。
为什么 sqlmap 不适合放进 CI/CD
sqlmap 是渗透测试工具,不是 CI 工具。它发真实 HTTP 请求,可能:
- 修改生产数据库(哪怕只读,也可能触发审计日志或锁表)
- 被 WAF 拦截并封 IP,导致后续构建失败
- 无法断言“是否漏洞”,只输出概率性提示,CI 里没法做
if判断 - 扫描耗时长(默认 level=3),拖慢整个流水线
CI 要的是“无副作用、可重复、有明确退出码”的检查。所以别在 .gitlab-ci.yml 或 Github Actions 里写 sqlmap --batch --level=3 -r request.har —— 这不是集成,是埋雷。
semgrep 怎么配置才能真正阻断 SQL 拼接
semgrep 不依赖编译,纯靠 AST 匹配,适合代码提交前拦截。关键配置项必须带:
-
--error:匹配到规则就返回非 0 码,CI 自动标红失败 -
--exclude=tests/ --exclude=migrations/:否则SELECT * FROM user_test这类测试 SQL 会误报 -
--config=p/python.lang.security.insecure-sql-string-concatenation:这是最常用的一条开源规则,能捕获cursor.execute("SELECT * FROM " + table)
示例命令(GitLab CI 中):
semgrep --config=p/python.lang.security.insecure-sql-string-concatenation \ --error \ --exclude=tests/ \ --exclude=migrations/ \ --json --output=semgrep.json \ .
注意:--config 必须指向具体规则 ID,不能只写 p/python,否则不生效。
SonarQube 的 JDBC 安全规则为什么总不触发
不是 SonarQube 不行,是 Java 安全规则默认关闭,且三要素缺一不可:
-
sonar.java.rule.jdbc=security:必须显式启用,否则Statement.executeUpdate("UPDATE t SET v = " + input)静默通过 -
sonar.java.binaries=target/classes:没这个路径,AST 分析就跑不起来,所有安全规则失效 -
sonar.sources=src/main/java:源码路径不对,上下文识别失败,@Query("SELECT * FROM u WHERE name = '" + name + "'")就漏掉
GitLab CI 中正确写法是设环境变量:
SONAR_SCANNER_OPTS="-Dsonar.java.rule.jdbc=security -Dsonar.java.rule.hql=security -Dsonar.java.binaries=target/classes"
千万别写成 sonar-scanner -Dsonar.java.rule.jdbc=security —— SonarScanner 5.0+ 明确不支持命令行传 rule.* 参数。
ORM 场景下最容易被忽略的注入点
用了 Django ORM 或 SQLAlchemy 并不等于免疫。真正危险的是这些“看似安全”的写法:
-
Model.objects.raw(f"SELECT * FROM {table_name}"):表名无法参数化,必须白名单校验,semgrep能抓到 -
queryset.extra(where=[f"user_id = {user_id}"]):extra()绕过 ORM 参数绑定,SonarQube在sonar.java.rule.jdbc=security开启后能识别 -
filter(**{request.GET.get('field'): value}):动态字段名未校验,semgrep规则python.lang.security.dynamic-field-in-filter可覆盖
这些都不是传统意义上的“字符串拼接”,但仍是 SQL 注入。工具链必须覆盖到这一层,否则扫描结果就是假阳性洼地。

















