AzureHound

MFA work around:

First Execute:

$body = @{
    "client_id" =     "1950a258-227b-4e31-a9cf-717495945fc2"
    "resource" =      "https://graph.microsoft.com"
}
$UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
$Headers=@{}
$Headers["User-Agent"] = $UserAgent
$authResponse = Invoke-RestMethod `
    -UseBasicParsing `
    -Method Post `
    -Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" `
    -Headers $Headers `
    -Body $body
$authResponse

Then execute:

$body=@{
    "client_id" =  "1950a258-227b-4e31-a9cf-717495945fc2"
    "grant_type" = "urn:ietf:params:oauth:grant-type:device_code"
    "code" =       $authResponse.device_code
}
$Tokens = Invoke-RestMethod `
    -UseBasicParsing `
    -Method Post `
    -Uri "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0" `
    -Headers $Headers `
    -Body $body
$Tokens

Execute Azure hound:

# download latest release from:
# https://github.com/BloodHoundAD/AzureHound
.\azurehound.exe list -t offsecad.onmicrosoft.com -u USER@TEST.onmicrosoft.com -p "PASSWORD" -o azurehound.json

## If using Refresh token:
.\azurehound.exe list -r $Tokens.refresh_token -o .\Cloud\azurehound.json -t offsecad.onmicrosoft.com

Azure Bloodhound custom queries:

Save the following @ ~/appdata/roaming/customerqueries.json

{
    "queries": [
                    
                    {
                        "name": "Return All Azure Users that are part of the 'Global Administrator' Role",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p =(n)-[r:AZGlobalAdmin*1..]->(m) RETURN p"
                        }]
                    },
                    {
                        "name": "Return All On-Prem users with edges to Azure",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH  p=(m:User)-[r:AZResetPassword|AZOwns|AZUserAccessAdministrator|AZContributor|AZAddMembers|AZGlobalAdmin|AZVMContributor|AZOwnsAZAvereContributor]->(n) WHERE m.objectid CONTAINS 'S-1-5-21' RETURN p"
                        }]
                    },
                    {
                        "name": "Find all paths to an Azure VM",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p = (n)-[r]->(g:AZVM) RETURN p"
                        }]
                    },
                    {
                        "name": "Find all paths to an Azure KeyVault",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p = (n)-[r]->(g:AZKeyVault) RETURN p"
                        }]
                    },
                    {
                        "name": "Return All Azure Users and their Groups (Warning: Heavy)",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p=(m:AZUser)-[r:AZMemberOf*1..]->(n) WHERE NOT m.objectid CONTAINS 'S-1-5' RETURN p"
                        }]
                    },
		    {
                        "name": "Return GUEST Azure Users and their Groups",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p=(m:AZUser)-[r:AZMemberOf*1..]->(n) WHERE NOT m.objectid CONTAINS 'S-1-5' AND m.userprincipalname=~ '(?i).*#EXT#.*' RETURN p"
                        }]
                    },
		    {
                        "name": "Return All Azure Users and their Admin Roles",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p=(n)-[:AZHasRole|AZMemberOf*1..]->(:AZRole) RETURN p"
                        }]
                    },
		    {
                        "name": "Return All Azure Users and their owned Devices (Warning: Heavy)",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p=(d:AZDevice)<-[r1:AZOwns]->(m:AZUser) RETURN p"
                        }]
                    },
		    {
                        "name": "Return All Azure Admins and their owned Devices",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p=(d:AZDevice)<-[r1:AZOwns]->(m:AZUser)<-[r2:AZHasRole]->(n) RETURN p"
                        }]
                    },
                    {
                        "name": "Return All Azure AD Groups that are synchronized with On-Premise AD",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH (n:Group) WHERE n.objectid CONTAINS 'S-1-5' AND n.azsyncid IS NOT NULL RETURN n"
                        }]
                    },
                    {
                        "name": "Find all Privileged Service Principals",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p = (g:AZServicePrincipal)-[r]->(n) RETURN p"
                        }]
                    },
                    {
                        "name": "Find all Owners of Azure Applications",
                        "category": "Azure",
                        "queryList": [{
                            "final": true,
                            "query": "MATCH p = (n)-[r:AZOwns]->(g:AZApp) RETURN p"
                        }]
                    },
                    {
                        "name": "Find the Shortest path to a high value target from an owned object",
                        "category": "Azure",
                        "queryList": [
                            {
                                "final": true,
                                "query": "MATCH p=shortestPath((g {owned:true})-[*1..]->(n {highvalue:true})) WHERE  g<>n return p"
                            }
                        ]
                    },
                        {
                        "name": "Find the Shortest path to a unconstrained delegation system from an owned object",
                        "category": "Azure",
                        "queryList": [
                            {
                                "final": true,
                                "query": "MATCH (n) MATCH p=shortestPath((n)-[*1..]->(m:Computer {unconstraineddelegation: true})) WHERE NOT n=m AND n.owned = true RETURN p"
                            }
                        ]
                    },
{
      "name": "Return all Members of the 'Global Administrator' Role",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p =(n)-[r:AZGlobalAdmin*1..]->(m) RETURN p"
        }
      ]
    },
    {
      "name": "Return all Members of High Privileged Roles",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(n)-[:AZHasRole|AZMemberOf*1..2]->(r:AZRole WHERE r.displayname =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|PRIVILEGED AUTHENTICATION ADMINISTRATOR') RETURN p"
        }
      ]
    },
    {
      "name": "Return all Members of High Privileged Roles that are synced from OnPrem AD",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(n WHERE n.onpremisesyncenabled = true)-[:AZHasRole|AZMemberOf*1..2]->(r:AZRole WHERE r.displayname =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|PRIVILEGED AUTHENTICATION ADMINISTRATOR') RETURN p"
        }
      ]
    },
        {
      "name": "Return all Azure Users that are synced from OnPrem AD",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZUser WHERE n.onpremisesyncenabled = true) RETURN n",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Return all Azure Groups that are synced from OnPrem AD",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (g:AZGroup {onpremsyncenabled: True}) RETURN g"
        }
      ]
    },
        {
      "name": "Return all Owners of Azure Applications",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (n)-[r:AZOwns]->(g:AZApp) RETURN p"
        }
      ]
    },
    {
      "name": "Return all Azure Subscriptions",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZSubscription) RETURN n"
        }
      ]
    },
    {
      "name": "Return all Azure Subscriptions and their direct Controllers",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (n)-[r:AZOwns|AZUserAccessAdministrator]->(g:AZSubscription) RETURN p"
        }
      ]
    },
    {
      "name": "Return all principals with the UserAccessAdministrator Role against Subscriptions",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (u)-[r:AZUserAccessAdministrator]->(n:AZSubscription) RETURN p"
        }
      ]
    },
    {
      "name": "Return all prinicpals with the UserAccessAdministrator Role",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (u)-[r:AZUserAccessAdministrator]->(n) RETURN p"
        }
      ]
    },
    {
      "name": "Return all Azure Users that DON'T hold an Azure Role but the RBAC Role \"User Access Administrator\"",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u:AZUser) WHERE NOT EXISTS((u)-[:AZMemberOf|AZHasRole*1..]->(:AZRole)) AND EXISTS((u)-[:AZUserAccessAdministrator]->()) RETURN u"
        }
      ]
    },
    {
      "name": "Return all Azure Principals that DON'T hold an Azure Role but the RBAC Role \"User Access Administrator\"",
      "category": "Azure - General",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u) WHERE NOT EXISTS((u)-[:AZMemberOf|AZHasRole*1..]->(:AZRole)) AND EXISTS((u)-[:AZUserAccessAdministrator]->()) RETURN u"
        }
      ]
    },{
      "name": "Find all Azure Users with a Path to High Value Targets",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (m:AZUser),(n {highvalue:true}),p=shortestPath((m)-[r*1..]->(n)) WHERE NONE (r IN relationships(p) WHERE type(r)= \"GetChanges\") AND NONE (r in relationships(p) WHERE type(r)=\"GetChangesAll\") AND NOT m=n RETURN p",
          "allowCollapse": true
        }
      ]
    },
                {
      "name": "Find OnPrem synced Users with Paths to High Value Targets",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (m:AZUser WHERE m.onpremisesyncenabled = true),(n {highvalue:true}),p=shortestPath((m)-[r*1..]->(n)) WHERE NONE (r IN relationships(p) WHERE type(r)= \"GetChanges\") AND NONE (r in relationships(p) WHERE type(r)=\"GetChangesAll\") AND NOT m=n RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths to High Value Roles",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZRole WHERE n.displayname =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|PRIVILEGED AUTHENTICATION ADMINISTRATOR'), (m), p=shortestPath((m)-[r*1..]->(n)) WHERE NOT m=n RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find Azure Applications with Paths to High Value Targets",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (m:AZApp),(n {highvalue:true}),p=shortestPath((m)-[r*1..]->(n)) WHERE NONE (r IN relationships(p) WHERE type(r)= \"GetChanges\") AND NONE (r in relationships(p) WHERE type(r)=\"GetChangesAll\") AND NOT m=n RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find all Paths to Azure VMs",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (n)-[r]->(g:AZVM) RETURN p"
        }
      ]
    },
        {
      "name": "Find shortest Path from Owned Azure Users to VMs",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZVM) MATCH p = shortestPath((m:AZUser{owned: true})-[*..]->(n)) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find all Paths to Azure KeyVaults",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (n)-[r]->(g:AZKeyVault) RETURN p"
        }
      ]
    },
    {
      "name": "Find all Paths to Azure KeyVaults from Owned Principals",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = ({owned: true})-[r]->(g:AZKeyVault) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths to Azure Subscriptions",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZSubscription), (m), p=shortestPath((m)-[r*1..]->(n)) WHERE NOT m=n RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find the Paths to Resources from Azure Users that DON'T hold an Azure Role but the RBAC Role \"User Access Administrator\"",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(u:AZUser)-[:AZUserAccessAdministrator]->(target) WHERE NOT EXISTS((u)-[:AZMemberOf|AZHasRole*1..]->(:AZRole)) RETURN u, p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find the Paths to Resources from Azure Principals that DON'T hold an Azure Role but the RBAC \"User Access Administrator\"",
      "category": "Azure - Paths",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(u)-[:AZUserAccessAdministrator]->(target) WHERE NOT EXISTS((u)-[:AZMemberOf|AZHasRole*1..]->(:AZRole)) RETURN u, p",
          "allowCollapse": true
        }
      ]
    },{
      "name": "Return all Service Principals with MS Graph AZMGGrantAppRoles rights -> PrivEsc Path to Global Admin",
      "category": "Azure - MS Graph",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(n)-[r:AZMGGrantAppRoles]->(o:AZTenant) RETURN p",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Return all Service Principals with MS Graph App Role Assignments",
      "category": "Azure - MS Graph",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(m:AZServicePrincipal)-[r:AZMGAppRoleAssignment_ReadWrite_All|AZMGApplication_ReadWrite_All|AZMGDirectory_ReadWrite_All|AZMGGroupMember_ReadWrite_All|AZMGGroup_ReadWrite_All|AZMGRoleManagement_ReadWrite_Directory|AZMGServicePrincipalEndpoint_ReadWrite_All]->(n:AZServicePrincipal) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Return all direct Controllers of MS Graph",
      "category": "Azure - MS Graph",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (n)-[r:AZAddOwner|AZAddSecret|AZAppAdmin|AZCloudAppAdmin|AZMGAddOwner|AZMGAddSecret|AZOwns]->(g:AZServicePrincipal {appdisplayname: \"Microsoft Graph\"}) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths to MS Graph",
      "category": "Azure - MS Graph",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n) WHERE NOT n.displayname=\"Microsoft Graph\" WITH n MATCH p = shortestPath((n)-[r*1..]->(g:AZServicePrincipal {appdisplayname: \"Microsoft Graph\"})) WHERE n<>g RETURN p",
          "allowCollapse": true
        }
      ]
    },{
      "name": "Return all Azure Service Principals",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (sp:AZServicePrincipal) RETURN sp",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Find all VMs with a tied Managed Identity",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(:AZVM)-[:AZManagedIdentity]->(n) RETURN p",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Return all Azure Service Principals that are Managed Identities",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (sp:AZServicePrincipal {serviceprincipaltype: 'ManagedIdentity'}) RETURN sp",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Find all Azure Privileged Service Principals",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p = (g:AZServicePrincipal)-[r]->(n) RETURN p"
        }
      ]
    },
    {
      "name": "Find shortest Paths from Owned Azure Users to Azure Service Principals",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u:AZUser {owned: true}), (m:AZServicePrincipal) MATCH p = shortestPath((u)-[*..]->(m)) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths from Owned Azure Users to Azure Service Principals that are Managed Identities",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u:AZUser {owned: true}), (m:AZServicePrincipal {serviceprincipaltype: 'ManagedIdentity'}) MATCH p = shortestPath((u)-[*..]->(m)) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths from all Azure Users to Azure Service Principals that are Managed Identities",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u:AZUser), (m:AZServicePrincipal {serviceprincipaltype: 'ManagedIdentity'}) MATCH p = shortestPath((u)-[*..]->(m)) RETURN p",
          "allowCollapse": true
        }
      ]
    },
        {
      "name": "Find all Service Principals that are Managed Identities an have a Path to an Azure Key Vault",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (m:AZServicePrincipal {serviceprincipaltype: 'ManagedIdentity'})-[*]->(kv:AZKeyVault) WITH collect(m) AS managedIdentities MATCH p = (n)-[r]->(kv:AZKeyVault) WHERE n IN managedIdentities RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find Paths from Managed Identities tied to a VM with a path to a Key Vault",
      "category": "Azure - Service Principals",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p1 = (:AZVM)-[:AZManagedIdentity]->(n) WITH collect(n) AS managedIdentities MATCH p2 = (m:AZServicePrincipal {serviceprincipaltype: 'ManagedIdentity'})-[*]->(kv:AZKeyVault) WHERE m IN managedIdentities RETURN p2",
          "allowCollapse": true
        }
      ]
    },{
      "name": "Return all Users and Azure Users possibly related to AADConnect",
      "category": "Azure - AADConnect",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (u) WHERE (u:User OR u:AZUser) AND (u.name =~ '(?i)^MSOL_|.*AADConnect.*' OR u.userprincipalname =~ '(?i)^sync_.*') OPTIONAL MATCH (u)-[:HasSession]->(s:Session) RETURN u, s",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find all Sessions of possibly AADConnect related Accounts",
      "category": "Azure - AADConnect",
      "queryList": [
        {
          "final": true,
          "query": "MATCH p=(m:Computer)-[:HasSession]->(n) WHERE (n:User OR n:AZUser) AND ((n.name =~ '(?i)^MSOL_|.*AADConnect.*') OR (n.userPrincipalName =~ '(?i)^sync_.*')) RETURN p",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find all AADConnect Servers (extracted from the SYNC_ Account names)",
      "category": "Azure - AADConnect",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZUser) WHERE n.name =~ '(?i)^SYNC_(.*?)_(.*?)@.*' WITH n, split(n.name, '_')[1] AS computerNamePattern MATCH (c:Computer) WHERE c.name CONTAINS computerNamePattern RETURN c",
          "allowCollapse": true
        }
      ]
    },
    {
      "name": "Find shortest Paths to AADConnect Servers from Owned Users",
      "category": "Azure - AADConnect",
      "queryList": [
        {
          "final": true,
          "query": "MATCH (n:AZUser) WHERE n.name =~ '(?i)^SYNC_(.*?)_(.*?)@.*' WITH n, split(n.name, '_')[1] AS computerNamePattern MATCH (c:Computer) WHERE c.name CONTAINS computerNamePattern WITH collect(c) AS computers MATCH p = shortestPath((u:User)-[*]-(c:Computer)) WHERE c IN computers AND length(p) > 0 AND u.owned = true RETURN u, p",
          "allowCollapse": true
        }
      ]
    }


                ]
            }



Last updated