如何使用 Semgrep 扫描自定义 Erlang 插件的 SQL 注入?
解读
CouchDB 的核心查询语言并非 SQL,但国内不少企业会在 Erlang 插件里直接拼接 SQL 去访问外部关系型数据库(MySQL、PostgreSQL、SQL Server),以完成复杂报表或权限校验。这类插件一旦上线,就暴露在公网 5984 端口,成为攻击链最后一环。面试官问“用 Semgrep 扫 SQL 注入”,不是考你会不会写规则,而是看你是否能把CouchDB 的 Erlang 编码习惯、国内常见缺陷模式、CI 落地流程三件事串成闭环。答不到“规则怎么写”“误报怎么压”“增量怎么跑”,就会被判定为“只看过文档,没上过生产线”。
知识点
- CouchDB 插件加载机制:
_plugins路径下的.beam由 couch_epi 动态热加载,源码通常写在src/目录,编译后打进priv/。 - Erlang SQL 拼接三大危险 API:
epgsql:sql_query/2、mysql:query/2、odbc:sql_query/2;凡是出现"SELECT ... " ++ Var或io_lib:format("SELECT ... ~s", [Var])即为高危。 - Semgrep 对 Erlang 的支持:
官方规则库仅 20 条,必须写自定义metavariable-pattern才能识别 Erlang 的字符串拼接函数;同时打开generic模式可补漏。 - 国内合规要求:
《个人信息保护法》第 51 条要求**“自动化扫描+人工复核”双签字**,因此规则集必须输出 SARIF 给内部安全平台留痕。 - CI 集成要点:
GitLab-CI 里用returntocorp/semgrep-agent:erlang镜像,MR 阶段增量扫描、主干合并后全量扫描,质量红线设为“高危 0 容忍”。
答案
- 建立规则文件
couchdb-erlang-sql-inject.yaml,内容如下:rules: - id: couchdb-erlang-sql-inject languages: [erlang] severity: ERROR message: 外部 SQL 拼接未参数化,存在注入风险 patterns: - pattern-either: - pattern: $API:sql_query($CONN, "..." ++ $VAR) - pattern: $API:sql_query($CONN, io_lib:format("..." ++ "...", [$VAR])) - metavariable-regex: metavariable: $API regex: (epgsql|mysql|odbc) metadata: cwe: "CWE-89" owasp: "A03:2021" - 本地验证:
确认命中行号、变量名无误后,把规则 push 到内部 GitLab 的semgrep --config=couchdb-erlang-sql-inject.yaml src/ -o result.json --sarif.semgrep/目录,成为组织级规则。 - CI 集成:
.gitlab-ci.yml中增加:semgrep: stage: security image: returntocorp/semgrep-agent:erlang script: - semgrep-agent --config=.semgrep/ --baseline=$(git merge-base HEAD origin/main) artifacts: reports: sast: gl-sast-report.json only: - merge_requests - main - 误报降噪:
对单元测试目录test/加paths: exclude,对内部 ORM 封装函数加pattern-not-inside: mysafequery(...),把误报率压到 5% 以下,否则安全部会打回。 - 闭环处置:
扫描结果自动同步到内部缺陷跟踪系统,高危漏洞 24h 内修复、72h 内复测,并在 Release Note 里注明“已通过 Semgrep SQL 注入专项扫描”,满足国内监管审计要求。
拓展思考
- 如果插件里用 erlang-elixir 互调,SQL 语句在 Elixir 端拼接后通过 Port 传回 Erlang,Semgrep 原生无法跨语言,需要写 Elixir 规则并在同一 Pipeline 里串联,否则会出现“漏扫”。
- 对于参数化查询但 ORDER BY 列名动态传入的场景,上述规则会误报;可再加一条
metavariable-pattern识别<<" ORDER BY ", Column/binary >>并标记为“需人工复核”,实现精准分级。 - 国内头部云厂商已要求**“双引擎交叉验证”**,可在 Semgrep 之后再接 sobelow + CodeQL,形成 Erlang 层、SQL 层、业务逻辑层三维覆盖,把高危漏洞检出率提升到 99% 以上,同时把平均修复时间 MTTR 压缩到 8 小时以内,这才是面试官想听到的“端到端安全运营”闭环。