查询 28 次,耗时 0.2717 秒

把大模型接入代码审计流水线:从发现漏洞到人工复核的可靠实践指南

speedhacker

New member

speedhacker Rep
0
0
0
Rep
0
speedhacker Vouches
Vouches
0
5 MONTHS
5 5 MONTHS OF SERVICE
speedhacker 获得
0
0
0
获得
0
speedhacker 凭证
0
0
0
凭证
0
主题
8
点赞
0
HakB
5 月
在社区成长 5 月
LEVEL 100 XP
 
一、背景:为什么安全团队不能只把代码丢给大模型

在代码审计、漏洞分流和安全运营中,大模型可以帮助分析复杂调用链、解释扫描结果、生成复现步骤草稿,并把分散的日志和提交记录整理成可读结论。但它并不是可靠的“自动审计员”:模型可能漏报、误报,可能误解框架语义,也可能把测试代码当成生产代码。更严重的是,如果把源码、日志、密钥或客户数据直接发送到不受控的外部服务,还会产生数据泄露风险。

比较稳妥的做法是将人工智能放在“辅助分析和排序”位置,而不是让它直接决定漏洞是否存在。静态分析工具负责尽可能确定地发现模式,大模型负责解释上下文、合并重复告警、补充人工检查清单,最终由安全人员依据代码、测试结果和业务边界确认结论。本文以本地靶场或自有测试仓库为例,搭建一条“规则扫描—AI 分析—人工复核—回归验证”的安全流水线。

二、适用场景与总体原理

本文适合以下场景:

1. 对自有项目进行提交前安全检查;
2. 对 Semgrep、Bandit、Gitleaks 等工具产生的结果进行去重和分级;
3. 分析本地应用日志,归纳可能的攻击链和检测缺口;
4. 为开发者生成可验证的修复建议和单元测试思路。

推荐的处理链如下:

代码或日志输入 → 脱敏 → 规则工具初筛 → 截取必要上下文 → 大模型结构化分析 → 人工确认 → 本地测试 → 修复与回归扫描。

其中有三个关键原则。第一,模型输入要最小化,只提供完成判断所需的代码片段和元数据。第二,要求模型输出证据、假设和不确定性,而不是只输出“有漏洞”或“没有漏洞”。第三,所有高风险结论都必须通过代码追踪、测试用例、日志证据或安全工具再次验证。

三、前置条件

建议准备一台隔离的本地实验环境,使用专门的测试仓库,不要直接导入生产源码。软件可以包括:

- Python 3.10 或更高版本;
- Git;
- Semgrep,用于多语言规则扫描;
- Bandit,用于 Python 常见安全问题检查;
- Gitleaks,用于发现可能的密钥和令牌;
- 一个经过组织批准的模型服务,或部署在内网的模型;
- jq,用于处理 JSON 结果。

初始化示例环境:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip bandit
python -m pip install semgrep

如果系统不允许从公网安装依赖,应使用经过内部审核的镜像或离线包。测试项目应当是自己编写的示例项目、公开授权的训练靶场,或明确获得许可的代码库。不要对陌生网站、第三方仓库或生产接口进行扫描和验证。

四、准备一个本地审计样例

在测试仓库中创建 app.py:

from flask import Flask, request
import sqlite3

app = Flask(__name__)

def find_user(name):
conn = sqlite3.connect("demo.db")
query = "SELECT id, name FROM users WHERE name = '" + name + "'"
return conn.execute(query).fetchall()

@app.get("/user")
def user():
name = request.args.get("name", "")
return {"items": find_user(name)}

这个示例只用于本地学习。它包含一个需要审计的输入拼接点,但是否构成可利用漏洞仍应结合数据库驱动、输入流向和部署方式判断。不要把验证过程扩展到任何不属于自己的系统。

先运行基础扫描:

semgrep --config p/python app.py --json --output semgrep.json
bandit -r . -f json -o bandit.json

gitleaks detect --source . --report-format json --report-path gitleaks.json

不同版本的规则集和输出字段可能存在差异,应以本地命令的实际结果为准。扫描结果不应直接作为最终漏洞报告,而应保留规则编号、文件路径、行号、匹配代码和工具版本,方便后续复核。

五、设计给大模型的审计输入

不要把整个仓库无差别发送给模型。可以编写一个小脚本,从扫描结果中提取告警位置上下各 30 至 80 行代码,再加入语言、框架、调用入口、数据流和已知测试结果。对于日志分析,则只提供脱敏后的时间、事件类型、状态码、请求路径模板和关联 ID,删除 Cookie、Authorization、手机号、邮箱、IP 之外的敏感标识,并根据组织政策处理 IP 地址。

推荐让模型使用固定 JSON 格式返回结果,例如:

{
"status": "confirmed|likely|uncertain|false_positive",
"severity": "critical|high|medium|low|info",
"evidence": ["指出具体代码或日志证据"],
"data_flow": "描述输入如何到达敏感操作",
"assumptions": ["列出尚未验证的前提"],
"safe_validation": ["只允许在本地或授权靶场进行的验证"],
"remediation": ["给出最小修复建议"],
"regression_tests": ["建议增加的测试"]
}

提示词可以这样设计:

“你是代码审计辅助分析器。只能依据提供的代码、扫描结果和上下文作出判断,不得猜测不存在的配置。请区分已证实事实、合理推断和未知信息。不要生成针对真实系统的攻击步骤,不要输出绕过认证、批量探测或破坏性操作。重点分析输入来源、敏感汇、编码或参数化处理、权限检查、异常分支和可测试的修复方案。若证据不足,必须返回 uncertain,并说明需要人工确认的内容。严格输出指定 JSON。”

这里的重点不是把提示词写得很长,而是约束模型不要把推测伪装成事实。模型输出中必须保留原始告警编号和代码位置,避免后续整理时丢失证据。

六、分步骤实践:从告警到结论

第一步,确认告警是否落在真实执行路径。

查看入口函数、路由绑定、调用关系和配置文件。一个未被调用的旧函数,风险通常不同于在线接口;测试夹具、示例代码和生产模块也应分别标注。可以使用 Git grep 或 IDE 的引用查找功能辅助确认:

git grep -n "find_user" -- '*.py'
git log -L 5,8:app.py

第二步,核对数据流和边界。

对于数据库、模板、命令执行、文件路径、反序列化等问题,需要确认外部输入是否经过可信的校验和安全 API。例如 SQL 查询应使用参数绑定,而不是通过字符串拼接。修复示例:

def find_user(name):
conn = sqlite3.connect("demo.db")
query = "SELECT id, name FROM users WHERE name = ?"
return conn.execute(query, (name,)).fetchall()

这个修复仍不代表所有问题都消失,还需要确认数据库权限、错误信息、分页限制和业务授权是否合理。AI 可以列出检查项,但不能替代这些检查。

第三步,要求模型进行反证分析。

除了“为什么可能存在问题”,还要让模型回答“什么证据会证明它不是问题”。例如:输入是否在更早位置被严格约束为枚举值?是否使用了安全的查询 API?告警是否只存在于不可达代码?反证分析有助于减少规则扫描和模型叠加造成的误报。

第四步,在本地进行非破坏性验证。

可以使用单元测试验证参数绑定是否生效,检查特殊字符是否被当作数据处理,而不是构造攻击载荷。测试应使用虚构数据和临时数据库,例如:

import sqlite3

def test_find_user_treats_input_as_data(tmp_path):
db = tmp_path / "demo.db"
conn = sqlite3.connect(db)
conn.execute("create table users(id integer, name text)")
conn.execute("insert into users values(1, 'alice')")
conn.commit()
conn.close()

测试重点是验证查询结果、异常行为和数据完整性,而不是对外部目标发起请求。完成修复后重新运行 Semgrep、Bandit 和相关测试,并在合并请求中保存前后差异。

第五步,建立人工复核结论。

建议把每条告警记录为:工具来源、首次发现时间、代码位置、影响资产、证据、置信度、严重性依据、修复提交、回归测试和复核人。AI 生成的内容只能作为草稿,人工必须重新阅读关键代码,并确认严重性是否符合组织的风险矩阵。

七、将 AI 用于安全运营时的注意事项

如果分析的是日志,模型更适合做事件归并、时间线整理和初步分类。例如把同一关联 ID 下的登录失败、权限变更和异常下载整理为一个待调查事件。但应先在 SIEM 或规则引擎中完成字段解析、时间校正和访问控制,模型不应直接接收原始密钥、会话令牌或完整请求体。

可采用分级策略:低风险事件自动摘要;中风险事件生成调查建议并等待分析员确认;高风险事件只允许模型提供证据索引,封禁账号、隔离主机、修改防火墙等动作必须经过明确授权和二次确认。任何“自动响应”都应有回滚机制、审计日志和紧急停止开关。

八、风险与注意事项

1. 数据泄露:源码、日志和提示内容可能包含密钥、个人信息或内部拓扑。发送前应做脱敏,并确认服务商的数据保留、训练使用和访问控制政策。
2. 提示注入:代码注释、日志字段或提交信息可能包含“忽略之前指令”等恶意文本。模型应把这些内容视为不可信数据,不能当作系统指令执行。
3. 幻觉和过度自信:模型可能引用不存在的函数、规则或 CVE。所有外部编号、版本影响和修复建议都必须人工核验。
4. 依赖污染:自动生成的补丁可能引入不必要依赖或降低校验强度。补丁必须经过代码审查、测试和依赖扫描。
5. 权限扩大:给模型配置写仓库、执行命令或关闭安全控制的权限会增加供应链风险。默认采用只读、最小权限和隔离执行。
6. 版本漂移:模型、规则集和扫描器升级后,结果可能变化。应记录版本,并用固定测试样例做回归比较。

九、常见问题

问:大模型能否替代 SAST 工具?
答:不建议。规则工具输出稳定、可重复,适合门禁;模型更适合解释上下文、归并告警和提出测试思路。两者应互相校验。

问:模型说“高危”,是否可以直接创建高优先级工单?
答:不能仅凭模型结论。至少要确认可达性、数据流、权限边界、影响范围和复现证据。证据不足时应标记为待确认,而不是直接定级。

问:扫描整个仓库是不是更准确?
答:不一定。无关文件会增加上下文噪声和数据泄露面。应先用工具定位,再提供最小必要上下文,并在需要时分批补充调用链。

问:如何评价这套方案是否有效?
答:可以统计误报率、漏报复核数、人工处理时间、重复告警比例、修复回归通过率和模型建议被采纳的比例。不要只看模型生成了多少文字。

十、总结

可靠地使用人工智能做安全工作,核心不是寻找一个“万能审计提示词”,而是建立证据链和责任边界。工具负责发现可重复的模式,模型负责整理复杂上下文,人工负责确认事实和风险,测试负责证明修复没有破坏功能。对于代码审计,建议从本地样例和只读分析开始,采用脱敏、结构化输出、版本记录、人工复核和回归扫描;对于安全运营,则应限制模型权限,禁止其直接执行高影响动作。只要把 AI 放在适当的位置,它可以显著降低告警理解和文档整理成本,同时不会把未经验证的推测误当成安全结论。
 
顶部