安全测试不是上线前的安检

很多团队把安全当成发布前的一道安检:功能都测完了,才让安全工程师拿扫描器扫一轮,扫出几个高危就修,扫不出来就放行。结果往往是高危漏洞反复出现,同一类问题换了个接口又来一遍。

真正的安全测试是一条贯穿开发全流程的防线:设计阶段做威胁建模,编码阶段跑静态扫描,联调阶段做动态测试,上线前再做一次汇总审计。越早发现问题,修复成本越低,这是安全界最朴素也最有效的规律。

在需求阶段修一个漏洞的成本,可能是上线后修它的几十分之一。
安全测试的四个层次
  • 威胁建模设计阶段,找出哪里可能被攻击。
  • SAST编码阶段,静态分析源码找隐患。
  • DAST联调阶段,黑盒扫描运行中的系统。
  • 审计上线前,汇总依赖、配置与边界检查。
安全测试示意:蓝色渐变背景中央玻璃质感发光放大镜,镜片内映出发光盾牌徽章,右侧悬浮更大的发光盾牌,周围散布柔和光斑与流线光效,扁平科技插画
安全测试像放大镜一样,把隐藏在代码与配置里的风险照出来。

先摸清攻击面:威胁建模

不知道哪里可能被攻击,扫描就是在盲扫。威胁建模做的事很简单:把系统拆开,标出每个入口、每份数据、每条信任边界,再问一句这里可能发生什么坏事。

常见思路是沿着数据流走一遍:用户从哪个入口进来、数据经过哪些组件、在哪个环节被存储和处理、哪些组件可信哪些不可信。重点盘这几个地方:对外暴露的接口、身份验证与授权逻辑、第三方回调、文件上传下载、数据导出。

# 一张简化的威胁模型记录
组件: 用户登录接口
入口: POST /api/login
信任边界: 公网 → 网关 → 认证服务 → 用户库
威胁: 暴力破解 | 会话劫持 | SQL 注入 | 响应体注入
缓解: 限流+验证码 | 短期令牌 | 参数化查询 | 输出编码
# 每条威胁都要落到一个可执行的缓解动作上

威胁建模的产出不是文档,而是一串可执行的测试用例:模型里识别出的每条威胁,都要对应一条验证它的安全用例。

SAST:在代码里找隐患

静态应用安全测试(SAST)不运行程序,直接分析源代码和依赖,擅长抓一类问题:危险函数的使用、注入点的构造、密码学误用、不安全的反序列化。它的价值在于能进 CI,每次提交都扫一遍,把问题拦在合并之前。

# 伪代码:一条典型的不安全 SQL 拼接
query = "SELECT * FROM users WHERE name = '" + userInput + "'"
# 扫描器会标记:未参数化的 SQL 拼接,存在注入风险
# 修复:使用参数化查询
query = "SELECT * FROM users WHERE name = ?"
execute(preparedStatement, [userInput])

用 SAST 有两点要注意:一是误报管理,扫描结果要有人工确认和标注,否则告警太多就会被无视;二是规则要与技术栈匹配,Java 的注入点、前端脚本的 XSS 点、数据层的脱敏要求各不相同。

DAST:在黑盒里试漏洞

动态应用安全测试(DAST)把系统跑起来,从外部像攻击者一样发送请求,观察响应:测参数注入、测越权、测文件上传、测认证绕过。它不关心代码怎么写的,只关心系统实际暴露出来的行为。

维度SASTDAST
视角白盒,看源码黑盒,看行为
时机编码阶段,每次提交联调阶段,系统可运行后
擅长的注入、密码学、代码坏味道越权、认证、配置、运行时问题
短板看不懂运行时的真实状态扫不到未暴露的代码路径

两者互补而不是替代:SAST 保证「写出来的代码没埋雷」,DAST 验证「跑起来的系统真的安全」。