
Burp、mitmproxy、またはChrome DevToolsのキャプチャからOAuth 2.0、OIDC、およびMicrosoft Entra IDトークンを分析・追跡します。トークンのライフサイクルを可視化し、リスクの高いスコープを検出し、インタラクティブなダッシュボードを通じてリプレイ用にトークンをエクスポートします。
キャプチャしたネットワークトラフィック全体にわたって OAuth 2.0、OIDC、および Microsoft Entra ID トークンを追跡します。Burp Suite の XML エクスポート、mitmproxy フローファイル、またはライブの Chrome DevTools Protocol ストリームを単一の SQLite データベースに取り込み、トークンのフィルタリング、交換の追跡、リスクの高いスコープの特定、リプレイ用のトークンエクスポート、トークンライフサイクルの Mermaid グラフとしての可視化を行うインタラクティブな Web ダッシュボードを提供します。
ステータス: TATS は個人利用 / エンゲージメント利用において安定しています。Microsoft 365 / Entra エコシステム (FOCI、BroCI/NAA、ESTSAUTH セッション Cookie、entrascopes.com によるエンリッチメント) に最適化されていますが、標準的な OAuth/OIDC トラフィックであれば何でも動作します。
長い Microsoft 365 または Azure セッションを Burp / mitmproxy 経由でプロキシすると、結果として得られるキャプチャは膨大になり、ほとんどのツールは次のいずれかです:
このツールは、観測されたすべての access / refresh / id トークンを抽出し、ソース間で同じトークンを相関させられるようにフィンガープリントを付与し、JWT クレームをデコードし、Microsoft のクライアント / リソース GUID を entrascopes.com に対して解決し、全体像を単一のダッシュボードとして描画します — これには FOCI のクロスアプリ交換や BroCI のネストされたアプリのトークン発行を追跡するリフレッシュトークンチェーン表示も含まれます。
このプロジェクトは主に研究および教育目的を意図していますが、コマンドプレビューやトークンエクスポート機能など、一部の攻撃的ツーリングを支援できるオプションも提供します。
ingest — Burp Suite の「Save items」XML エクスポートmitm — mitmproxy の .mitm フローファイル (HTTP および WebSocket フレーム)cdp — DevTools Protocol 経由で Chrome / Edge にライブ接続
(リアルタイムで、プロキシ CA なしで TLS 復号済みの HTTP および WebSocket フレームをキャプチャ。ブラウザレベルの自動アタッチにより、既存のすべてのタブと実行中に開かれたすべてのタブを追跡)--append を付けて実行することで既存のデータベースにマージできます。トークンはアップサートされ (使用回数 + 観測されたライフタイムが累積)、イベントと交換は追記され、行の source_tag にはそのトークンを観測したすべてのパスが記録されます。pip install mitmproxy)。access_token、refresh_token、id_token) と Cookie 名のヒューリスティックがトークンタイプを決定します。ESTSAUTH、ESTSAUTHPERSISTENT、ESTSAUTHLIGHT、SignInStateCookie`) はリフレッシュ相当のトークンとして明示的に認識されます (そうでなければ、汎用的な「auth」Cookie ヒントによって誤分類されるでしょう)。foci フィールドを介して検出されます。brk_client_id、brk_redirect_uri、および brk-<guid>:// リダイレクトスキームを介して検出されます。--enrich フラグは https://entrascopes.com/ から firstpartyscopes.json と resources.json を取得し、appid / azp / aud GUID をクリック可能なリンク付きの分かりやすい名前へと解決します。upn / preferred_username / unique_name / email / name によるトークンのバケット化。sub@iss または oid にフォールバックし、アプリ専用および不明な ID のバケットを別途表示します。各 ID 行は、そのユーザーが 2 つ以上の source_tag に現れる場合に captures バッジ (クロスキャプチャ生存、--append の主要な研究シグナル) を表示し、さらに first_seen → last_seen のスパンと、Sequence-diagram タブでそのユーザーのすべてのトークンをハイライトする timeline ボタンを表示します。appid / azp / フォームボディの client_id / brk_client_id / brk_nested_id)。FOCI / brokerable / broker / nested バッジ付き。aud クレーム。可能な場合は entrascopes のリソース名に解決されます。tid 値。scp / scope / roles を、影響度の高い Microsoft Graph アクセス許可と Azure リソーススコープの厳選されたウォッチリストに対してチェックします。aud クレームと一致しないホストで使用されたすべての (token, host) ペアにフラグを立てます (資格情報の漏洩または誤用を示唆)。amr) — pwd / mfa / pop / smartcard の分布。xms_cc=CP1)、proof-of-possession バインディング (cnf クレーム、オーディエンス間での共有 kid 検出付き)、ステップアップ認証要件 (acrs)、および acr 認証コンテキストレベルにフラグを立てます。各行はクリック可能で、そのマーカーを持つトークンのみに Tokens タブをフィルタリングします。⚠ priv バッジを付けます — FOCI / BroCI スタイルの特権拡大の研究シグナルです。source_tag ごとのトークン数。各取り込みパスから何行が来たかを確認できます。roadtx describe、roadtx auth、curl、Python requests、PowerShell Invoke-RestMethod のコピー&ペースト用スニペットを含むコマンドプレビューブロックを備えたインラインパネルが展開されます。ws-frame-sent / ws-frame-received、ソース ws[body_json[<key>]]、および 1 つの WebSocket 接続内のすべてのフレームをグループ化する ws_session_id を持つイベントを生成します。データベースは、観測されたすべてのトークンの SHA-256 フィンガープリント (先頭 12 桁の 16 進文字) と 12 文字のプレフィックスを保存します。完全なトークン文字列が入力ファイルから外に出ることはありません。
デコードされた JWT クレームの内容 (ヘッダー + ペイロード、oid、sub、upn、email、tid、スコープリストなどを含む) は、分析のまさに目的であるため、デフォルトでそのまま保存されます。JWT が存在する場合は常に、データベースおよび共有されたダッシュボード URL を機密として扱ってください。
--redact-claims (ingest、mitm、および cdp で利用可能) は、データベースに到達する前に、リストされたクレーム値を安定したハッシュプレースホルダーに置き換えます。デフォルトのフィールドリストは sub、oid、upn、email、name、unique_name、preferred_username、emails、mail、ipaddr、given_name、family_name をカバーします。明示的なカンマ区切りリスト (例: --redact-claims sub,upn,oid) を渡してデフォルトを上書きします。同じ入力は常に同じプレースホルダーにマッピングされるため、ダッシュボードの Users / Tenants のグループ化はユーザーを明かすことなく機能し続けます。
--store-tokens (ingest、mitm、および cdp で利用可能、デフォルトではオフ) は、ダッシュボードが以下を提供できるように、完全なトークン文字列をデータベースに書き込むことを選択します:
.roadtools_auth にドロップすると、任意の roadtx サブコマンドがそれを拾い上げます)。roadtx describe、roadtx auth、curl、Python requests、PowerShell Invoke-RestMethod — を、トークンの実際の tid、appid、および クレームを使用して事前入力します。dataclasses を使用)。3.12 でテスト済み。python -m tats を直接実行します。| 必要なもの | インストール |
|---|---|
mitm サブコマンド | pip install mitmproxy |
| Chrome / Edge からのライブキャプチャ | なし — stdlib の WebSocket クライアントを使用 |
--enrich (entrascopes.com) | なし — urllib.request を使用 |
チェックアウトから実行 (インストールなし):```bash git clone tats cd tats python -m tats --help
ダッシュボードの HTML / CSS / JS は `tats/static/` にあり、
初回インポート時に読み込まれるため、ビルド手順は不要です — チェックアウトから
モジュールを直接実行するだけです。
**パッケージとしてインストール (`tats` コンソールスクリプトが利用可能になります):**```bash
pip install . # core only
pip install .[mitm] # + mitmproxy flow file support
pip install .[test] # + pytest for the test suite
pip install .[all] # everything
インストール後は、短縮名でツールを呼び出せます:```bash tats ingest engagement.xml -o tokens.db --enrich tats serve tokens.db
Burp / CDP パスのみが必要な場合、ファイルは Python 標準ライブラリのみで完全に自己完結しており、インストールや追加パッケージは不要です。
---
## クイックスタート
**Burp XML エクスポートを分析し、ダッシュボードを開く:**```bash
tats ingest examples/fixture.xml -o tokens.db --enrich
tats serve tokens.db
Burp キャプチャと mitmproxy フローファイルを1つの DB に統合する:```bash tats ingest engagement.xml -o tokens.db --enrich tats mitm chat-session.mitm -o tokens.db --enrich --append tats serve tokens.db
**Chromeブラウザからのライブキャプチャ(TLS復号済みのHTTP + WebSocketフレームを参照、プロキシCA不要)— ツールにブラウザを起動させる場合:**```bash
# Terminal 1 — auto-launch Chrome / Edge / Chromium / Brave
tats cdp -o tokens.db --enrich --launch-chrome
# Terminal 2 — open the dashboard (auto-refreshes every 5 s)
tats serve tokens.db
起動されたブラウザは、cdp コマンドを Ctrl-C すると終了し、その一時プロファイルは削除されます。
すでに実行中のブラウザにアタッチしたい場合は、--remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile を付けて起動し、--launch-chrome なしで cdp を実行してください。
共有する前にデータベースをサニタイズする(PII の秘匿化):```bash
tats ingest engagement.xml -o tokens.db
--enrich --redact-claims
レダクションはコンテンツ安定です。同一の値は同一のプレースホルダーにマッピングされるため、ダッシュボードのユーザーごとのグループ化はユーザーを表示せずに機能します。
データが流れ始めると、ダッシュボードのヘッダーに `live · updated <time>` が表示されます。
---
## サブコマンド
すべてのサブコマンドは、正規のオプション一覧を表示する `--help` を受け付けます。以下の注記では、それぞれを*いつ*、*どのように*使うかを説明します。
### グローバルフラグ
これらはすべてのサブコマンドに適用され、サブコマンド名の*前に*指定します:
* `-v` / `--verbose` — INFO ログ行(エンリッチメントのステータス、インジェストのレダクション件数)を追加します。`-vv` は DEBUG(すべてのサーバーリクエスト)を追加します。
* `-q` / `--quiet` — INFO ログ行を抑制し、WARNING と ERROR のみを表示します。最終的なユーザー出力行(例:`wrote tokens.db (...)`)および `error: …` 診断は影響を受けないため、スクリプトからでも重要な情報を確認できます。
* `--version` — ツールのバージョンを表示して終了します。
### `ingest` — Burp Suite XML エクスポート
「Save items」XML(Proxy → HTTP history → 右クリック → Save items)を読み込みます。バイナリの `.burp` プロジェクトファイルは**サポートされていません** — この形式はプロプライエタリであり、Burp のバージョン間で不安定です。対象のアイテムをエクスポートするのがサポートされたワークフローです。```bash
tats [-v|-q] ingest <burp_items.xml> -o tokens.db \
[--enrich] [--enrich-cache-dir DIR] [--no-enrich-cache] \
[--append] [--source-tag TAG] [--no-progress] \
[--redact-claims [CLAIMS]] [--no-serve-hint]
例:```bash
tats ingest burp.xml -o tokens.db --enrich
tats ingest day2.xml -o tokens.db --append
--source-tag burp:day2
### `mitm` — mitmproxy `.mitm` フローファイル
`mitmdump`、`mitmproxy`、または `mitmweb` が生成したフローファイルを読み取ります。これは、ライブブラウザセッションなしで **WebSocket フレーム** をキャプチャする唯一の取り込み経路です — フローファイルはすべてのテキスト / バイナリフレームのペイロードを保持します。```bash
tats [-v|-q] mitm <flow_file.mitm> -o tokens.db \
[--enrich] [--enrich-cache-dir DIR] [--no-enrich-cache] \
[--append] [--source-tag TAG] [--no-progress] \
[--redact-claims [CLAIMS]] [--no-serve-hint]
pip install mitmproxy が必要です。パッケージが欠けている場合、ツールは明確なエラーを出力します。
mitmproxy でフローファイルをキャプチャします:```bash mitmdump -w session.mitm
tats mitm session.mitm -o tokens.db --enrich
### `cdp` — Chrome / Edge へのライブアタッチ
DevTools Protocol を介して実行中の Chromium 系ブラウザに接続し、
`Network.*` イベントをデータベースへストリーミングします。HTTP リクエスト /
レスポンス(ボディは `Network.getResponseBody` 経由で取得)、WebSocket
アップグレード、および双方向のすべての WebSocket フレームをキャプチャします。
バッファは N イベントごと(デフォルト 25)にデータベースへフラッシュされるため、
ダッシュボードの 5 秒ポーリングは、ブラウザがリクエストを行ってから
数秒以内に新しいトークンを取得します。```bash
tats [-v|-q] cdp [-o tokens.db] \
[--host 127.0.0.1] [--port 9222] [--target ID] \
[--launch-chrome [PATH]] [--flush-every N] \
[--enrich] [--append] [--redact-claims [CLAIMS]]
--launch-chrome)```bashtats cdp -o tokens.db --launch-chrome
tats cdp -o tokens.db
--launch-chrome /opt/google/chrome-canary/chrome
起動されたブラウザは `--remote-debugging-port=<port>` と
新規の一時的な user-data-dir で実行されます。`cdp` コマンドを停止すると(Ctrl-C)、
ブラウザは終了し、一時プロファイルは削除されます。
### すでに実行中のブラウザにアタッチする
自分でブラウザを新規プロファイルで起動し、次に `--launch-chrome` を付けずに `cdp` を実行します:```bash
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
--remote-debugging-port=9222 ^
--user-data-dir="%TEMP%\cdp-profile"
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile
別の user-data-dir を使うことで、個人プロファイルへのアタッチを避け、 実行中のブラウザがデバッグフラグを拒否するのを防ぎます。
デフォルトでは cdp は browser レベルでアタッチし、起動時に存在するすべてのタブ
と、実行中に開かれたすべてのタブ(window.open、Ctrl-click、新しいタブボタン)を追跡します。
すべてのタブは CDP フラットプロトコルセッションマルチプレクサを介して単一の
WebSocket を共有するため、キャプチャ実行中にタブを開いたり閉じたりすることは完全にサポートされています。
各タブのアタッチ / デタッチは、INFO レベルで stderr に 1 行のメモを出力します。
単一のタブに固定し、そのタブが閉じたときにアタッチを終了させたい場合は、 利用可能なターゲットを一覧表示します:```bash curl http://127.0.0.1:9222/json/list
…その後 `--target <id>` を渡します。
Ctrl-C を押して停止します。処理中のバッファの末尾は、プロセスが終了する前にデータベースへフラッシュされます。
### `serve` — Web ダッシュボード
既存のデータベースを読み取り、`127.0.0.1:8765` でシングルページ Web UI を提供します。サーバーは読み取り専用であり、データベースに書き込むことはありません。そのため、実行中の `cdp` または `mitm` の取り込みと並行して実行しても安全です。```bash
tats serve <tokens.db> \
[--host 127.0.0.1] [--port 8765] [--no-browser]
例:```bash
tats serve tokens.db
tats serve tokens.db --port 9000 --no-browser
tats serve tokens.db --host 0.0.0.0
> **警告:** Web UI は、バインドアドレスに到達できる誰にでも、デコードされた JWT ペイロード (クレーム)、トークンフィンガープリント、アクティビティタイムライン、Mermaid グラフを公開します。`--store-tokens` で取り込んだ場合、`/api/token/<fp>` および `/api/export?fps=...` を通じて**生のトークン全体**も公開されます。**認証はありません**。意図的にそうしない限り、`--host` は `127.0.0.1` のままにしてください。
#### リプレイ対応エクスポート
データベースが `--store-tokens` で構築された場合、Tokens タブの展開された各トークンにはワンクリックアクションの行が表示されます:
* **Copy raw** — トークン文字列全体をクリップボードにコピーします。
* **Copy Bearer header** — `Authorization: Bearer <token>`、そのまま貼り付け可能。
* **Copy curl example** — トークンの `aud` (またはその発行者ホスト) を対象とし、ベアラーヘッダーを付加したワンライナー。
* **Download JSON** — raw、claims、observed events、exchanges を含む単一トークンの JSON ファイル。
* **Copy as roadtx** — roadtools トークンキャッシュの JSON 形式 (`tokenType`、`accessToken` / `refreshToken` / `idToken`、`expiresOn`、`tenantId`、`_clientId`、`resource`、`foci`、`scope`)。`.roadtools_auth` ファイルにそのまま貼り付けられます。
* **Download .roadtools_auth** — 同じペイロードをファイルとしてダウンロードします。`.roadtools_auth` にリネームする (または `roadtx <cmd> --tokens-file` で渡す) と、任意の roadtx サブコマンドがそれを読み取ります。
Tokens タブのツールバーには **Export selected for replay** もあり、これは `/api/export?fps=fp1,fp2,...` を呼び出し、最大 200 トークン (raw、claims、events) を 1 つのバンドルにまとめた単一の JSON ドキュメントをダウンロードします。`--store-tokens` がない場合、同じボタンはリプレイ対応エクスポートを可能にするために再取り込みを促すヒントを表示します。
#### コマンドプレビュー
展開された各トークンには、折りたたみ可能な **Command preview** ブロックもあり、トークンの実際のクレーム (`--store-tokens` がオンの場合は生の値全体) を使用して、最も一般的なリプレイ / 検査の呼び出しを事前入力します。各スニペットにはワンクリックの Copy ボタンがあります。正確な内容はトークンタイプによって異なります:
* **任意の JWT:** `roadtx describe -t '<token>'` (ネットワークなしでデコード)。
* **リフレッシュトークン:**
* `roadtx auth --refresh-token '...' -c <client_id> -t <tenant_id>` —
リフレッシュトークンを新しいアクセストークンと交換します。
* `curl -X POST .../oauth2/v2.0/token` — roadtx を実行していないユーザー向けの OAuth 相当のコマンド。
* **アクセス / id / 不明なトークン:**
* `curl -H 'Authorization: Bearer ...' '<aud>'`
* ベアラーヘッダーを設定した Python `requests.get(...)`。
* 同じヘッダーを使用した PowerShell `Invoke-RestMethod`。
* **常に:** `.roadtools_auth` に投入する JSON オブジェクト。
`--store-tokens` がオフの場合、スニペットは `<TOKEN>` をプレースホルダーとしてレンダリングするため、パネルはドキュメント参照として引き続き有用です。
---
## Web UI の詳細
### トップナビゲーション
`Summary | Tokens | Exchanges | FOCI | BroCI | Graph | Sequence`
各タブは `/api/data` の同じインメモリスナップショットから独立してレンダリングされます。タブの切り替えは瞬時に行われ、グラフとシーケンス図はオンデマンドで再レンダリングされ、Tokens タブの現在の選択を反映します。
### Summary
上部にまたがる統計タイル (tokens / access / refresh / id / unknown / used / unused / events / exchanges / FOCI exchanges / BroCI exchanges / hosts)、その後に [Features → Dashboard cards](#dashboard-cards) で説明されているカードのグリッドが続きます。
任意のカードの任意の行をクリックすると、事前フィルタリングされた Tokens タブにジャンプします — たとえば、テナント行をクリックすると、その `tid` を持つトークンにインベントリがフィルタリングされます。
### Tokens
フィルタリング可能でソート可能なインベントリ。複数選択はハイライト / 分離 / シーケンスボタンを制御します。行を展開すると、完全にデコードされた JWT (ヘッダー + ペイロードを生の JSON として)、そのトークンを含むすべてのイベント、およびそれが入力または出力であったすべての交換が表示されます。
### Exchanges
検出されたすべてのトークン間交換のソート可能なリスト — リフレッシュトークンのローテーション、FOCI クロスリデンプション、BroCI ネストされたアプリの交換。BroCI 列には、ブローカー + ネストされたクライアント ID が、検出をトリガーした証拠と並べて表示されます。
### FOCI
2 つのテーブル: FOCI ファミリーでタグ付けされたすべてのリフレッシュトークン (現在、Microsoft は `"1"` のみを発行)、および応答に `foci` フィールドが含まれていたすべての交換。
### BroCI
Nested App Authentication の交換。それぞれについて: ブローカーアプリ (`brk_client_id`)、ネストされたクライアント (`client_id`)、検出をトリガーした証拠 (`brk_client_id`、`brk_redirect_uri`、`brk-<guid>://` リダイレクト URI)、および入力 / 出力トークンのフィンガープリント。
### Graph
トークン ↔ サービスの関係の Mermaid `flowchart LR`。リフレッシュトークンはシリンダーとして、アクセス / id トークンはスタジアムとして描画されます。エッジは発行、提示、交換、ローテーションを示します。ハイライト (Tokens タブから) は黄色のアクセントを追加します。分離は、選択されたトークンとそれらが交換するトークンのみでグラフを再レンダリングします。
### Sequence
キャプチャ順のすべてのイベントの Mermaid シーケンス図。単一のトークンを選択するとそのシーケンスのみが表示されます。複数を選択すると完全なビューが維持されますが、選択されたトークンに星が付きます。設定可能な最大イベント上限 (デフォルト 200、Mermaid シーケンス図は数百メッセージを超えると判読できなくなります)。
---
## Microsoft 固有のサポート
### Family of Client IDs (FOCI)
Microsoft は、「ファミリー」内の 1 つのアプリに発行されたリフレッシュトークンを、同じファミリー内の**他の任意のアプリ**がトークンエンドポイントで引き換えることを許可しています。このツールは、トークンエンドポイントの応答 JSON を解析して `foci` フィールド (現在、唯一知られているファミリーでは常に `"1"`) を探すことで、ワイヤー上の FOCI を検出します。そのような応答で発行されたリフレッシュトークンはファミリー ID でタグ付けされ、専用の **FOCI** タブに表示されます。
`--enrich` が有効な場合、インベントリの app 列は `firstpartyscopes.json` の `foci: true/false` フラグも表示します — これはワイヤー上の検出と一致しない場合があることに注意してください (entrascopes データセットは時に保守的です)。ワイヤー上の `foci` フィールドが常に権威あるシグナルです。
### Brokered Client Init / Nested App Authentication (BroCI / NAA)
Office アドイン、Teams アプリ、Azure Portal は NAA を使用して、ブローカーアプリを通じてネストされたクライアントのトークンを取得します。このツールはリクエスト側で以下を介してこれを検出します:
* `brk_client_id` フォームパラメータ (ブローカーアプリの GUID)、
* `brk_redirect_uri` フォームパラメータ (ブローカーの実際のリダイレクト URI)、
* `brk-<guid>://...` 形式の `redirect_uri` (ここで `<guid>` はブローカー)。
結果として得られるアクセストークンの `appid` / `azp` クレームはネストされたクライアントです。ブローカーはワイヤー上にのみ現れ、JWT クレームとしては決して現れません。ダッシュボードは両側を明確に表示します。
### `ESTSAUTH` セッション Cookie
`ESTSAUTH`、`ESTSAUTHPERSISTENT`、`ESTSAUTHLIGHT`、`SignInStateCookie` は、`Authorization: Bearer` では送信されないが、ブラウザがサイレント認証フローを介して新しいアクセストークンを発行するために使用する Microsoft Entra セッション Cookie です。このツールは、汎用の `auth` 部分文字列ルールで誤って `access` として分類するのではなく、それらを `refresh` (それらの機能的役割) としてラベル付けします。
### entrascopes.com エンリッチメント (`--enrich`)
<https://entrascopes.com/> から `firstpartyscopes.json` (約 2.8 MB、504 のファーストパーティアプリとその FOCI フラグ、リダイレクト URI、スコープ、ブローカー機能) および `resources.json` (約 170 KB、1,750 以上のリソース → 表示名マッピング) を取得してキャッシュします。キャッシュの場所:
| 変数 | デフォルト |
|---|---|
| `$TATS_CACHE` | (最優先; `$BURP_TOKEN_TRACKER_CACHE` は 1 リリースの移行のためのフォールバックとして尊重されます) |
| `$XDG_CACHE_HOME/tats` | (Linux/macOS) |
| `%LOCALAPPDATA%\tats\cache` | (Windows) |
| `~/.cache/tats` | (フォールバック) |
TTL は 7 日です。再取得を強制するには `--no-enrich-cache` を使用します。ツールがオフラインで実行される場合、キャッシュは古いフォールバックとして再利用されます。
`--enrich` がオンの場合、すべての `appid` / `azp` / `client_id` GUID およびすべての GUID または URL の `aud` クレームは、クリック可能な `https://entrascopes.com/?appId=<guid>` リンク付きのフレンドリ名に解決されます。
---
## アーキテクチャ
### ワンショット: ファイル → DB → Web UI```
burp.xml ─┐
.mitm ─┼─→ Tracker ─→ ingest_to_db ─→ tokens.db ─→ Store ─→ /api/data ─→ dashboard
CDP WS ─┘ ▲ │
(live, repeated) └───── --append upserts on every flush ─┘
すべてのソースパスは同じ Tracker オブジェクトを生成します。ingest_to_db
はそれをデータベースの行に変換します。Store は HTTP サーバー用にデータベースを読み取り、
サーバーは /api/data、/api/meta、
/api/token/<fp>、/api/export、/api/graph、/api/sequence で JSON を公開します。
tokens (主キー fp) — フィンガープリント、サンプルプレフィックス、タイプ、
フォーマット、観測されたライフタイム、JSON としての JWT ヘッダー / ペイロード、エンリッチメント
フィールド、派生フィールド (user_identity、exp_unix、tenant_id、
scopes_text)、カンマ区切りの source_tag、raw (完全なトークン
文字列、--store-tokens で取り込まれない限り NULL)、および
security_features (検出された CAE / PoP /
ステップアップマーカーを記述するコンパクトな JSON — セキュリティ機能カードを参照)。
古い v2 / v3 データベースは、追加モードで再度開かれたときに自動移行されます:
v2 → v3 は NULL 許容の raw カラムを追加します; v3 → v4 は NULL 許容の
security_features カラムを追加し、初回オープン時に各トークンの保存された
jwt_payload_json からそれをバックフィルします。既存の行は両方の
カラムを以前の値のまま保持します。events — 観測されたすべてのトークンインタラクション: HTTP リクエスト /
レスポンスまたは WebSocket フレーム。ロール: issued / returned /
presented / used / exchanged-in / ws-frame-sent /
ws-frame-received。接続内のフレームをグループ化するための ws_session_id を
持ちます。exchanges — トークンエンドポイントへのトークンを含むリクエストが
そのレスポンスで新しいトークンを生成したとき。FOCI / BroCI メタデータを記録します。exchange_inputs、exchange_outputs — すべての交換の
各側のトークンフィンガープリント。hosts — 個別の host:port ラベル。meta — スキーマバージョン、ソースリスト、generated_at、last_modified
(ダッシュボードのライブポーリングで使用)、カウント。DB に書き込まれるすべての行は source_tag を持ちます — デフォルトでは
burp:<filename>、mitm:<filename>、または cdp:<host>:<port> ですが、
--source-tag で上書き可能です。同じフィンガープリントが複数の取り込みパスで
見られた場合、source_tag フィールドはカンマ区切りのリストとして蓄積されるため、
ダッシュボードの Sources カードはすべてのトークンの来歴を表示できます。
--append は既存の DB を保持し、トークンに対しては UPSERT でマージし
(使用回数 + 観測されたライフタイムが蓄積され、不明なタイプはアップグレードされます)、
イベント / 交換に対しては INSERT でマージします (seq 番号は既存の最大値を
超えてオフセットされるため、アクティビティタイムラインは単調に保たれます)。
スキーマバージョンの不一致は、サイレントなデータ損失を防ぐためにマージを拒否します。
Web サーバーの /api/meta エンドポイントは meta テーブル (~200
バイト) を返します。ダッシュボードは 5 秒ごとにそれをポーリングし、
last_modified が変化したときのみ完全な /api/data を再取得します。cdp 取り込みパスは
デフォルトで 25 イベントごとにインメモリトラッカーを DB にフラッシュするため、
ブラウザリクエストからダッシュボード更新までの実時間レイテンシは
通常 10 秒未満です。
.burp プロジェクトファイルはサポートされていません。 Save items を使用して
ツールが消費する XML を生成してください。alg=none、および鍵混同攻撃は対象外です。それらには
専用の JWT 監査ツールを使用してください。unknown になり、デフォルトでは非表示になります
(Burp 専用の古いフラグで --include-unknown が設定されている場合を除く)。--enrich は外部 HTTP リクエストを行います
https://entrascopes.com/ に対して。環境がそれを許可しない場合は
このフラグをスキップしてください。| 症状 | 考えられる原因 | 修正 |
|---|---|---|
error: could not parse <file> as XML | バイナリの .burp プロジェクトファイルを取り込もうとしている | Burp で: Proxy → HTTP history → アイテムを選択 → 右クリック → Save items |
error: no <item> elements found | XML が Burp の Save items で生成されたものではない | Burp から再エクスポート; ルート要素は <items> である必要があります |
error: cannot append to DB with schema_version 1 | DB が以前のビルドで作成された | DB を削除して元のソースを再取り込み; スキーマ移行は意図的に自動ではありません |
error: the 'mitm' source needs the mitmproxy Python package | mitmproxy がインストールされていない | pip install mitmproxy |
error: cannot reach Chrome at 127.0.0.1:9222 | Chrome が --remote-debugging-port 付きで起動されていない | cdp サブコマンド の起動のおまじないを参照 |
| CDP はアタッチするがイベントが流れない | ページがまだネットワークリクエストを行っていない、またはすべてのアクティビティが OOPIF / ワーカー内にある (自動アタッチされない) | ページをリロード; タブが登録されたことを確認 (stderr の tab attached: … ログ行を探す) |
no browser-level webSocketDebuggerUrl at /json/version | Chrome のバージョンがブラウザレベルの CDP には古すぎる、または間違った形状を返した | Chrome を更新するか、--target <id> を渡してレガシーの単一タブアタッチを使用 |
target … has no webSocketDebuggerUrl | 別のデバッガ (例: DevTools ウィンドウ) がすでにアタッチされている | DevTools を閉じるか、別のターゲットにアタッチ |
ダッシュボードが Failed to load /api/data を表示 | サーバーがデータベースファイルを読み取れない | DB パスが正しいこと、ファイルが読み取り可能であること、スキーマバージョンが一致することを確認 |
| ライブ更新が届かなくなる | cdp プロセスが終了した、またはネットワークバッファのフラッシュがまだ発火していない | cdp ターミナルでエラーを確認; より迅速な更新のために --flush-every を減らす |
2 つのフィクスチャビルダーが examples/ にあります:```bash
python examples/make_fixture.py examples/fixture.xml tats ingest examples/fixture.xml -o tokens.db --enrich
python examples/make_mitm_fixture.py examples/fixture.mitm tats mitm examples/fixture.mitm -o tokens.db --enrich --append
両方の実行後、`tokens.db` には15個のトークン(Burpから11個 + mitmproxyから4個)、WebSocketフレームイベントを含む23個のイベント、そして3個の交換が含まれています。
### テストスイート```bash
pip install .[test]
pytest
このスイートは、トークン抽出、JWT 解析、Microsoft セッション Cookie の分類、FOCI / BroCI 検出、クレームサマリー、PII の秘匿化、append モードの UPSERT セマンティクスを伴う Burp XML 取り込みパス、および mitmproxy WebSocket フレーム取り込みパス(オプションの mitmproxy 依存関係が欠落している場合は自動スキップ)をカバーしています。```text
$ pytest tests/
============================= test session starts =============================
…
======================== 62 passed in 1.4s =================================
### サーバーをフォアグラウンドで実行する```bash
tats serve tokens.db --no-browser
…そして手動で http://127.0.0.1:8765 を開きます。サーバーはすべての
リクエストとハンドラーのエラーを stderr にログ出力します。
| パス | 目的 |
|---|---|
tats/__init__.py | ツール全体 — パーサー、DB レイヤー、HTTP サーバー、CDP クライアント。tats/static/ からダッシュボードを読み込む |
tats/__main__.py | python -m tats のエントリポイント。インストールされた tats コンソールスクリプトと同じロジック |
tats/static/index.html | {{CSS}} / {{JS}} プレースホルダーを含むダッシュボード HTML の骨組み |
tats/static/style.css | ダッシュボードのスタイリング — 通常の CSS ツールで編集 |
tats/static/app.js | ダッシュボードのロジック — 通常の JS ツール(LSP / lint / formatter)で編集 |
pyproject.toml | パッケージングメタデータ、オプションの extras([mitm]、[test]、[all])、コンソールエントリポイント |
LICENSE | GNU General Public License v3 |
README.md | このファイル |
examples/ | 合成キャプチャ + フィクスチャビルダースクリプト(examples/README.md を参照) |
examples/make_fixture.py | 合成 Burp XML ジェネレーター |
examples/make_mitm_fixture.py | 合成 mitmproxy フローファイルジェネレーター |
examples/fixture.xml | ビルド済み Burp XML フィクスチャ |
examples/fixture.mitm | ビルド済み mitmproxy フローフィクスチャ |
tests/ | pytest スイート(pytest で実行) |
シングルファイル構成は意図的なものです。このツールは、Python が インストールされている誰でも読めて、監査でき、調査に投入できる ように作られています。隠れたセットアップも、評価すべき依存関係 ツリーも、ファイル自体以外の表面もありません。
サブコマンド、スキーマ、ダッシュボードカード、または公開 API
サーフェス(CLI フラグ、/api/* エンドポイント)を変更した場合は、
同じ変更の中でこのファイルの関連セクションを更新してください。
最も乖離しやすいセクション:
GNU General Public License v3.0 以降 — 全文はリポジトリ
ルートの LICENSE ファイルにあります。スクリプトのソースには、
同じものを指す標準の短いヘッダーが含まれています。
GPL v3(または、あなたの選択によりそれ以降のバージョン)の条件の 下で、このツールを再配布および/または改変することができます。いかなる 保証もなく配布されます。完全な条件については LICENSE を参照してください。
aud/api/export?fps=... は、下流のツーリング用に最大 200 個のトークン (raw、claims、events、exchanges) を 1 つの JSON バンドルで返します。これを有効にすると、データベースはまるごと資格情報になります — キャプチャされた任意のセッションをリプレイするために必要なすべてのバイトがそこに含まれます。--redact-claims と組み合わせてデコードされた JWT ビューをスクラブできますが、生のトークンには依然としてその内部にエンコードされた未編集のクレームが含まれていることに注意してください。フラグがオフの場合でも、ダッシュボードのコマンドプレビューブロックはレンダリングされますが、<TOKEN> がプレースホルダーとして使用されるため、構文リファレンスとして機能します。エクスポートボタンは再取り込みを促すヒントを表示します。