CI/CDパイプラインのセキュリティ強化:SCA・SAST・DASTの実践ガイド

Security tutorial - IT technology blog
Security tutorial - IT technology blog

深夜2時の警報:なぜセキュリティは全員の問題なのか

セキュリティは「セキュリティチームの仕事」ではないと、私は身をもって学びました。数年前、私のサーバーがブルートフォース攻撃にさらされ、10分も経たないうちにSSHログイン失敗が5,000件記録されました。ログが流れ込んでくるのを見ながら、現実を突きつけられた気分でした。インフラがこれほど簡単に見つかるなら、締め切りに追われて書いたアプリケーションコードはザルも同然でしょう。その夜以来、セキュリティを最後の仕上げではなく、コアな機能として扱うようになりました。

ほとんどの開発チームの目標は「素早く出荷すること」です。コードをプッシュし、GitHub Actionsの緑のチェックマークを待って、デプロイする。しかし、ビルドが成功しても、それはコードが動作することを証明しているだけで、安全であることは証明していません。開発サイクルの終わりまでセキュリティ監査を先送りにすれば、大惨事を招くだけです。数週間かけて書き直すべきアーキテクチャ上の欠陥が見つかり、リリースの勢いが完全に失われることも珍しくありません。

脆弱なコードの本当のコスト

脆弱性は「コードが悪い」から生まれるわけではありません。現代の開発ワークフローの隙間からじわじわと入り込んでくるのです。IBMによると、本番環境でバグを修正するコストは、設計・ビルドフェーズで修正するコストの最大30倍にもなるといいます。危険が潜んでいる主な場所をご紹介します:

  • 依存関係の罠:現代のアプリケーションはコードの80〜90%がサードパーティ製です。2年前にインポートしたライブラリに新たなCVE(共通脆弱性識別子)が発見された場合、悪名高いLog4jの脆弱性のように、スタック全体が危険にさらされます。
  • シークレットの漏洩:疲れた開発者が一人いるだけで、AWSのシークレットキーやStripe APIトークンをうっかり公開リポジトリにコミットしてしまいます。数秒以内にボットがそれをスキャンして持っていくでしょう。
  • インジェクションの欠陥:SQLインジェクションやクロスサイトスクリプティング(XSS)は依然としてOWASP Top 10を占めています。これらはバリデーションされていないユーザー入力の中に堂々と潜んでいることが多いです。

手動監査 vs. 自動化されたDevSecOps

手動のセキュリティレビューは大きなボトルネックです。通常、セキュリティの専門家が四半期に一度スキャンを実施します。その頃には、元の開発者たちはそのコードをなぜ書いたのかすら忘れていることが多いです。数ヶ月後に問題を修正するのは、コストがかかるだけでなく、非常にストレスもたまります。

DevSecOpsは「シフトレフト」によってこの流れを逆転させます。セキュリティチェックをパイプラインの最初の段階に移動させるのです。コードをコミットするたびに、自動ツールが欠陥をスキャンします。重大な脆弱性が見つかればビルドは即座に失敗します。ロジックが頭の中に新鮮なうちに問題を修正できるのです。

3層の防御戦略

堅牢なパイプラインには複数のツールが必要です。私はSCA・SAST・DASTの組み合わせに頼ってあらゆる側面をカバーしています。標準的なCI/CDフローへの設定方法をご紹介します。

1. SCA(ソフトウェア構成分析)

SCAツールはpackage.jsonrequirements.txtを解析し、依存関係に存在する既知の脆弱性を発見します。私はSnykやTrivyを好んで使っています。これらはデータベースが最新のエクスプロイト情報で常に更新されているからです。

このGitHub Actionsのスニペットは、Node.jsの依存関係に深刻度が「高」の脆弱性が検出された場合、ビルドを失敗させます:

name: セキュリティスキャン
on: [push]
jobs:
  snyk-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Snykを実行
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

2. SAST(静的アプリケーションセキュリティテスト)

SASTはスーパーパワードなリンターだと思ってください。コードを実行せずにソースコードをスキャンし、ハードコードされたパスワードや安全でない暗号関数などのパターンを探します。PythonにはBanditが最適で、多言語のエンタープライズプロジェクトにはSonarQubeが標準的です。

パイプラインでBanditの簡単なスキャンを実行する方法はこちらです:

  sast-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Banditをインストール
        run: pip install bandit
      - name: スキャンを実行
        run: bandit -r ./app -f json -o results.json

3. DAST(動的アプリケーションセキュリティテスト)

DASTは実行中のアプリケーションを外部から内部へとテストする点が異なります。設定ミスのあるヘッダーや安全でないCookieを探そうとする攻撃者を模倣します。OWASP ZAPは業界で最もよく使われるツールです。

DASTはライブ環境が必要なため、ステージングサーバーへのデプロイ後にトリガーしてください:

  dast-scan:
    runs-on: ubuntu-latest
    steps:
      - name: OWASP ZAP フルスキャン
        uses: zaproxy/[email protected]
        with:
          target: 'https://staging.example.com'

実行戦略

ツールだけでは救われません。プロセスが必要です。チームにこれを実装する際、私は3つのルールに従います。まず、マージをブロックすること。スキャンで「Critical」な欠陥が見つかったら、修正されるまでPRは開いたままにします。次に、シークレット検出を自動化すること。gitleaksを使って、APIキーがクラウドに到達する前に検出します。最後に、ベースラインから始めること。400件の脆弱性を抱える古いプロジェクトがあっても、慌てる必要はありません。まず新しい脆弱性を修正し、その後は毎週1時間スケジュールを組んで古い技術的負債を少しずつ解消していきましょう。

まとめ

DevSecOpsパイプラインの構築は、高価なエンタープライズソフトウェアを購入することではありません。セキュリティを「完了の定義」の一部にすることです。自動化されたスクリプトは眠らず、攻撃者も眠りません。SCA・SAST・DASTを統合することで、リポジトリに24時間365日の番人を置けます。YAMLファイルの設定に数時間かかりますが、その安心感は十分に価値があります。

Share: