🔍
概念 #セキュリティ #Webアプリ #Burp Suite #SAST #DAST #ペネトレーションテスト 📚 Webアプリセキュリティ

Webアプリセキュリティテスト実践(Burp Suite・SAST・DAST)

セキュリティテストの全体像

セキュリティテストの種類:

  SAST(Static Application Security Testing)
    └── コードを実行せず静的解析でバグを検出
        ツール: Semgrep, Bandit, CodeQL, Checkmarx

  DAST(Dynamic Application Security Testing)
    └── 動作中のアプリに実際にリクエストを送って脆弱性を検出
        ツール: OWASP ZAP, Burp Suite Pro(Scanner), Nikto

  IAST(Interactive AST)
    └── 実行中のアプリにエージェントを埋め込んでリアルタイム検出
        ツール: Contrast Security, Seeker

  ペネトレーションテスト(手動)
    └── テスターが攻撃者の視点で能動的に脆弱性を探す
        フレームワーク: OWASP WSTG, PTES

  SCA(Software Composition Analysis)
    └── 依存ライブラリの既知 CVE を検出
        ツール: Trivy, Dependabot, Snyk

Burp Suite 実践

基本セットアップ

1. Burp Suite Community / Pro を起動
2. Proxy → Options → Proxy Listeners: 127.0.0.1:8080
3. ブラウザのプロキシ設定を 127.0.0.1:8080 に向ける
   (推奨: Burp の組み込みブラウザを使う)
4. Burp の CA 証明書をブラウザにインポート
   → http://burp → CA Certificate をダウンロード → ブラウザにインストール
5. Proxy → Intercept → ON でリクエストをキャプチャ開始

Proxy でのインターセプト操作

主要ショートカット:
  Ctrl+F  → Forward(リクエストを転送)
  Drop    → リクエストを破棄
  Action → Send to Repeater(Ctrl+R)
  Action → Send to Intruder(Ctrl+I)

Proxy History でリクエスト一覧を確認:
  ・Filter で特定のホスト・ステータスコードに絞り込み
  ・右クリック → Send to Repeater で詳細テスト

Repeater(手動リクエスト改ざん)

使い方:
  1. Proxy History から気になるリクエストを Repeater に送る
  2. リクエストのパラメータを手動で変更して Send
  3. レスポンスを比較して脆弱性を確認

テスト例(SQLi 確認):
  元: GET /api/users?id=1
  改: GET /api/users?id=1'    ← SQL エラーが返れば SQLi の可能性
  改: GET /api/users?id=1 OR 1=1--
  改: GET /api/users?id=1 AND SLEEP(5)--  ← Blind SQLi

Intruder(自動化・ブルートフォース)

使い方:
  1. Repeater で使うリクエストを Intruder に送る
  2. Positions タブでペイロードを挿入する位置を § マーカーで囲む
  3. Payloads タブでリストまたはパターンを設定
  4. Start Attack でリクエストを一括送信

Attack タイプ:
  Sniper:       1つの位置に順番にペイロードを挿入
  Battering ram: 全位置に同じペイロードを同時挿入
  Pitchfork:    各位置に異なるリストを並行挿入(user + password の組み合わせ)
  Cluster bomb: 全位置に全組み合わせ挿入(総当たり)

Community 版の制限: Intruder はスロットリングあり → Pro 版推奨

Scanner(Pro 版のみ)

受動スキャン: Proxy を通過するすべてのリクエストを自動分析
能動スキャン: 対象 URL に積極的に攻撃ペイロードを送信して脆弱性を検出

スキャン手順:
  1. Target → Site Map で対象ホストを確認
  2. 対象ホストを右クリック → Active Scan
  3. スキャン完了後、Dashboard → Issues で結果を確認

重要度(Severity):
  High:   即座に対処が必要(SQLi, RCE, 認証バイパス)
  Medium: 対処推奨(XSS, SSRF)
  Low:    コンテキスト依存(情報漏洩, ヘッダー欠如)
  Info:   参考情報(バージョン情報, パス列挙)

Decoder / Comparer

Decoder:
  ・Base64 / URL エンコード / HTML エンティティ / 16進数 を相互変換
  ・JWT のペイロード部分(Base64url)を貼り付けてデコード
  ・Use: Proxy でトークンをコピー → Decoder に貼り付け → Decode as Base64

Comparer:
  ・2つのレスポンスの差分を視覚的に比較
  ・Use: レスポンスの長さが異なる場合に Blind SQLi の結果を比較

OWASP WSTG に沿った手動テスト

OWASP Web Security Testing Guide(WSTG)はセキュリティテストの標準手順書。

情報収集(Reconnaissance)

# サブドメイン列挙
subfinder -d example.com
amass enum -d example.com

# ポートスキャン・サービス検出
nmap -sV -sC -p 80,443,8080,8443 example.com

# ディレクトリ・ファイルのブルートフォース
gobuster dir -u https://example.com -w /usr/share/wordlists/dirb/common.txt
ffuf -u https://example.com/FUZZ -w wordlist.txt -mc 200,301,302,403

# Wayback Machine でページ履歴を確認(廃止 API の発見)
waybackurls example.com | grep "api"

# JS ファイルから隠しエンドポイントを抽出
cat *.js | grep -E "(api|endpoint|url|path)" | sort -u

認証テスト

WSTG-AUTHN-01: 暗号化されていない認証チャネルのテスト
  → HTTP でログインページが提供されていないか確認
  → HSTS が設定されているか確認

WSTG-AUTHN-03: アカウントロックアウトのテスト
  Burp Intruder でパスワードをブルートフォース(許可された環境のみ)
  → 10回失敗後もロックアウトされないか確認

WSTG-AUTHN-06: ブラウザキャッシュの脆弱性テスト
  → ログアウト後に「戻る」ボタンで画面が表示されないか
  → Cache-Control: no-store が設定されているか
# パスワードリセットのテスト手順
"""
1. パスワードリセットを要求 → メールのトークンを取得
2. トークンの長さ・エントロピーを確認(最低 128bit = 16バイト)
3. トークンを使用後に無効化されるか確認(2度使えないか)
4. 有効期限を確認(1時間以内が推奨)
5. ユーザー名を変えて同じトークンが使えないか確認
"""

セッション管理テスト

WSTG-SESS-01: セッション管理スキームの分析
  Burp Sequencer でセッション ID のランダム性を統計的に評価:
    1. Proxy でログインリクエストをキャプチャ
    2. Set-Cookie の値を Sequencer に送る
    3. Start Live Capture → 1000件のセッション ID を収集
    4. Analyze → Information content(ビット数)を確認
       → 100bit 未満であれば予測可能なリスク

WSTG-SESS-02: Cookie 属性のテスト
  Proxy でレスポンスの Set-Cookie ヘッダーを確認:
  □ HttpOnly が設定されているか
  □ Secure が設定されているか
  □ SameSite が Strict または Lax か
  □ 有効期限が適切か

WSTG-SESS-06: ログアウト機能のテスト
  1. ログイン → セッション Cookie を記録
  2. ログアウト
  3. 記録したセッション Cookie を手動でセットして API にアクセス
  → サーバー側でセッションが無効化されているか確認

認可テスト(IDOR・権限昇格)

WSTG-ATHZ-01: ディレクトリトラバーサルのテスト
  Burp Repeater でファイルパスのパラメータを改ざん:
    /api/files/report.pdf → /api/files/../../../etc/passwd
    /api/files/report.pdf → /api/files/%2e%2e%2f%2e%2e%2fetc%2fpasswd(URL エンコード)

WSTG-ATHZ-04: 水平・垂直権限昇格テスト
  1. User A と User B の2アカウントを用意
  2. User A の認証 Cookie / JWT を使って User B のリソースにアクセス
     GET /api/orders/B_ORDER_ID  with A's token → 403 を返すはず
  3. 管理者 URL を推測してアクセス
     /api/admin/users, /api/v1/admin, /api/internal

インジェクションテスト

SQLi の手動テスト:
  1. 単一引用符: ' → SQL エラーを確認
  2. トートロジー: 1 OR 1=1 → 全件取得されないか
  3. コメント: 1--  1#  1;-- → SQL 構文の残りをコメントアウト
  4. Union: ' UNION SELECT NULL--  → カラム数を特定
  5. Time-based: ' AND SLEEP(5)-- → 応答遅延で Blind SQLi を確認

XSS の手動テスト:
  基本ペイロード:
    <script>alert(1)</script>
    <img src=x onerror=alert(1)>
    <svg onload=alert(1)>
  属性インジェクション:
    " onmouseover="alert(1)
    "><script>alert(1)</script>
  DOM XSS の確認:
    ブラウザコンソールで document.getElementById('output').innerHTML を確認
    URL パラメータが innerHTML / document.write に渡っていないか調査

SAST(静的解析)ツール

Semgrep

# .semgrep.yml: カスタムルール例(危険な eval の検出)
rules:
  - id: dangerous-eval
    pattern: eval(...)
    message: "eval() の使用はコードインジェクションのリスクがあります"
    languages: [javascript, typescript]
    severity: WARNING

  - id: sql-injection-string-concat
    pattern: |
      $QUERY = "SELECT ... " + $INPUT
    message: "文字列結合によるSQLクエリはSQLインジェクションのリスクがあります"
    languages: [python]
    severity: ERROR
# 実行
semgrep --config=auto src/        # 公式ルールセットで自動スキャン
semgrep --config=.semgrep.yml src/ # カスタムルールで実行

# CI(GitHub Actions)への組み込み
# .github/workflows/semgrep.yml
# GitHub Actions での Semgrep 統合
name: Semgrep SAST
on: [push, pull_request]
jobs:
  semgrep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten
            p/python

Bandit(Python 専用)

# インストール
pip install bandit

# スキャン
bandit -r src/ -f json -o bandit-report.json

# 重大度・信頼度でフィルタ
bandit -r src/ -l  # 高重大度のみ
bandit -r src/ -ll # 中以上の重大度

# 主要な検出項目
# B101: assert の使用(テストコード以外)
# B105: ハードコードされたパスワード
# B201: Flask のデバッグモードが有効
# B301: pickle の安全でない使用
# B501: SSL 証明書の検証を無効化
# B608: SQLi の可能性(文字列結合のクエリ)

DAST ツール

OWASP ZAP

# Docker で ZAP フルスキャン(CI 向け)
docker run --rm -v $(pwd):/zap/wrk/:rw \
  ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py \
  -t https://example.com \
  -r zap-report.html \
  -J zap-report.json

# ベースラインスキャン(パッシブのみ、CI の PR チェック向け)
docker run --rm \
  ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
  -t https://staging.example.com \
  -r baseline-report.html
# GitHub Actions での ZAP 統合
name: DAST Scan
on:
  push:
    branches: [main]
jobs:
  zap_scan:
    runs-on: ubuntu-latest
    steps:
      - name: ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.12.0
        with:
          target: 'https://staging.example.com'
          rules_file_name: '.zap/rules.tsv'
          fail_action: false   # 脆弱性があっても CI を落とさない(最初は warn のみ)

SCA(依存ライブラリのスキャン)

# Trivy(コンテナ・ファイルシステム・SBOM)
trivy fs --scanners vuln,secret . --format table

# npm audit
npm audit --audit-level=high

# pip-audit
pip install pip-audit
pip-audit -r requirements.txt

# GitHub Dependabot(自動 PR で依存更新)
# .github/dependabot.yml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5

  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"

Burp Suite 拡張(BApp Store)

必須インストール拡張:

  DOM Invader:
    ・DOM XSS の Source / Sink を自動追跡
    ・Canary 文字列を埋め込んでどの Sink に到達したか検出

  Param Miner:
    ・隠しパラメータ・ヘッダーをブルートフォースで発見
    ・Cache Poisoning の原因になる未知のキャッシュキーを発見

  InQL(GraphQL Analyzer):
    ・GraphQL の Introspection を解析してクエリを自動生成
    ・Burp Suite と統合してインターセプト・テストが可能

  JWT Editor:
    ・JWT の alg:none 攻撃・RS256→HS256 混同攻撃を自動でテスト
    ・ペイロードを改ざんして再署名

  Active Scan++:
    ・Scanner の検出精度を向上させる追加チェック項目

テストのスコーピングと注意事項

必ず実施すること:
  □ テスト対象のスコープを書面(テスト許可書)で取得する
  □ 本番環境ではなくステージング環境でテストする
  □ Burp Target → Scope で対象ホストを制限する(スコープ外に誤送信しない)
  □ テスト中のアクションをログに記録する(証跡として残す)
  □ 発見した脆弱性はすぐに報告する(悪用しない)

Burp でスコープを設定する手順:
  1. Target → Scope → Add
  2. テスト対象の URL を入力
  3. Proxy → Options → "Out-of-Scope Requests" で警告を有効化

セキュリティテスト総合チェックリスト

認証・セッション

□ ログイン失敗に対してアカウントロックアウトまたはレートリミットがある
□ セッション ID が最低 128bit のエントロピーを持つ(Burp Sequencer で確認)
□ Cookie に HttpOnly・Secure・SameSite=Strict が設定されている
□ ログアウト後にサーバー側でセッションが無効化される
□ パスワードリセットトークンが使用後に無効化・有効期限がある
□ JWT の alg:none 攻撃・RS256/HS256 混同が成立しない(Burp JWT Editor で確認)

認可

□ 他ユーザーの ID を使ったオブジェクトアクセスが 403 を返す(IDOR テスト)
□ 一般ユーザーが管理者エンドポイントにアクセスできない
□ /api/admin, /api/internal, /api/v1/admin 等の URL を試した
□ HTTP メソッドを変えても(GET→POST→DELETE)認可が効いている

インジェクション

□ 全パラメータに単一引用符(')を入力してエラーが出ないことを確認
□ HTML 出力箇所に <script>alert(1)</script> を入力して実行されないことを確認
□ ファイルパスのパラメータに ../../../etc/passwd を試した
□ URL フェッチ機能に http://127.0.0.1/ を試した(SSRF)

セキュリティヘッダー

□ CSP ヘッダーが設定されている(securityheaders.com でスキャン)
□ HSTS が設定されている
□ X-Content-Type-Options: nosniff が設定されている
□ Server・X-Powered-By ヘッダーでバージョン情報が漏れていない

依存ライブラリ

□ npm audit / pip-audit / trivy fs で HIGH 以上の CVE がない
□ Dependabot または定期的な SCA スキャンを CI に組み込んでいる

参考文献

  • OWASP Web Security Testing Guide v4.2(owasp.org/www-project-web-security-testing-guide)— Webアプリテストの標準手順書(全テストケース)
  • PortSwigger Web Security Academy(portswigger.net/web-security)— Burp Suite を使ったインタラクティブ学習ラボ(無料)
  • PortSwigger Burp Suite Documentation — Repeater・Intruder・Scanner の公式操作ガイド
  • Dafydd Stuttard & Marcus Pinto『The Web Application Hacker’s Handbook』(Wiley, 2011)— 手動テスト手法の体系的解説
  • Semgrep ドキュメント(semgrep.dev)— SAST ルールの書き方・公式ルールセット一覧

出典: OWASP Testing Guide v4.2 / PortSwigger Burp Suite Documentation / OWASP WSTG / The Web Application Hacker's Handbook(Stuttard & Pinto, 2011)