Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
TATS — Analysez et suivez les jetons OAuth 2.0, OIDC et Microsoft Entra ID à partir des captures de Burp, mitmproxy ou Chrome DevTools. Visualisez les cycles de vie des jetons, détectez les scopes à risque et exportez les jetons pour rejouer via un tableau de bord interactif. | Kitploit
Outils/GitHubGitHub/icemoonhsv/tats
Sécurité WebTests d'IntrusionGestion des Identités et des Accès (IAM)AuthentificationAnalyse de Journaux
GitHubicemoonhsv/tats

TATS

Analysez et suivez les jetons OAuth 2.0, OIDC et Microsoft Entra ID à partir des captures de Burp, mitmproxy ou Chrome DevTools. Visualisez les cycles de vie des jetons, détectez les scopes à risque et exportez les jetons pour rejouer via un tableau de bord interactif.

Voir le dépôt
7128il y a 16 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

TATS — Token Analysis and Tracking System

Suivez les jetons OAuth 2.0, OIDC et Microsoft Entra ID à travers le trafic réseau capturé. Ingère les exports XML de Burp Suite, les fichiers de flux mitmproxy ou les flux live du Chrome DevTools Protocol dans une base de données SQLite unique, puis sert un tableau de bord web interactif pour filtrer les jetons, parcourir les échanges, repérer les scopes à risque, exporter les jetons pour rejeu et visualiser les cycles de vie des jetons sous forme de graphes Mermaid.

Statut : TATS est stable pour un usage personnel / en engagement. Optimisé pour l'écosystème Microsoft 365 / Entra (FOCI, BroCI/NAA, cookies de session ESTSAUTH, enrichissement entrascopes.com) mais fonctionne contre tout trafic OAuth/OIDC à peu près standard.


Pourquoi il existe

Lorsque vous proxifiez une longue session Microsoft 365 ou Azure via Burp / mitmproxy, la capture résultante est énorme et la plupart des outils soit :

  • N'affichent qu'un seul jeton à la fois (l'extension JWT de Burp), soit
  • Ne suivent pas le dialecte OAuth de Microsoft (FOCI, BroCI, cookies ESTSAUTH), soit
  • Ne suivent pas les trames WebSocket, où Teams / Skype / SignalR envoient des jetons, soit
  • Ne vous disent pas quels jetons sont encore valides à l'instant présent.

Cet outil extrait chaque jeton access / refresh / id observé, les empreinte pour pouvoir corréler le même jeton entre les sources, décode les claims JWT, résout les GUID de client / ressource Microsoft contre entrascopes.com, et restitue l'ensemble du tableau sous forme d'un seul tableau de bord — y compris une vue des chaînes de refresh-token qui suit les échanges inter-applications FOCI et l'émission de jetons d'applications imbriquées BroCI.

Ce projet est destiné principalement à des fins de recherche et d'éducation mais fournit des options telles que l'aperçu de commandes et les fonctionnalités d'export de jetons qui peuvent soutenir certains outils offensifs.


Fonctionnalités

Cœur

  • Trois sources d'ingestion dans un seul outil :
    • ingest — export XML « Save items » de Burp Suite
    • mitm — fichier de flux .mitm de mitmproxy (HTTP et trames WebSocket)
    • cdp — attachement live à Chrome / Edge via le DevTools Protocol (temps réel, capture le HTTP déchiffré TLS et les trames WebSocket sans CA de proxy ; suit chaque onglet existant ET chaque onglet ouvert pendant l'exécution via l'auto-attachement au niveau du navigateur)
  • Un store SQLite canonique unique depuis lequel le tableau de bord lit. Chaque passe d'ingestion peut être exécutée avec --append pour fusionner dans une base de données existante ; les jetons sont upsertés (le nombre d'utilisations + la durée de vie observée s'accumulent), les événements et les échanges sont ajoutés, et le source_tag de la ligne enregistre chaque passe qui a vu le jeton.
  • Tableau de bord web live servi par un serveur HTTP de la stdlib. Interroge la base de données toutes les 5 secondes et re-rend lorsque les données sous-jacentes changent — ainsi une capture CDP en cours met à jour le tableau de bord en quasi temps réel.
  • Aucune dépendance propriétaire pour les chemins du cœur. L'ingestion Burp, la couche base de données, l'interface web et l'attachement CDP sont tous uniquement basés sur la stdlib. L' import mitmproxy est la seule dépendance optionnelle (pip install mitmproxy).

Classification et enrichissement des jetons

  • Clés de corps OAuth (access_token, refresh_token, id_token) et les heuristiques sur les noms de cookies déterminent le type de jeton.
  • Cookies de session Microsoft (ESTSAUTH, ESTSAUTHPERSISTENT, ESTSAUTHLIGHT, SignInStateCookie) sont explicitement reconnus comme des jetons équivalents à des refresh (ils seraient sinon mal classés par l'indice générique de cookie « auth »).
  • Claims JWT (en-tête + payload) décodés et stockés verbatim — jamais tronqués.
  • Microsoft FOCI (Family of Client IDs) détecté via le champ foci dans les réponses du point de terminaison de jeton.
  • Microsoft BroCI / Nested App Authentication détecté via brk_client_id, brk_redirect_uri, et les schémas de redirection brk-<guid>:// dans le corps de la requête.
  • Option --enrich récupère firstpartyscopes.json et resources.json depuis https://entrascopes.com/ et résout les GUID appid / azp / aud en noms conviviaux avec des liens cliquables.

Cartes du tableau de bord

  • Tuiles de résumé — comptages de jetons, hôtes, échanges (avec signalements FOCI / BroCI), et un indicateur de statut d'enrichissement.
  • Utilisateurs — regroupement des jetons par upn / preferred_username / unique_name / email / name, avec repli sur sub@iss ou oid, et exposition séparée des compartiments app-only et identité inconnue. Chaque ligne d'identité affiche un badge captures lorsque l'utilisateur apparaît dans ≥2 source_tags (survie inter-captures, le signal de recherche phare de --append) plus une plage first_seen → last_seen et un bouton timeline qui met en évidence chaque jeton pour cet utilisateur sur l'onglet Diagramme de séquence.
  • Validité des jetons — comptages des jetons d'accès actuellement valides vs expirés, statut d'expiration des refresh-tokens (avec « expiration inconnue » pour les jetons opaques), et une liste top-3 « prochains à expirer » avec auto-refresh de 30 secondes.
  • Clients — chaque application distincte (appid / azp / client_id du corps de formulaire / brk_client_id / brk_nested_id) apparue dans les échanges, avec badges FOCI / brokerable / broker / nested.
  • Audiences — chaque claim aud observé, résolu en noms de ressources entrascopes lorsque possible.
  • Tenants — valeurs tid distinctes avec comptages de jetons / utilisateurs / applications.
  • Hôtes — événements, destinataires bearer distincts, émetteurs distincts, et comptages d'échanges par hôte.
  • Scopes et rôles privilégiés — vérifie le scp / scope / roles de chaque jeton contre une liste de surveillance curatée de permissions Microsoft Graph à fort impact et de scopes de ressources Azure.
  • Incohérences audience / hôte — signale chaque paire (token, host) où le jeton a été utilisé sur un hôte qui ne correspond pas à son claim aud (suggère une fuite d'identifiants ou un usage abusif).
  • Méthodes d'authentification (amr) — distribution pwd / mfa / pop / smartcard.
  • Fonctionnalités de sécurité — signale Continuous Access Evaluation (xms_cc=CP1), la liaison proof-of-possession (claim cnf, avec détection de kid partagé entre audiences), les exigences d'authentification step-up (acrs), et le niveau de contexte d'authentification acr. Chaque ligne est cliquable et filtre l' onglet Tokens pour ne montrer que les jetons portant ce marqueur.
  • Chaînes de refresh-token — parcourt les arêtes d'échange pour identifier les lignées de rotation, la longueur de chaîne la plus longue, et les refresh-tokens inactifs. Chaque chaîne affiche une colonne Δ scopes (scopes ajoutés / supprimés à travers les sauts, avec le diff complet par saut au survol) et signale les chaînes où un scope ajouté correspond à la liste de surveillance des scopes privilégiés avec un badge ⚠ priv — le signal de recherche d'expansion de privilèges de style FOCI / BroCI.
  • Sources — comptages de jetons par source_tag pour voir combien de lignes proviennent de chaque passe d'ingestion.

Onglets Tokens / Exchanges

  • Cliquez sur un en-tête de colonne pour trier.
  • Les cases à cocher multi-sélection pilotent une barre d'outils :
    • Highlight in Graph — accent jaune sur les nœuds sélectionnés.
    • Isolate in Graph — redessine le diagramme en ne montrant que les jetons sélectionnés plus les jetons avec lesquels ils échangent.
    • Show in Sequence — diagramme de séquence ciblé pour le(s) jeton(s) sélectionné(s).
  • Cliquez sur une ligne pour déplier un panneau inline avec l'en-tête + payload JWT complet (JSON brut), tous les événements, les échanges associés, les boutons d'export prêts pour le rejeu (raw / Bearer / curl / JSON / cache de jetons roadtx), et un bloc d'aperçu de commandes avec des extraits copier-coller pour roadtx describe, roadtx auth, curl, Python requests, et PowerShell Invoke-RestMethod.
  • Filtres : puces de type (access / refresh / id / unknown), puces de format (jwt / opaque), menu déroulant used / unused, menu déroulant de validité (any / valid / expired / unknown expiry), FOCI-only, BroCI-only, has-app-match, has-resource-match, plus une recherche en texte libre sur fp / sample / claims / host / app / resource / source_tag / user.
  • Export CSV / JSON des lignes actuellement filtrées + triées.
  • Persistance du hash d'URL — l'onglet actif et chaque état de filtre sont sérialisés dans le hash de l'URL, de sorte que les liens vers des vues filtrées spécifiques sont partageables.

Prise en charge WebSocket

  • Les captures mitmproxy et CDP préservent chaque payload de trame WebSocket texte / binaire. Le contenu des trames est analysé à la recherche de jetons avec le même walker JSON / form / raw-JWT qui traite les corps HTTP.
  • Les jetons trouvés dans les trames génèrent des événements avec le rôle ws-frame-sent / ws-frame-received, la source ws[body_json[<key>]], et un ws_session_id qui regroupe toutes les trames d'une même connexion WebSocket.
  • La poignée de main est capturée comme un événement HTTP normal afin que les cookies / jetons bearer transportés dans l'upgrade soient également suivis.

Confidentialité

  • La base de données stocke des empreintes SHA-256 (12 premiers caractères hex) et un préfixe de 12 caractères de chaque jeton observé. Les chaînes de jetons complètes ne quittent jamais le fichier d'entrée.

  • Le contenu des claims JWT décodés (en-tête + payload, y compris oid, sub, upn, email, tid, listes de scopes, etc.) est stocké verbatim par défaut car c'est tout l'intérêt de l'analyse. Traitez la base de données et toute URL de tableau de bord partagée comme sensibles dès que des JWT sont présents.

  • --redact-claims (disponible sur ingest, mitm, et cdp) remplace les valeurs de claims listées par des placeholders de hachage stables avant qu'elles n'atteignent la base de données. La liste de champs par défaut couvre sub, oid, upn, email, name, unique_name, preferred_username, emails, mail, ipaddr, given_name, family_name. Passez une liste explicite séparée par des virgules (par ex. --redact-claims sub,upn,oid) pour remplacer la valeur par défaut. La même entrée correspond toujours au même placeholder, donc le regroupement Utilisateurs / Tenants du tableau de bord fonctionne toujours sans révéler l'utilisateur.

  • --store-tokens (disponible sur ingest, mitm, et cdp, désactivé par défaut) opte pour l'écriture de la chaîne de jeton complète dans la base de données afin que le tableau de bord puisse offrir :

    • Actions Copy raw / Copy Bearer / Copy curl.
    • Téléchargement du JSON du jeton (raw + claims + événements observés).
    • Copie / Téléchargement en tant que cache de jetons roadtools (déposez le fichier dans .roadtools_auth et n'importe quelle sous-commande roadtx le récupère).
    • Un bloc Command preview par jeton qui pré-remplit les invocations de rejeu les plus courantes — roadtx describe, roadtx auth, curl, Python requests, PowerShell Invoke-RestMethod — en utilisant les claims tid, , et réels du jeton.

Installation

Prérequis

  • Python 3.10+ (utilise une syntaxe de types compatible avec les match-statements et des dataclasses modernes). Testé sur 3.12.
  • Aucune étape de build. Clonez le dépôt et exécutez python -m tats directement.

Dépendances optionnelles

BesoinInstallation
Sous-commande mitmpip install mitmproxy
Capture live depuis Chrome / EdgeAucune — utilise un client WebSocket de la stdlib
--enrich (entrascopes.com)Aucune — utilise urllib.request

Installation rapide

Exécuter depuis un checkout (sans installation) :```bash git clone tats cd tats python -m tats --help

root@kitploit:~
Le HTML / CSS / JS du tableau de bord se trouvent dans `tats/static/` et sont chargés
lors de la première importation, donc aucune étape de build n'est requise — exécutez simplement le module
directement depuis le checkout.

**Installer en tant que package (vous donne le script console `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

Après l'installation, vous pouvez appeler l'outil par son nom court :```bash tats ingest engagement.xml -o tokens.db --enrich tats serve tokens.db

root@kitploit:~
Si vous n'avez besoin que des chemins Burp / CDP, le fichier est entièrement autonome
avec la bibliothèque standard Python — aucune installation ni extras requis.

---

## Démarrage rapide

**Analyser un export XML Burp et ouvrir le tableau de bord :**```bash
tats ingest examples/fixture.xml -o tokens.db --enrich
tats serve tokens.db

Combiner une capture Burp avec un fichier de flux mitmproxy dans une seule base de données :```bash tats ingest engagement.xml -o tokens.db --enrich tats mitm chat-session.mitm -o tokens.db --enrich --append tats serve tokens.db

root@kitploit:~
**Capture en direct depuis un navigateur Chrome (voit le HTTP déchiffré TLS + les trames WebSocket, aucun proxy CA nécessaire) — en laissant l'outil lancer le navigateur :**```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

Le navigateur lancé est terminé et son profil temporaire est supprimé lorsque vous faites Ctrl-C sur la commande cdp.

Si vous préférez vous attacher à un navigateur déjà en cours d'exécution, démarrez-le avec --remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile et exécutez cdp sans --launch-chrome.

Assainir une base de données avant de la partager (anonymisation des données personnelles) :```bash tats ingest engagement.xml -o tokens.db
--enrich --redact-claims

every sub / oid / upn / email / name / unique_name / preferred_username

(and a few related claims) is replaced with a stable hash placeholder

root@kitploit:~
La rédaction est stable en termes de contenu : des valeurs identiques correspondent à des espaces réservés identiques, de sorte que le regroupement par utilisateur du tableau de bord fonctionne toujours sans afficher l'utilisateur.

L'en-tête du tableau de bord affiche `live · updated <time>` une fois que les données commencent à affluer.

---

## Sous-commandes

Chaque sous-commande accepte `--help` pour obtenir la liste canonique des options. Les notes ci-dessous expliquent *quand* et *comment* vous utiliseriez chacune d'elles.

### Options globales

Elles s'appliquent à chaque sous-commande et se placent *avant* le nom de la sous-commande :

* `-v` / `--verbose` — ajoute des lignes de journal INFO (statut d'enrichissement, compteurs de rédaction à l'ingestion). `-vv` ajoute DEBUG (chaque requête au serveur).
* `-q` / `--quiet` — supprime les lignes de journal INFO ; seuls les WARNING et ERROR apparaissent. La ligne de sortie finale destinée à l'utilisateur (par ex. `wrote tokens.db (...)`) et tout diagnostic `error: …` ne sont pas affectés, de sorte que vous verrez toujours ce qui compte depuis un script.
* `--version` — affiche la version de l'outil et quitte.

### `ingest` — export XML de Burp Suite

Lit un XML « Save items » (Proxy → HTTP history → clic droit → Save items). Les fichiers de projet binaires `.burp` ne sont **pas** pris en charge — le format est propriétaire et instable selon les versions de Burp ; exporter les éléments qui vous intéressent est le flux de travail pris en charge.```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]

Exemples :```bash

fresh DB, with Microsoft enrichment

tats ingest burp.xml -o tokens.db --enrich

add another Burp export to an existing DB without losing the first one

tats ingest day2.xml -o tokens.db --append
--source-tag burp:day2

root@kitploit:~
### `mitm` — fichier de flux `.mitm` de mitmproxy

Lit un fichier de flux produit par `mitmdump`, `mitmproxy` ou `mitmweb`. C'est
le seul chemin d'ingestion qui capture les **trames WebSocket** sans session
navigateur active — les fichiers de flux préservent chaque charge utile de
trame texte / binaire.```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]

Nécessite pip install mitmproxy. L'outil émettra une erreur claire si le paquet est manquant.

Capturez un fichier de flux avec mitmproxy :```bash mitmdump -w session.mitm

... drive the browser ...

Ctrl-C to stop

tats mitm session.mitm -o tokens.db --enrich

root@kitploit:~
### `cdp` — attachement en direct à Chrome / Edge

Se connecte à un navigateur de la famille Chromium en cours d'exécution via le DevTools Protocol
et diffuse les événements `Network.*` dans la base de données. Capture les requêtes /
réponses HTTP (avec les corps récupérés via `Network.getResponseBody`), les upgrades
WebSocket, et chaque trame WebSocket dans les deux sens. Le tampon est vidé vers
la base de données tous les N événements (25 par défaut), de sorte que le polling de 5 secondes
du tableau de bord récupère les nouveaux jetons quelques secondes après que le navigateur a effectué la
requête.```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]]

Laisser l'outil lancer le navigateur (--launch-chrome)```bash

auto-detect Chrome / Edge / Chromium / Brave

tats cdp -o tokens.db --launch-chrome

explicit path (useful for non-default installs / sandboxed builds)

tats cdp -o tokens.db
--launch-chrome /opt/google/chrome-canary/chrome

root@kitploit:~
Le navigateur lancé s'exécute avec `--remote-debugging-port=<port>` et un
répertoire de données utilisateur temporaire fraîchement créé. Lorsque vous arrêtez la commande `cdp` (Ctrl-C),
le navigateur est terminé et le profil temporaire est supprimé.

### S'attacher à un navigateur déjà en cours d'exécution

Démarrez le navigateur vous-même, avec un profil vierge, puis exécutez `cdp` sans
`--launch-chrome` :```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

Un user-data-dir distinct évite de s'attacher à un profil personnel et empêche le navigateur en cours d'exécution de refuser le drapeau de débogage.

Par défaut, cdp s'attache au niveau du navigateur et suit chaque onglet qui existe au démarrage AINSI que chaque onglet ouvert pendant l'exécution (window.open, Ctrl-clic, bouton nouvel onglet). Tous les onglets partagent l'unique WebSocket via le multiplexeur de session du protocole plat CDP, donc ouvrir ou fermer des onglets pendant la capture est entièrement pris en charge. Chaque attachement / détachement d'onglet affiche une note d'une ligne sur stderr au niveau INFO.

Si vous préférez vous fixer sur un seul onglet et que l'attachement se termine lorsque cet onglet se ferme, listez les cibles disponibles :```bash curl http://127.0.0.1:9222/json/list

root@kitploit:~
…puis passez `--target <id>`.

Appuyez sur Ctrl-C pour arrêter. La fin de tout tampon en cours est vidée vers la
base de données avant que le processus ne se termine.

### `serve` — tableau de bord web

Lit une base de données existante et sert une interface web monopage sur
`127.0.0.1:8765`. Le serveur est en lecture seule ; il n'écrit jamais dans la
base de données, il est donc sûr de l'exécuter en parallèle d'une ingestion
`cdp` ou `mitm` en cours.```bash
tats serve <tokens.db> \
    [--host 127.0.0.1] [--port 8765] [--no-browser]

Exemples :```bash

default — opens a browser tab automatically

tats serve tokens.db

bind to a different port without auto-launching the browser

tats serve tokens.db --port 9000 --no-browser

(do this only on a trusted network — no auth)

tats serve tokens.db --host 0.0.0.0

root@kitploit:~
> **Avertissement :** l'interface web expose les charges utiles JWT décodées (claims), les empreintes de jetons, la chronologie d'activité et les graphiques Mermaid à quiconque peut atteindre l'adresse d'écoute. Si vous avez ingéré avec `--store-tokens`, elle expose également les **jetons bruts complets** via `/api/token/<fp>` et `/api/export?fps=...`. Il n'y a **aucune authentification**. Gardez `--host` sur `127.0.0.1` sauf si vous en décidez spécifiquement autrement.

#### Export prêt pour le rejeu

Lorsque la base de données a été construite avec `--store-tokens`, chaque jeton développé dans l'onglet Tokens obtient une rangée d'actions en un clic :

* **Copier le brut** — la chaîne de jeton complète dans le presse-papiers.
* **Copier l'en-tête Bearer** — `Authorization: Bearer <token>`, prêt à coller.
* **Copier l'exemple curl** — une commande d'une ligne qui cible l'`aud` du jeton (ou son hôte émetteur) avec l'en-tête bearer attaché.
* **Télécharger le JSON** — un fichier JSON à jeton unique contenant le brut, les claims, les événements observés et les échanges.
* **Copier en roadtx** — la forme JSON d'un cache de jetons roadtools (`tokenType`, `accessToken` / `refreshToken` / `idToken`, `expiresOn`, `tenantId`, `_clientId`, `resource`, `foci`, `scope`). Collez directement dans un fichier `.roadtools_auth`.
* **Télécharger .roadtools_auth** — même charge utile, téléchargée sous forme de fichier. Renommez-le en `.roadtools_auth` (ou passez-le via `roadtx <cmd> --tokens-file`) et n'importe quelle sous-commande roadtx le récupère.

La barre d'outils de l'onglet Tokens dispose également de **Exporter la sélection pour le rejeu**, qui appelle `/api/export?fps=fp1,fp2,...` et télécharge un document JSON unique contenant jusqu'à 200 jetons (brut, claims, événements) en un seul lot. Sans `--store-tokens`, les mêmes boutons affichent une indication pour réingérer avant que l'export prêt pour le rejeu ne devienne possible.

#### Aperçu des commandes

Chaque jeton développé dispose également d'un bloc **Aperçu des commandes** repliable qui pré-remplit les invocations de rejeu / d'inspection les plus courantes en utilisant les claims réels du jeton (et la valeur brute complète lorsque `--store-tokens` est activé). Chaque extrait dispose d'un bouton Copier en un clic. Le mélange exact dépend du type de jeton :

* **Tout JWT :** `roadtx describe -t '<token>'` (décoder sans réseau).
* **Jetons d'actualisation :**
  * `roadtx auth --refresh-token '...' -c <client_id> -t <tenant_id>` — échanger un jeton d'actualisation contre de nouveaux jetons d'accès.
  * `curl -X POST .../oauth2/v2.0/token` — l'équivalent OAuth pour les utilisateurs qui n'utilisent pas roadtx.
* **Jetons d'accès / id / inconnus :**
  * `curl -H 'Authorization: Bearer ...' '<aud>'`
  * Python `requests.get(...)` avec l'en-tête bearer défini.
  * PowerShell `Invoke-RestMethod` avec le même en-tête.
* **Toujours :** l'objet JSON à déposer dans `.roadtools_auth`.

Lorsque `--store-tokens` est désactivé, les extraits s'affichent avec `<TOKEN>` comme espace réservé afin que le panneau reste utile comme référence de documentation.

---

## L'interface web en détail

### Navigation supérieure

`Summary | Tokens | Exchanges | FOCI | BroCI | Graph | Sequence`

Chaque onglet est rendu indépendamment à partir du même instantané en mémoire de `/api/data`. Le changement d'onglet est instantané ; les diagrammes de graphe et de séquence sont re-rendus à la demande et respectent la sélection en cours dans l'onglet Tokens.

### Summary

Des tuiles de statistiques en haut (tokens / access / refresh / id / unknown / used / unused / events / exchanges / FOCI exchanges / BroCI exchanges / hosts) suivies d'une grille de cartes décrites dans
[Fonctionnalités → Cartes du tableau de bord](#dashboard-cards).

Cliquez sur n'importe quelle ligne de n'importe quelle carte pour accéder à un onglet Tokens pré-filtré — par exemple, cliquer sur une ligne de locataire filtre l'inventaire sur les jetons portant ce `tid`.

### Tokens

Inventaire filtrable et triable. La sélection multiple pilote les boutons de mise en surbrillance / isolement / séquence. Le développement d'une ligne affiche le JWT décodé complet (en-tête + charge utile en JSON brut), chaque événement impliquant ce jeton, et chaque échange où il était une entrée ou une sortie.

### Exchanges

Liste triable de chaque échange jeton-contre-jeton détecté — rotations de jetons d'actualisation, échanges croisés FOCI et échanges d'applications imbriquées BroCI. La colonne BroCI affiche les ID client broker + imbriqué côte à côte avec la preuve qui a déclenché la détection.

### FOCI

Deux tableaux : chaque jeton d'actualisation étiqueté avec une famille FOCI (actuellement Microsoft n'émet que `"1"`), et chaque échange dont la réponse portait le champ `foci`.

### BroCI

Les échanges d'authentification d'application imbriquée. Pour chacun : l'application broker (`brk_client_id`), le client imbriqué (`client_id`), la preuve qui a déclenché la détection (`brk_client_id`, `brk_redirect_uri`, URI de redirection `brk-<guid>://`), et les empreintes des jetons d'entrée / sortie.

### Graph

`flowchart LR` Mermaid des relations jeton ↔ service. Les jetons d'actualisation sont dessinés comme des cylindres, les jetons d'accès / id comme des stades. Les arêtes montrent l'émission, la présentation, l'échange et la rotation. La mise en surbrillance (depuis l'onglet Tokens) ajoute un accent jaune ; l'isolement re-rend le graphe avec uniquement les jetons sélectionnés et les jetons avec lesquels ils échangent.

### Sequence

Diagramme de séquence Mermaid de chaque événement dans l'ordre de capture. Sélectionner un seul jeton n'affiche que sa séquence ; en sélectionner plusieurs conserve la vue complète mais met en vedette les jetons sélectionnés. Plafond d'événements maximum configurable (par défaut 200 ; les diagrammes de séquence Mermaid deviennent illisibles au-delà de quelques centaines de messages).

---

## Prise en charge spécifique à Microsoft

### Family of Client IDs (FOCI)

Microsoft permet qu'un jeton d'actualisation émis pour une application d'une « famille » soit échangé au point de terminaison de jeton par **n'importe quelle autre application** de la même famille. L'outil détecte FOCI sur le réseau en analysant le JSON de réponse du point de terminaison de jeton pour un champ `foci` (actuellement toujours `"1"` pour la seule famille connue). Les jetons d'actualisation émis dans une telle réponse sont étiquetés avec l'identifiant de famille et exposés dans l'onglet **FOCI** dédié.

Si `--enrich` est activé, la colonne app de l'inventaire expose également l'indicateur `foci: true/false` de `firstpartyscopes.json` — notez que cela peut être en désaccord avec la détection sur le réseau (le jeu de données entrascopes est parfois conservateur). Le champ `foci` sur le réseau est toujours le signal faisant autorité.

### Brokered Client Init / Nested App Authentication (BroCI / NAA)

Les compléments Office, les applications Teams et le portail Azure utilisent NAA pour acquérir des jetons pour un client imbriqué via une application broker. L'outil détecte cela côté requête via :
* le paramètre de formulaire `brk_client_id` (GUID de l'application broker),
* le paramètre de formulaire `brk_redirect_uri` (URI de redirection réelle du broker),
* un `redirect_uri` de la forme `brk-<guid>://...` (où `<guid>` est le broker).

Le claim `appid` / `azp` du jeton d'accès résultant est le client imbriqué ; le broker n'apparaît que sur le réseau — jamais comme claim JWT. Le tableau de bord expose clairement les deux côtés.

### Cookies de session `ESTSAUTH`

`ESTSAUTH`, `ESTSAUTHPERSISTENT`, `ESTSAUTHLIGHT` et `SignInStateCookie` sont des cookies de session Microsoft Entra qui ne voyagent pas dans `Authorization: Bearer` mais sont utilisés par le navigateur pour générer de nouveaux jetons d'accès via des flux d'authentification silencieuse. L'outil les étiquette comme `refresh` (leur rôle fonctionnel) au lieu de laisser la règle générique de sous-chaîne `auth` les mal classer comme `access`.

### Enrichissement entrascopes.com (`--enrich`)

Récupère et met en cache `firstpartyscopes.json` (~2,8 Mo ; 504 applications first-party avec leur indicateur FOCI, URI de redirection, scopes et capacité broker) et `resources.json` (~170 Ko ; plus de 1 750 mappages ressource → nom d'affichage) depuis <https://entrascopes.com/>. Le cache réside dans :

| Variable | Défaut |
|---|---|
| `$TATS_CACHE` | (priorité la plus élevée ; `$BURP_TOKEN_TRACKER_CACHE` est honoré comme solution de repli pour une migration d'une version) |
| `$XDG_CACHE_HOME/tats` | (Linux/macOS) |
| `%LOCALAPPDATA%\tats\cache` | (Windows) |
| `~/.cache/tats` | (repli) |

Le TTL est de 7 jours. Utilisez `--no-enrich-cache` pour forcer une nouvelle récupération. Le cache est réutilisé comme repli obsolète lorsque l'outil est exécuté hors ligne.

Lorsque `--enrich` est activé, chaque GUID `appid` / `azp` / `client_id` et chaque claim `aud` GUID-ou-URL est résolu en un nom convivial avec un lien cliquable `https://entrascopes.com/?appId=<guid>`.

---

## Architecture

### One-shot : fichier → DB → interface web```
  burp.xml ─┐
   .mitm   ─┼─→ Tracker ─→ ingest_to_db ─→ tokens.db ─→ Store ─→ /api/data ─→ dashboard
   CDP WS  ─┘                  ▲                                       │
            (live, repeated)   └───── --append upserts on every flush ─┘

Chaque chemin source produit le même objet Tracker. ingest_to_db le transforme en lignes dans la base de données. Store lit la base de données pour le serveur HTTP, qui expose du JSON via /api/data, /api/meta, /api/token/<fp>, /api/export, /api/graph et /api/sequence.

Schéma de base de données (v4)

  • tokens (clé primaire fp) — empreinte, préfixe d'échantillon, type, format, durée de vie observée, en-tête / payload JWT en JSON, champs d'enrichissement, champs dérivés (user_identity, exp_unix, tenant_id, scopes_text), source_tag séparé par des virgules, raw (chaîne de jeton complète, NULL sauf si ingéré avec --store-tokens), et security_features (JSON compact décrivant les marqueurs CAE / PoP / step-up détectés — voir la carte Security features). Les bases de données v2 / v3 plus anciennes migrent automatiquement lorsqu'elles sont rouvertes en mode append : v2 → v3 ajoute la colonne nullable raw ; v3 → v4 ajoute la colonne nullable security_features et la remplit à partir du jwt_payload_json stocké de chaque jeton lors de la première ouverture. Les lignes préexistantes conservent les deux colonnes à leurs valeurs précédentes.
  • events — chaque interaction de jeton observée : requête / réponse HTTP ou trame WebSocket. Rôles : issued / returned / presented / used / exchanged-in / ws-frame-sent / ws-frame-received. Porte ws_session_id pour regrouper les trames au sein d'une connexion.
  • exchanges — lorsqu'une requête portant un jeton vers un endpoint de jeton a produit de nouveaux jetons dans sa réponse. Enregistre les métadonnées FOCI / BroCI.
  • exchange_inputs, exchange_outputs — empreintes de jetons de chaque côté de chaque échange.
  • hosts — libellés host:port distincts.
  • meta — version du schéma, liste des sources, generated_at, last_modified (utilisé par le polling en direct du tableau de bord), compteurs.

Étiquetage des sources et mode append

Chaque ligne écrite dans la base de données porte un source_tag — par défaut burp:<filename>, mitm:<filename>, ou cdp:<host>:<port>, mais surchargeable via --source-tag. Lorsque la même empreinte est vue par plus d'une passe d'ingestion, le champ source_tag s'accumule sous forme de liste séparée par des virgules, afin que la carte Sources du tableau de bord puisse afficher la provenance de chaque jeton.

--append conserve une base de données existante et y fusionne via UPSERT pour les jetons (les compteurs d'utilisation + la durée de vie observée s'accumulent, les types inconnus sont mis à niveau) et INSERT pour les événements / échanges (avec leurs numéros seq décalés au-delà du maximum existant, afin que la chronologie d'activité reste monotone). Une incompatibilité de version de schéma refuse la fusion pour prévenir une perte silencieuse de données.

Mises à jour en direct

L'endpoint /api/meta du serveur web renvoie la table meta (~200 octets). Le tableau de bord l'interroge toutes les 5 secondes et ne récupère à nouveau l'intégralité de /api/data que lorsque last_modified change. Le chemin d'ingestion cdp vide son tracker en mémoire vers la base de données tous les 25 événements par défaut, afin que la latence en temps réel entre une requête du navigateur et une mise à jour du tableau de bord soit généralement < 10 secondes.


Limitations

  • Les fichiers de projet Burp .burp ne sont pas pris en charge. Utilisez Save items pour produire le XML que l'outil consomme.
  • Aucune gestion de CA proxy. Cet outil n'intercepte pas TLS lui-même. Utilisez-le en aval de Burp / mitmproxy, ou utilisez le chemin CDP qui voit le trafic déchiffré TLS depuis l'intérieur du navigateur.
  • L'attachement CDP couvre les cibles de page de premier niveau. Les iframes hors processus (OOPIFs) et les workers dédiés ne sont pas auto-attachés récursivement, donc les événements qui transitent par ces types de cibles peuvent être manqués. Pour les flux Microsoft / OAuth autour desquels cet outil est conçu, l'attachement de page de premier niveau capture tout ce qui compte.
  • Aucune vérification de signature sur les JWT. L'outil décode les claims pour l'affichage ; la vérification de signature, alg=none et les attaques de confusion de clé sont hors périmètre. Utilisez un auditeur JWT dédié pour cela.
  • Faux positifs de jetons opaques. L'heuristique « est-ce un jeton ? » traite toute chaîne URL-safe de 20+ caractères dans des contextes de forme OAuth comme un jeton. De longs identifiants aléatoires peuvent être signalés à tort. Les jetons dont le type ne peut pas être inféré finissent en unknown et sont masqués par défaut sauf si --include-unknown est défini sur l'ancien flag (Burp uniquement).
  • --enrich effectue des requêtes HTTP sortantes vers https://entrascopes.com/. Ignorez le flag si votre environnement ne le permet pas.
  • L'interface web n'a aucune authentification. Liez-la à localhost sauf si vous avez placé une autre couche d'authentification devant.

Dépannage

SymptômeCause probableCorrectif
error: could not parse <file> as XMLTentative d'ingestion d'un fichier de projet .burp binaireDans Burp : Proxy → HTTP history → sélectionner les éléments → clic droit → Save items
error: no <item> elements foundLe XML n'a pas été produit par Save items de BurpRéexportez depuis Burp ; l'élément racine doit être <items>
error: cannot append to DB with schema_version 1La base de données a été créée par une version antérieureSupprimez la base de données et réingérez les sources d'origine ; la migration de schéma n'est intentionnellement pas automatique
error: the 'mitm' source needs the mitmproxy Python packagemitmproxy n'est pas installépip install mitmproxy
error: cannot reach Chrome at 127.0.0.1:9222Chrome n'a pas été démarré avec --remote-debugging-portVoir l'incantation de lancement dans cdp subcommand
CDP s'attache mais aucun événement ne circuleLa page n'a pas encore effectué de requêtes réseau, ou toute l'activité est dans un OOPIF / worker (non auto-attaché)Rechargez la page ; confirmez que les onglets ont été enregistrés (cherchez les lignes de log tab attached: … sur stderr)
no browser-level webSocketDebuggerUrl at /json/versionLa version de Chrome est trop ancienne pour le CDP au niveau navigateur, ou il a renvoyé une forme incorrecteMettez à jour Chrome, ou passez --target <id> pour utiliser l'attachement mono-onglet hérité
target … has no webSocketDebuggerUrlUn autre débogueur (par ex. la fenêtre DevTools) est déjà attachéFermez DevTools, ou attachez-vous à une autre cible
Le tableau de bord affiche Failed to load /api/dataLe serveur ne peut pas lire le fichier de base de donnéesVérifiez que le chemin de la base de données est correct, que le fichier est lisible et que la version du schéma correspond
Les mises à jour en direct cessent d'arriverLe processus cdp s'est arrêté ou le vidage du tampon réseau ne s'est pas encore déclenché

Développement

Fixtures de smoke-test

Deux constructeurs de fixtures se trouvent dans examples/ :```bash

Burp XML fixture (HTTP-only, includes FOCI + BroCI exchanges)

python examples/make_fixture.py examples/fixture.xml tats ingest examples/fixture.xml -o tokens.db --enrich

mitmproxy flow fixture (HTTP + WebSocket frames carrying tokens)

python examples/make_mitm_fixture.py examples/fixture.mitm tats mitm examples/fixture.mitm -o tokens.db --enrich --append

root@kitploit:~
Après les deux exécutions, `tokens.db` contient 15 jetons (11 de Burp + 4 de
mitmproxy), 23 événements dont un événement de trame WebSocket, et 3
échanges.

### Suite de tests```bash
pip install .[test]
pytest

La suite couvre l'extraction de jetons, l'analyse JWT, la classification des cookies de session Microsoft, la détection FOCI / BroCI, le résumé des revendications, la rédaction des PII, le chemin d'ingestion XML Burp avec la sémantique UPSERT en mode ajout, et le chemin d'ingestion des trames WebSocket mitmproxy (automatiquement ignoré lorsque la dépendance optionnelle mitmproxy est absente).```text $ pytest tests/ ============================= test session starts ============================= … ======================== 62 passed in 1.4s =================================

root@kitploit:~
### Exécution du serveur au premier plan```bash
tats serve tokens.db --no-browser

…et ouvrez http://127.0.0.1:8765 manuellement. Le serveur journalise chaque requête et toute erreur de gestionnaire sur stderr.

Arborescence des fichiers

CheminRôle
tats/__init__.pyL'outil complet — parseurs, couche BD, serveur HTTP, client CDP ; charge le tableau de bord depuis tats/static/
tats/__main__.pyPoint d'entrée pour python -m tats ; même logique que le script console tats installé
tats/static/index.htmlSquelette HTML du tableau de bord avec les espaces réservés {{CSS}} / {{JS}}
tats/static/style.cssStyle du tableau de bord — à modifier avec vos outils CSS habituels
tats/static/app.jsLogique du tableau de bord — à modifier avec vos outils JS habituels (LSP / lint / formateur)
pyproject.tomlMétadonnées d'empaquetage, extras optionnels ([mitm], [test], [all]), point d'entrée console
LICENSEGNU General Public License v3
README.mdCe fichier
examples/Captures synthétiques + scripts de construction de fixtures (voir examples/README.md)
examples/make_fixture.pyGénérateur XML Burp synthétique
examples/make_mitm_fixture.pyGénérateur de fichier de flux mitmproxy synthétique
examples/fixture.xmlFixture XML Burp pré-construite
examples/fixture.mitmFixture de flux mitmproxy pré-construite
tests/Suite pytest (à exécuter avec pytest)

La structure en fichier unique est délibérée : l'outil est conçu pour être lu, audité et intégré dans des investigations par toute personne disposant de Python installé. Il n'y a pas de configuration cachée, pas d'arbre de dépendances à évaluer, et aucune surface autre que le fichier lui-même.

Maintenir ce README

Si vous modifiez les sous-commandes, le schéma, les cartes du tableau de bord ou la surface d'API publique (options CLI, points de terminaison /api/*), mettez à jour les sections pertinentes de ce fichier dans la même modification. Les sections les plus susceptibles de dériver :

  • Fonctionnalités — lors de l'ajout de sources d'ingestion ou de cartes du tableau de bord
  • Sous-commandes — lors de la modification des options
  • Prise en charge spécifique à Microsoft — lorsque la logique de détection change
  • Architecture — lorsque le schéma ou le flux de mise à jour en direct change
  • Dépannage — lorsqu'un nouveau message d'erreur apparaît

Licence

GNU General Public License v3.0 ou ultérieure — texte intégral dans le fichier LICENSE à la racine du dépôt. Le code source du script porte l'en-tête court standard pointant vers le même texte.

Vous pouvez redistribuer et/ou modifier l'outil selon les termes de la GPL v3 (ou toute version ultérieure, à votre choix). Il est distribué sans aucune garantie ; consultez la LICENSE pour les termes complets.

Télécharger l’outil
appid
aud
  • /api/export?fps=... renvoyant jusqu'à 200 jetons (raw, claims, événements, échanges) dans un seul bundle JSON pour l'outillage en aval.
  • Activer ceci transforme la base de données en un identifiant en gros — chaque octet nécessaire pour rejouer n'importe quelle session capturée s'y trouve. Combinez avec --redact-claims pour nettoyer la vue JWT décodée, mais sachez que le jeton brut porte toujours les claims non expurgés encodés à l'intérieur. Lorsque l'option est désactivée, le bloc d'aperçu de commandes du tableau de bord s'affiche toujours, juste avec <TOKEN> comme placeholder pour qu'il fonctionne comme une référence de syntaxe ; les boutons d'export affichent un indice pour ré-ingérer.

    Vérifiez le terminal cdp pour les erreurs ; réduisez --flush-every pour des mises à jour plus réactives