安全测试指南

安全测试方法对比

类型全称工作方式常用工具
SAST静态应用安全测试不运行代码,分析源代码Semgrep、CodeQL、SonarQube
DAST动态应用安全测试对运行中的应用发起攻击(黑盒)OWASP ZAP、Burp Suite、Nuclei
SCA软件成分分析扫描依赖中已知 CVESnyk、Dependabot、OWASP Dependency-Check
密钥扫描检测代码/历史中的凭据扫描 git 历史和文件的模式匹配GitLeaks、TruffleHog、GitHub Secret Scanning

CI 安全流水线

# GitHub Actions 安全检查 jobs: security: steps: # 1. 密钥检测(最快,最先失败) - name: 扫描密钥 uses: gitleaks/gitleaks-action@v2 # 2. 依赖漏洞扫描 - name: Snyk 扫描 uses: snyk/actions/node@master with: args: --severity-threshold=high # 3. SAST——Semgrep - name: Semgrep SAST uses: semgrep/semgrep-action@v1 with: config: p/owasp-top-ten # 4. 容器镜像扫描 - name: Trivy 镜像扫描 uses: aquasecurity/trivy-action@master with: image-ref: myapp:${{ github.sha }} severity: CRITICAL,HIGH exit-code: 1

安全回归测试

// 与功能代码同步编写安全测试,防止回归 describe('认证安全', () => { it('拒绝过期的 JWT', async () => { const expiredToken = generateToken({ userId: 1 }, { expiresIn: '-1s' }); await request(app) .get('/api/profile') .set('Authorization', `Bearer ${expiredToken}`) .expect(401); }); it('防止 IDOR:用户不能访问他人数据', async () => { const user1Token = await loginAs('[email protected]'); await request(app) .get('/api/users/user2-id/orders') .set('Authorization', `Bearer ${user1Token}`) .expect(403); }); it('登录尝试频率限制', async () => { for (let i = 0; i < 10; i++) { await request(app).post('/api/login').send({ email: 'x', password: 'x' }); } const res = await request(app).post('/api/login').send({ email: 'x', password: 'x' }); expect(res.status).toBe(429); // 请求过多 }); });