GitLab教程(11): 安全扫描与漏洞管理

GitLab提供了完整的安全扫描功能,可以在CI/CD流程中自动检测代码漏洞。本文将介绍GitLab的各种安全扫描工具和漏洞管理方法。

安全扫描类型

# GitLab支持的安全扫描类型

1. SAST (Static Application Security Testing)
   - 静态代码分析
   - 检测代码中的安全漏洞
   - 支持多种语言

2. DAST (Dynamic Application Security Testing)
   - 动态应用测试
   - 对运行中的应用进行扫描
   - 检测运行时漏洞

3. Dependency Scanning
   - 依赖项漏洞扫描
   - 检测第三方库的已知漏洞

4. Container Scanning
   - 容器镜像扫描
   - 检测Docker镜像中的漏洞

5. Secret Detection
   - 密钥泄露检测
   - 检测代码中的敏感信息

6. License Compliance
   - 许可证合规检查
   - 检测依赖项的许可证类型

启用安全扫描

# 使用GitLab模板快速启用所有扫描

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml
  - template: Security/License-Scanning.gitlab-ci.yml

stages:
  - build
  - test
  - security

# 所有扫描Job将自动添加到security阶段

SAST - 静态代码分析

# 启用SAST
include:
  - template: Security/SAST.gitlab-ci.yml

# 支持的语言和工具
# - JavaScript/TypeScript: Semgrep, NodeJsScan
# - Python: Semgrep, Bandit
# - Java: Semgrep, SpotBugs
# - Go: Semgrep, Gosec
# - Ruby: Brakeman
# - PHP: PHPStan
# - C/C++: Flawfinder
# - .NET: Security Code Scan

# 自定义SAST配置
variables:
  SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
  SAST_EXCLUDED_ANALYZERS: "gosec, flawfinder"
  SEARCH_MAX_DEPTH: 4

# SAST扫描输出
$ Running SAST analyzers
[INFO] Running Semgrep analyzer...
[INFO] Found 3 vulnerabilities

Vulnerability Report:
┌────────┬──────────────────────────────────┬──────────┬────────────┐
│ ID     │ Description                      │ Severity │ File       │
├────────┼──────────────────────────────────┼──────────┼────────────┤
│ SQL-01 │ SQL Injection vulnerability      │ Critical │ db/user.js │
│ XSS-02 │ Cross-site scripting (XSS)       │ High     │ view/index │
│ SEC-03 │ Hardcoded credentials            │ Medium   │ config.js  │
└────────┴──────────────────────────────────┴──────────┴────────────┘

Dependency Scanning

# 启用依赖扫描
include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml

# 支持的包管理器
# - npm/yarn (JavaScript)
# - pip/pipenv/poetry (Python)
# - Maven/Gradle (Java)
# - Go modules
# - Bundler (Ruby)
# - Composer (PHP)
# - NuGet (.NET)
# - Conan (C++)

# 配置变量
variables:
  DS_EXCLUDED_PATHS: "spec, test, tests"
  DS_EXCLUDED_ANALYZERS: "gemnasium-python"

# 扫描输出示例
$ Running dependency scanning...
[INFO] Analyzing package-lock.json
[INFO] Found 5 vulnerable dependencies

Vulnerable Dependencies:
┌────────────────────┬─────────────┬──────────┬────────────────┐
│ Package            │ Version     │ Severity │ Fixed Version  │
├────────────────────┼─────────────┼──────────┼────────────────┤
│ lodash             │ 4.17.15     │ Critical │ 4.17.21        │
│ axios              │ 0.21.0      │ High     │ 0.21.2         │
│ express            │ 4.17.1      │ Medium   │ 4.18.2         │
│ minimist           │ 1.2.5       │ Medium   │ 1.2.6          │
│ moment             │ 2.29.1      │ Low      │ 2.29.4         │
└────────────────────┴─────────────┴──────────┴────────────────┘

Secret Detection

# 启用密钥检测
include:
  - template: Security/Secret-Detection.gitlab-ci.yml

# 检测的密钥类型
# - AWS Access Keys
# - Azure Service Principals
# - GCP Service Account Keys
# - GitHub Personal Access Tokens
# - GitLab Personal Access Tokens
# - Slack Tokens
# - SSH Private Keys
# - Database Passwords
# - API Keys

# 配置
variables:
  SECRET_DETECTION_EXCLUDED_PATHS: "tests/fixtures"
  SECRET_DETECTION_HISTORIC_SCAN: "true"  # 扫描历史提交

# 扫描输出
$ Running secret detection...
[INFO] Scanning current commit...
[ALERT] Found 2 secrets

Secrets Found:
┌──────────────────────────┬────────────────────┬──────────┐
│ Type                     │ File               │ Line     │
├──────────────────────────┼────────────────────┼──────────┤
│ AWS Access Key           │ config/aws.js      │ 15       │
│ GitHub Personal Token    │ scripts/deploy.sh  │ 8        │
└──────────────────────────┴────────────────────┴──────────┘

[WARNING] Secrets should not be committed to the repository!
          Use environment variables or a secrets manager.

Container Scanning

# 启用容器扫描
include:
  - template: Security/Container-Scanning.gitlab-ci.yml

variables:
  CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  CS_SEVERITY_THRESHOLD: HIGH  # 只报告HIGH和CRITICAL

# 需要先构建并推送镜像
stages:
  - build
  - scan

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

container_scanning:
  stage: scan
  variables:
    CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

# 使用Trivy替代默认扫描器
container_scanning:
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  script:
    - trivy image --format json --output trivy-report.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  artifacts:
    reports:
      container_scanning: trivy-report.json
  allow_failure: true

# 扫描输出
$ trivy image registry.gitlab.com/mygroup/myproject:abc123

registry.gitlab.com/mygroup/myproject:abc123 (alpine 3.18)

Total: 12 (CRITICAL: 2, HIGH: 3, MEDIUM: 5, LOW: 2)

┌──────────────┬────────────────┬──────────┬────────────────┐
│   Library    │ Vulnerability  │ Severity │ Fixed Version  │
├──────────────┼────────────────┼──────────┼────────────────┤
│ openssl      │ CVE-2024-1234  │ CRITICAL │ 3.1.5-r0       │
│ libcurl      │ CVE-2024-2345  │ CRITICAL │ 8.5.0-r0       │
│ busybox      │ CVE-2024-3456  │ HIGH     │ 1.36.1-r7      │
└──────────────┴────────────────┴──────────┴────────────────┘

DAST - 动态应用测试

# 启用DAST
include:
  - template: DAST.gitlab-ci.yml

variables:
  DAST_WEBSITE: https://staging.example.com
  DAST_FULL_SCAN_ENABLED: "true"

# 需要先部署应用
stages:
  - deploy
  - dast

deploy-staging:
  stage: deploy
  script:
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com

dast:
  stage: dast
  needs: [deploy-staging]
  variables:
    DAST_WEBSITE: https://staging.example.com

# DAST检测的漏洞类型
# - SQL Injection
# - Cross-Site Scripting (XSS)
# - Cross-Site Request Forgery (CSRF)
# - Insecure Headers
# - SSL/TLS Issues
# - Authentication Issues
# - Session Management Issues

# 使用OWASP ZAP进行扫描
dast:
  image:
    name: owasp/zap2docker-stable
    entrypoint: [""]
  script:
    - zap-baseline.py -t https://staging.example.com -r zap-report.html
  artifacts:
    paths:
      - zap-report.html
  allow_failure: true

漏洞报告

# 查看漏洞报告
# Project > Security & Compliance > Vulnerability Report

# 漏洞仪表盘显示
┌─────────────────────────────────────────────────────────────┐
│  Vulnerability Report                                       │
├─────────────────────────────────────────────────────────────┤
│  Total: 23                                                  │
│  ├── Critical: 2 (需要立即处理)                             │
│  ├── High: 5                                                │
│  ├── Medium: 10                                             │
│  ├── Low: 6                                                 │
│  └── Unknown: 0                                             │
│                                                             │
│  By Scanner:                                                │
│  ├── SAST: 8                                                │
│  ├── Dependency Scanning: 12                                │
│  ├── Container Scanning: 3                                  │
│  └── Secret Detection: 0                                    │
└─────────────────────────────────────────────────────────────┘

# 漏洞状态
# - Detected: 新发现
# - Confirmed: 已确认
# - Dismissed: 已忽略(误报或不适用)
# - Resolved: 已修复

在MR中显示安全报告

# MR会自动显示新增的安全问题

# MR安全报告显示
┌─────────────────────────────────────────────────────────────┐
│  Security scanning detected 2 new potential vulnerabilities │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  SAST                                                       │
│  ├── ⚠ SQL Injection in db/queries.js:45                   │
│  │   Severity: Critical                                     │
│  │   [Show details] [Dismiss] [Create issue]                │
│  │                                                          │
│  └── ⚠ Hardcoded password in config/db.js:12               │
│      Severity: High                                         │
│      [Show details] [Dismiss] [Create issue]                │
│                                                             │
│  Dependency Scanning                                        │
│  └── No new vulnerabilities                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

# 配置MR安全检查
# Project > Settings > Merge requests
# Security approvals: 勾选需要安全批准

安全策略

# 配置安全策略 (需要Ultimate版)
# Group/Project > Security & Compliance > Policies

# 扫描执行策略示例
# .gitlab/security-policies/policy.yml
name: Required Security Scans
description: Enforce security scanning on all MRs
enabled: true
rules:
  - type: pipeline
    branches:
      - main
      - develop
actions:
  - scan: sast
  - scan: dependency_scanning
  - scan: secret_detection

# 扫描结果策略
name: Block Critical Vulnerabilities
description: Block MR merge if critical vulnerabilities found
enabled: true
rules:
  - type: scan_finding
    scanners:
      - sast
      - dependency_scanning
    vulnerabilities_allowed: 0
    severity_levels:
      - critical
    vulnerability_states:
      - detected
actions:
  - type: require_approval
    approvals_required: 1
    user_approvers:
      - security-team

修复建议

# 自动修复依赖漏洞
# MR页面 > Security > Dependency Scanning
# 点击 "Create merge request to remediate"

# 自动生成的MR会更新有漏洞的依赖版本

# 手动修复示例

# 1. SQL注入修复
# 修复前
const query = `SELECT * FROM users WHERE id = ${userId}`;

# 修复后 (使用参数化查询)
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);

# 2. 依赖更新
npm audit fix
# 或
npm update lodash@4.17.21

# 3. 移除硬编码密钥
# 修复前
const apiKey = 'sk-1234567890abcdef';

# 修复后 (使用环境变量)
const apiKey = process.env.API_KEY;

完整配置示例

# 完整的安全扫描配置

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

stages:
  - build
  - test
  - security
  - deploy

variables:
  SAST_EXCLUDED_PATHS: "tests, spec, node_modules"
  DS_EXCLUDED_PATHS: "tests"
  CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  SECRET_DETECTION_HISTORIC_SCAN: "false"

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

test:
  stage: test
  script:
    - npm ci
    - npm test

# 安全扫描Job由include自动添加

# 阻止部署如果有Critical漏洞
security-gate:
  stage: security
  needs: [sast, dependency_scanning, secret_detection, container_scanning]
  script:
    - echo "Checking security scan results..."
    - |
      if [ -f gl-sast-report.json ]; then
        CRITICAL=$(jq '.vulnerabilities | map(select(.severity=="Critical")) | length' gl-sast-report.json)
        if [ "$CRITICAL" -gt 0 ]; then
          echo "Found $CRITICAL critical vulnerabilities! Blocking deployment."
          exit 1
        fi
      fi
    - echo "Security gate passed!"
  allow_failure: false

deploy:
  stage: deploy
  needs: [security-gate]
  script:
    - ./deploy.sh
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

总结

本文介绍了GitLab的安全扫描功能,包括SAST、依赖扫描、密钥检测和容器扫描。将安全扫描集成到CI/CD流程中可以尽早发现和修复安全问题。

下一篇我们将学习GitLab Pages静态网站托管。

发表回复

后才能评论