burpsuite-project-parser について
Burp Suite プロジェクトファイルのデータを検索・抽出するスキルで、HTTP トラフィックの分析や監査結果の確認に使います。Burp Suite Professional と拡張機能に解析を委ね、未検証の空結果を区別する手順を設けています。
主な機能
- 01リクエストとレスポンスの正規表現検索
- 02監査結果と深刻度の抽出
- 03プロキシ履歴とサイトマップの確認
- 04出力制限とレスポンス本文の切り詰め
- 05パーサー拡張機能の動作確認
活用シーン
- 01レスポンスヘッダーや本文のパターン検索
- 02深刻度による監査結果の絞り込み
- 03プロジェクト内のプロキシ通信の確認
- 04空の検索結果が有効かどうかの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trailofbits/ skills --skill burpsuite-project-parserインストール後、Claude Code で/burpsuite-project-parserを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlassets/trail-of-bits-mark.svgscripts/burp-search.sh詳細
Burp プロジェクトパーサー
burpsuite-project-file-parser 拡張機能を使用して、Burp Suite のプロジェクトファイルからデータを検索、抽出します。
使用する場面
- 正規表現パターンを使ってレスポンスヘッダーや本文を検索する場合
- Burp プロジェクトからセキュリティ監査の検出事項を抽出する場合
- プロキシ履歴やサイトマップのデータをダンプする場合
- Burp プロジェクトファイルに記録された HTTP トラフィックを分析する場合
前提条件
このスキルは、解析を Burp Suite Professional に委任します。.burp ファイルを直接解析するわけではありません。
必要なもの:
- Burp Suite Professional — インストールされている必要があります(portswigger.net)
- burpsuite-project-file-parser 拡張機能 — CLI 機能を提供します
拡張機能のインストール:
- github.com/BuffaloWill/burpsuite-project-file-parser からダウンロードします
- Burp Suite で、Extender → Extensions → Add を選択します
- ダウンロードした JAR ファイルを選択します
クイックリファレンス
ラッパースクリプトを使用します:
{baseDir}/scripts/burp-search.sh /path/to/project.burp [FLAGS]
スクリプトは、プラットフォーム間の互換性を確保するために環境変数を使用します:
BURP_JAVA:Java 実行ファイルへのパスBURP_JAR:burpsuite_pro.jar へのパス
終了コードを確認してください。出力が空でも、正常な結果とは限りません。 Burp は認識できないフラグを無視するため、パーサー拡張機能がないと通常どおり起動し、クエリを無視します。これは、検索で何も一致しなかった場合とまったく同じように見えます。
| 終了コード | 意味 | 対応 |
|---|---|---|
| 0 | 出力が生成された | 続行します |
| 1 | 使用方法が不正、またはファイル、Java、JAR が見つからない | メッセージを確認し、パスを修正します |
| 3 | 出力がまったくない | これを「見つからなかった」と報告しないでください。 空の結果セットと拡張機能が読み込まれていない状態は、ここでは区別できません。以下の制御クエリを実行して、どちらかを判別してください |
| 4 | 出力が JSON ではない | 拡張機能が読み込まれておらず、Burp はフラグを無視しました。結果を信頼する前にインストールしてください |
終了コードが 0 以外の場合、検索結果は未検証です。その結果を根拠に「一致するトラフィックはありません」と報告すると、クリーンな検出結果として誤った陰性を報告することになります。
Exit 3 の解決:コントロールクエリ
Exit 3 はよくあるケースです。対象を狭く限定した正規表現の多くは、正当に何も一致しないため、自分で実行できる解決策が必要です。使用できるのは Bash と Read です。ここでは Burp がヘッドレスで動作しているため、開く Extensions タブも、確認する GUI もありません。同じクエリを再実行しても、再び 3 が返るだけです。
代わりにコントロールクエリを実行します。パーサーが正常に動作していれば必ず行が返るほど広いセレクターを、同じプロジェクトファイルに対して使用します。セレクター単体ではなく、サブコンポーネントフィルターを使用してください。コントロールもクエリであり、上記のルールがそのまま適用されます。
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 2000
proxyHistory.request.headers が適切なコントロールである理由は、プロジェクト内のすべてのレコードを対象にしつつ、範囲が限定されているためです。各レコードは 1KB 未満です。proxyHistory だけでも同じ問いへの答えは得られますが、上記で禁止しているのには理由があります。本文を含むレコードは数 MB になることがあり、head -n 1 を使ってもそれを防げません。レコード 1 件が、そのまま完全な形で出力されます。
| コントロール結果 | 意味 | 対応 |
|---|---|---|
| 標準出力に行が出る | パーサーは動作しています | より狭い範囲のクエリに実際に一致するものがありませんでした。その結果を報告してください |
| 再び Exit 3 | 何も返ってきません | 拡張機能が読み込まれていないか、このプロジェクトにプロキシ履歴がありません。正しいプロジェクトファイルを指定していること、およびファイルが空でないことを確認したうえで、Burp Suite → Extensions に burpsuite-project-file-parser が表示されているかユーザーに確認してもらってください |
| Exit 4 | Burp は起動しましたが、フラグが無視されました | 拡張機能が読み込まれていません。その旨を伝えてください。トラフィックについて報告してはいけません |
プロジェクトのトラフィックについて結論を出す前に、必ずコントロールを実行してください。 拡張機能が読み込まれていると思い込むと、未検証の空の結果を問題なしと判断してしまいます。コントロールで結論が出ない場合に、ユーザーに GUI を確認してもらうのは適切な対応です。推測はしないでください。
パイプを通すと、終了コードはそのまま読み取れません。 パイプラインでは、最後のコマンドの終了ステータスが報告されます。この例のほぼすべては | jq、| head、または | wc -cl で終わるため、$? はスクリプトの 3 ではなく head の 0 になります。信頼できる方法は 2 つあります。
- 標準エラー出力。パイプを通しても必ず確認できます。
Error: the parser produced no output.またはError: Burp produced output, but not one JSON objectが答えです。そのようなブロックがなければ、実行は正常です。 - 終了コードそのものが必要な場合は
set -o pipefailを使うか、${PIPESTATUS[0]}を読み取ります。
set -o pipefail
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq -c 'select(.severity == "High")'
echo "exit: $?"
JSON 以外の出力は標準出力に出ないため、後続の grep や jq が Burp の起動バナーに一致し、それをデータと誤認することはありません。
設定手順については、プラットフォームの設定を参照してください。
サブコンポーネントフィルター(必ず使用)
完全なダンプではなく、必ずサブコンポーネントフィルターを使用してください。 proxyHistory または siteMap を完全に取得すると、数 GB のデータが返されることがあります。サブコンポーネントフィルターを使えば、必要なデータだけを取得できます。
使用可能なフィルター
| フィルター | 取得内容 | 一般的なサイズ |
|---|---|---|
proxyHistory.request.headers | リクエスト行とヘッダーのみ | 小(レコードあたり 1KB 未満) |
proxyHistory.request.body | リクエスト本文のみ | 可変 |
proxyHistory.response.headers | ステータスとヘッダーのみ | 小(レコードあたり 1KB 未満) |
proxyHistory.response.body | レスポンス本文のみ | 大 — 避ける |
siteMap.request.headers | サイトマップの同じ情報 | 小 |
siteMap.request.body | 可変 | |
siteMap.response.headers | 小 | |
siteMap.response.body | 大 — 避ける |
デフォルトの方法
本文ではなく、まずヘッダーを確認してください。
# GOOD - headers only, safe to retrieve
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 50000
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | head -c 50000
# BAD - full records include bodies, can be gigabytes
{baseDir}/scripts/burp-search.sh project.burp proxyHistory # NEVER DO THIS
ヘッダーを確認した後、特定の URL の本文だけを取得し、必ず切り詰めてください。
# 1. First, find interesting URLs from headers
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | \
jq -r 'select(.headers | test("text/html")) | .url' | head -n 20
# 2. Then search bodies with targeted regex - MUST truncate body to 1000 chars
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*specific-pattern.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
厳守ルール:1000 文字を超える本文の内容をコンテキストに入れてはいけません。 ユーザーが本文全体を確認する必要がある場合は、Burp Suite の UI で確認してもらってください。
正規表現による検索操作
レスポンスヘッダーを検索
responseHeader='.*regex.*'
すべてのレスポンスヘッダーを検索します。出力:{"url":"...", "header":"..."}
例 — サーバーの識別情報を検索:
responseHeader='.*(nginx|Apache|Servlet).*' | head -c 50000
レスポンス本文の検索
responseBody='.*regex.*'
必須:本文の内容は常に最大1000文字に切り詰めてください。 レスポンス本文は、それぞれ数メガバイトに達することがあります。
# REQUIRED format - always truncate .body field
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*<form.*action.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
本文の内容をすべて取得してはいけません。 特定のレスポンスについてさらに確認する必要がある場合は、Burp Suite の UI で開くようユーザーに依頼してください。
その他の操作
監査項目の抽出
auditItems
すべてのセキュリティ上の検出事項を返します。出力には、name、severity、confidence、host、port、protocol、url が含まれます。
注: 監査項目は小さく(本文はありません)、head -n 100 で取得しても安全です。
プロキシ履歴のダンプ(使用しない)
proxyHistory
これを直接使用してはいけません。 代わりにサブコンポーネントのフィルターを使用してください。
proxyHistory.request.headersproxyHistory.response.headers
サイトマップのダンプ(使用しない)
siteMap
これを直接使用してはいけません。 代わりにサブコンポーネントのフィルターを使用してください。
出力制限(必須)
重要:データを取得する前に、必ず結果のサイズを確認してください。 範囲の広い検索では、数千件のレコードが返されることがあり、それぞれが数メガバイトに達する可能性があります。これによりコンテキストウィンドウがあふれてしまいます。
ステップ 1:必ず最初にサイズを確認する
検索の前に、レコード数とバイト数の両方を確認してください。
# Check record count AND total bytes - never skip this step
{baseDir}/scripts/burp-search.sh project.burp proxyHistory | wc -cl
{baseDir}/scripts/burp-search.sh project.burp "responseHeader='.*Server.*'" | wc -cl
{baseDir}/scripts/burp-search.sh project.burp auditItems | wc -cl
wc -cl の出力は <bytes> <lines> の形式です(例:524288 42 は、42件のレコードで合計512KBを意味します)。
結果の見方 — 両方の条件を満たす必要があります。
| 指標 | 安全 | 検索範囲を絞る | 広すぎる | 停止 |
|---|---|---|---|---|
| 行数 | < 50 | 50-200 | 200+ | 1000+ |
| バイト数 | < 50KB | 50-200KB | 200KB+ | 1MB+ |
1行に収まる10MBのレスポンスは、行数は1でもバイト数が大きくなります。バイト数の確認で検出できます。
wc -cl の結果が 0 0 でも、サイズを確認できたとは限りません。スクリプトが終了コード3で終了し、何も検証されていない可能性があります。パイプ処理ではその状態が隠れるため、クエリを単独で再実行し、終了コードを確認してから、プロジェクトに該当するトラフィックがないと判断してください。
ステップ 2:範囲の広い検索を絞り込む
件数またはサイズが大きすぎる場合:
-
サブコンポーネントのフィルターを使用する(上の表を参照):
# Instead of: proxyHistory (gigabytes) # Use: proxyHistory.request.headers (kilobytes) -
正規表現パターンを絞り込む:
# Too broad (matches everything): responseHeader='.*' # Better - target specific headers: responseHeader='.*X-Frame-Options.*' responseHeader='.*Content-Security-Policy.*' -
取得前に jq でフィルターする:
# Get only specific content types {baseDir}/scripts/burp-search.sh project.burp proxyHistory.response.headers | \ jq -c 'select(.url | test("/api/"))' | head -n 50
ステップ 3:出力は常に切り詰める
検索範囲を絞り込んだ後も、必ず切り詰め処理にパイプしてください。
# ALWAYS use head -c to limit total bytes (max 50KB)
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | head -c 50000
# For body searches, truncate each JSON object's body field:
{baseDir}/scripts/burp-search.sh project.burp "responseBody='pattern'" | \
head -n 20 | jq -c '.body = (.body | if length > 1000 then .[:1000] + "...[TRUNCATED]" else . end)'
# Limit both record count AND byte size:
{baseDir}/scripts/burp-search.sh project.burp auditItems | head -n 50 | head -c 50000
必ず適用する上限:
- すべての出力に
head -c 50000(最大50KB)を適用 .bodyフィールドは1000文字に切り詰めること — 必須、例外なしjq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
件数を数えず、切り詰めも行わずに、次のものを実行してはいけません:
proxyHistory/siteMap(全件ダンプ — 必ずサブコンポーネントのフィルターを使用)responseBody='...'の検索(本文はそれぞれ数メガバイトに達することがあります).*や.+のような範囲の広い正規表現
調査ワークフロー
-
調査範囲を特定する — 何を探していますか?(特定の脆弱性の種類、エンドポイント、ヘッダーのパターン)
-
まず監査項目を検索する — Burp の検出結果から始めます。
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq 'select(.severity == "High")' -
信頼度スコアを確認する — 対応すべき検出結果を絞り込みます。
... | jq 'select(.confidence == "Certain" or .confidence == "Firm")' -
影響を受ける URL を抽出する — 攻撃対象領域を確認します。
... | jq -r '.url' | sort -u -
生のトラフィックを検索して状況を把握する — 実際のリクエスト/レスポンスを調べます。
{baseDir}/scripts/burp-search.sh project.burp "responseBody='pattern'" -
手動で検証する — Burp の検出結果は手掛かりであり、証明ではありません。一つずつ検証してください。
結果の理解
重大度と信頼度
Burp は重大度(High/Medium/Low)と信頼度(Certain/Firm/Tentative)の両方を報告します。トリアージでは両方を使用してください。
| 組み合わせ | 意味 |
|---|---|
| High + Certain | 実際の脆弱性である可能性が高いため、調査を優先してください |
| High + Tentative | 誤検知であることが多いため、報告前に検証してください |
| Medium + Firm | 調査する価値があり、手動での検証が必要になる場合があります |
「重大度はHigh、信頼度はTentative」の検出結果は、誤検知であることがよくあります。重大度だけを根拠に検出結果を報告しないでください。
プロキシ履歴が不完全な場合
プロキシ履歴には、Burp がキャプチャした内容のみが含まれます。次の理由でトラフィックが欠落している可能性があります。
- スコープフィルターによってドメインが除外されている
- インターセプト設定によってリクエストが破棄されている
- ブラウザーのトラフィックが Burp プロキシ経由でルーティングされていない
想定したトラフィックが見つからない場合は、元のプロジェクトで Burp のスコープとプロキシの設定を確認してください。
HTTP ボディのエンコーディング
レスポンスボディは、gzip 圧縮、チャンク転送、または UTF-8 以外のエンコーディングが使用されている場合があります。プレーンテキストで機能する正規表現パターンでも、エンコードされたレスポンスでは気付かないうちに失敗することがあります。検索結果が予想より少ない場合は、次の点を確認してください。
- レスポンスが圧縮されているか確認します
- より広範なパターンを試すか、先にヘッダーを検索します
- Burp の UI で未加工のレスポンスとレンダリング済みのレスポンスを確認します
避けるべき誤った判断
脆弱性の見落としや誤報につながる、よくある近道です。
| 近道 | それが誤りである理由 |
|---|---|
| 「この正規表現なら問題なさそう」 | まずサンプルデータで検証してください。エンコーディングやエスケープが原因で、気付かないうちに失敗することがあります |
| 「重大度が高いなら、必ず修正が必要」 | 信頼度スコアも確認してください。Burp は誤検知することがあります |
| 「監査項目はすべて関連がある」 | 実際の脅威モデルに基づいて絞り込んでください。すべての検出結果が、すべてのアプリに関係するわけではありません |
| 「プロキシ履歴は完全だ」 | Burp のスコープやインターセプトの設定によってフィルタリングされている場合があります。Burp がキャプチャしたものしか表示されません |
| 「Burp が検出したのだから、これは脆弱性だ」 | Burp の検出結果は手動で検証する必要があります。潜在的な問題を示すものであり、証明ではありません |
| 「検索結果が何もないから、トラフィックは存在しない」 | まず終了コードを確認してください。終了コード 3 は、スクリプトが空の結果と未ロードの拡張機能を区別できなかったことを意味し、終了コード 4 はクエリが実行されなかったことを意味します。結果が何もないことをプロジェクトについての結論として述べられるのは、終了コードが 0 の場合だけです。そうでなければ、ツールについての結論にすぎません |
出力形式
出力はすべて JSON で、1 行につき 1 つのオブジェクトです。整形するには jq にパイプします。
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq .
grep で絞り込みます。
{baseDir}/scripts/burp-search.sh project.burp auditItems | grep -i "sql injection"
例
CORS ヘッダーを検索します(バイト数の上限を指定)。
{baseDir}/scripts/burp-search.sh project.burp "responseHeader='.*Access-Control.*'" | head -c 50000
重大度の高い検出結果をすべて取得します(監査項目は小さいものの、上限を指定してください)。
{baseDir}/scripts/burp-search.sh project.burp auditItems | jq -c 'select(.severity == "High")' | head -n 100
プロキシ履歴からリクエスト URL のみを抽出します。
{baseDir}/scripts/burp-search.sh project.burp proxyHistory.request.headers | jq -r '.request.url' | head -n 200
レスポンスボディを検索します(ボディは必ず 1000 文字に切り詰めてください)。
{baseDir}/scripts/burp-search.sh project.burp "responseBody='.*password.*'" | \
head -n 10 | jq -c '.body = (.body[:1000] + "...[TRUNCATED]")'
プラットフォームの設定
ラッパースクリプトでは、Burp Suite に同梱された Java と JAR ファイルの場所を特定するため、2 つの環境変数が必要です。
macOS
export BURP_JAVA="/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java"
export BURP_JAR="/Applications/Burp Suite Professional.app/Contents/Resources/app/burpsuite_pro.jar"
Windows
$env:BURP_JAVA = "C:\Program Files\BurpSuiteProfessional\jre\bin\java.exe"
$env:BURP_JAR = "C:\Program Files\BurpSuiteProfessional\burpsuite_pro.jar"
Linux
export BURP_JAVA="/opt/BurpSuiteProfessional/jre/bin/java"
export BURP_JAR="/opt/BurpSuiteProfessional/burpsuite_pro.jar"
これらのエクスポートをシェルプロファイル(.bashrc、.zshrc など)に追加すると、設定が保持されます。
手動での実行
ラッパースクリプトを使わない場合は、次のコマンドを直接実行します。
"$BURP_JAVA" -jar -Djava.awt.headless=true "$BURP_JAR" \
--project-file=/path/to/project.burp [FLAGS]