Skip to content

ROADtools Token eXchange (roadtx)

Dirk-jan edited this page Aug 20, 2024 · 26 revisions

ROADtools Token eXchange, or roadtx in short, is a tool to automate and implement authentication and registration flows against Azure AD. It is focused around tokens, such as (primary) refresh tokens and access tokens.

It can do the following:

  • Register and join devices to Azure AD.
  • Request Primary Refresh Tokens from user credentials or other valid tokens.
  • Use Primary Refresh Tokens in a similar way as the Web Account Manager (WAM) in Windows does.
  • Perform all kind of Oauth2 token redemption flows.
  • Perform interactive logins based on Browser SSO by injecting the Primary Refresh Token into the authentication flow.
  • Add SSO capabilities to Chrome via the Windows 10 accounts plugin and a custom browsercore implementation.
  • Automate sign-ins, MFA and token requesting to various resources in Azure AD by using Selenium.
  • Possibility to load credentials and MFA TOTP seeds from a KeePass database to use in automated flows.
  • Provision and use Windows Hello for Business keys.

This page describes the commands and concepts. For more context, read the roadtx release blog.

Authentication

Authentication in the OAuth2 token flows that Azure AD uses always work with two important parts. A client, specified with -c or --client, which is the app we are using or impersonating, and a resource, specified with -r or --resource that we are requesting access to. In many cases, the client will be the Azure AD PowerShell module, the Azure CLI, or a client such as Teams when dealing with Microsoft 365 services. The resource is where the data is stored that we want to access. For internal Azure AD operations, this will be the Azure AD Graph or the Microsoft Graph. Clients are identified by a GUID, and resources by a GUID or a URL, but in roadtx you can also use one of the built-in aliases that will automatically translate to the right GUID/URL. You can list them with roadtx listaliases. These aliases work in any command requiring a client or resource parameter.

For example:

roadtx gettokens -u myuser@mytenant -p mypassword -c msteams -r msgraph
roadtx interactiveauth -c msteams -r https://graph.microsoft.com

Important: if you do not specify a client or resource, it will default to the client ID of the Azure AD PowerShell module and the resource Azure AD graph (graph.windows.net). So if you want to have a token for the Microsoft Graph instead, you always have to specify it or you will get an "invalid audience" error when using the token.

The gettokens or auth module can be used to request access tokens and/or refresh tokens for various services. It uses the authentication options offered by roadlib, so while it is flexible it is not designed to work seamlessly with .prt files from disk or device credentials.

You will likely use this as initial authentication method before calling the other roadtx functions, and it is a useful tool to work with refresh tokens. See the ROADrecon documentation for examples of what you can use in this module.

Examples:

Request tokens for AAD Graph with a username and password

roadtx gettokens -u user@iminyour.cloud -p mypassword -r aadgraph

Use a refresh token to request a token for the Microsoft Graph:

roadtx gettokens --refresh-token <token> -r msgraph

Authentication with refresh tokens

When using a refresh token to authenticate, you should ensure that the client ID used to refresh the token is identical to the client the token was issued to, or the request will fail. An exception to this is when you are using a FOCI client, which support refreshing tokens with different client IDs to obtain different access scopes. A list of client IDs and their scopes can be found here. You can also use roadtx findscope to find a client with the desired scope (this command is explained below). Example of authentication using one client and refreshing using a different client:

roadtx gettokens -u user@iminyour.cloud -p mypassword -c azcli
roadtx gettokens --refresh-token <token> -c msteams

In the above example you can also use the word file as argument to --refresh-token, which will make it read the refresh token from the .roadtools_auth file where the first command saved it.

Using refresh tokens with the refreshtokento command

While you can use the gettokens command to use refresh tokens, this command requires you that you specify all parameters manually. If you already have a .roadtools_auth file, for example from a previous gettokens command, you can also use the refreshtokento command. This will use the refresh token cached in the .roadtools_auth file, and automatically takes the client ID from there as well. This means that we can use this command to switch between different resources or scopes without having to specify the refresh token or client ID manually. We can still change the client ID in case of a FOCI refresh token. Examples (assumes that you already have a valid refresh token in the .roadtools_auth file):

roadtx refreshtokento -r msgraph
roadtx refreshtokento -s https://graph.microsoft.com/.default
roadtx refreshtokento -c msteams -r msgraph

Continuous Access Evaluation

roadtx also supports Continuous Access Evaluation tokens. To request them, you have to specify the --cae flag with a token request command. Not all commands support this yet. Also, this only works if you use the -s or --scope parameter (which triggers the v2.0 endpoint), not if you use the -r or --resource parameter, which is the default. You can validate that the resulting token is CAE aware by using roadtx describe and looking for the "xms_cc":["cp1"], claim in the token. These tokens may be valid for 26 hours instead of only 1-1.5 hours, but they can be revoked at any time and could be blocked if used from a different IP address than the IP they were issued to.

Devices

roadtx can register a device in Azure AD, either as a registered or joined device. Devices are represented by their device certificate and a private key. By default, these will be stored in devicename.pem and devicename.key respectively, though you can change the file names with the command line parameters.

Registering a device can be done with an access token to the device registration service. You can obtain such a token via one of the methods implemented in roadtx, via the gettokens command, using the devicereg resource alias with -r devicereg. See authentication for details. Registering a device is done with the roadtx device command. This reads the access token from the .roadtools_auth file and submits the request with a randomized name. For customization options, see roadtx device -h.

roadtx device -n blogdevice
Saving private key to blogdevice.key
Registering device
Device ID: 5f138d8b-6416-448d-89ef-9b279c419943
Saved device certificate to blogdevice.pem

Hybrid devices

Devices that are joined to an on-premises Active Directory domain that is set-up in hybrid configuration can also be used with roadtx. Registration is done with the roadtx hybriddevice command. This command requires several parameters, among which is a certificate that is set on the corresponding computer object in Active Directory and synced to Azure AD by Azure AD Connect. Such a certificate can be generated and stored on the computer object using the ROADtools hybrid utilities setcert.py script. This will also give you the SID and tenant ID that should be used with the hybriddevice registration command. Once the device is registered, the device credentials can be used as any other device that is joined/registered in Azure AD.

Deleting a device

It is possible to delete a device in Azure AD using the device certificate and private key:

roadtx device -a delete -c blogdevice.pem -k blogdevice.key

Primary Refresh Tokens (PRTs)

Requesting PRTs

With a device identity and user credentials it is possible to request a Primary Refresh Token. There are currently 3 ways of requesting a PRT:

  • Via username + password
  • Via a refresh token specifically requested for this purpose (see Enriching a PRT below), or a refresh token from the broker client ID (see here for context).
  • Via a Windows Hello key that was added to the account.
roadtx prt -u myuser@mytenant.com -p password --key-pem blogdevice.key --cert-pem blogdevice.pem

Primary Refresh tokens and their session key are saved in a .prt file by default (named roadtx.prt). You can choose a different name with the --prt-file or the shorter -f parameter. Most commands that accept a PRT also accept one that is specified via the command line with the --prt and --prt-sessionkey parameters.

Renewing

You can renew a PRT with the -a renew action. This will extend the validity of the PRT with 90 days from the renew date.

roadtx prt -a renew
Renewing PRT
Saved PRT to roadtx.prt

Using Primary Refresh Tokens

You can use PRTs in multiple ways with roadtx:

  • Use them directly similar to how Windows deals with PRTs with roadtx prtauth
  • Use them interactively with a Selenium based browser window with roadtx browserprtauth
  • Use them via in Chrome on Windows via a BrowserCore replacement
  • Use them in an emulated SSO flow with roadtx gettokens

If you are just looking to use default Microsoft client IDs to get tokens for various resources, the roadtx prtauth method is the easiest. This emulates the Web Account Manager (WAM). It will automatically load the PRT from disk from roadtx.prt, from the PRT file you specify with -f or it will use a manual PRT and session key specified with --prt and --prt-sessionkey. Similar to the gettokens command, this command accepts custom clients, resources and redirect URLS.

usage: roadtx prtauth [-h] [-c CLIENT] [-r RESOURCE] [-ru URL] [-f FILE] [--prt PRT] [--prt-sessionkey PRT_SESSIONKEY] [--tokenfile TOKENFILE] [--tokens-stdout]

optional arguments:
  -h, --help            show this help message and exit
  -c CLIENT, --client CLIENT
                        Client ID to use when authenticating.
  -r RESOURCE, --resource RESOURCE
                        Resource to authenticate to. Either a full URL or alias (list with roadtx listaliases)
  -ru URL, --redirect-url URL
                        Custom redirect URL used when authenticating (default: ms-appx-web://Microsoft.AAD.BrokerPlugin/<clientid>)
  -f FILE, --prt-file FILE
                        PRT storage file (default: roadtx.prt)
  --prt PRT             Primary Refresh Token
  --prt-sessionkey PRT_SESSIONKEY
                        Primary Refresh Token session key (as hex key)
  --tokenfile TOKENFILE
                        File to store the credentials (default: .roadtools_auth)
  --tokens-stdout       Do not store tokens on disk, pipe to stdout instead

Examples:

Request access/refresh tokens to Azure AD graph with Azure AD PowerShell client ID (default client and resource)

roadtx prtauth

Use the Azure CLI client ID and request access to Azure Resource manager (the resulting refresh token can be used with AzureHound).

roadtx prtauth -c azcli -r azrm     

Use the Microsoft Teams client ID, request tokens for Microsoft Graph

roadtx prtauth -c msteams -r msgraph

Creating PRT cookies for external use with prtcookie command

The prtcookie command takes a Primary Refresh Token and session key from either a .prt file or from the command line, and prints the PRT cookie that roadtx would use in browser based PRT authentication flows. It allows you to use the PRT cookie in for example an external browser, but only as long as the PRT cookie is valid (typically 5 minutes).

Selenium based authentication

Selenium based authentication controls a browser window and optionally the raw HTTP requests to autofill and inject credentials, MFA OTPs and PRTs. It requires you to have the geckodriver in your PATH, in your current directory, or in the location specified with --driver-path/-d.

Most Selenium based commands can automatically grab tokens, this is the default mode of operation. The operation relies on a client ID and resource being specified. It assumes you are using a public client, so it will try to grab the token by redirecting to one of the native authentication redirect URLs.

It is also possible to operate the Selenium based authentication on an automated flow which simply browses websites and logs in when it first encounters the Microsoft logon page. To trigger this mode, use the -url parameter and specify a custom URL to start browsing. You can combine this with the --keep-open parameter to disable the default timeout (120 seconds) that the script will wait to capture a token.

Interactive authentication

This is the simplest mode, perform interactive authentication, optionally autofilling username specified with -u and password specified with -p. Any MFA will have to be satisfied by hand.

roadtx interactiveauth -u myuser@mytenant.com -p password

KeePass based authentication

Several modules support support loading credentials from a KeePass file (kdbx) or a KeePass XML export. This file can hold multiple identities, optionally with MFA TOTP seeds to automate doing Multi Factor Auth. For setting up accounts, see this page on this wiki. Each entry should have the username in userprincipalname format (user@tenantdomain), and can optionally have an advanced property called otp which is the TOTP seed.

Note that roadtx only supports KeePass 2.0 (kdbx v3 format) files, with AES encryption and AES-KDF key transformation. If the tool complains about the database being too new, export it as v2.34 old format.

To authenticate with an identity from a KeePass file, either name the keepass file as roadtx.kdbx, or specify the file path with -kp. You can specify the password via the KPPASS environment variable, or with the -kpp command line flag. If it is a plain xml, no password is needed.

Examples:

Regular authentication

roadtx keepassauth -c msteams -u myuser@mytenant.com -kp accounts.kdbx -kpp keepassfilepassword

Keep the browser window open, browse to the myaccount page.

roadtx keepassauth -url https://myaccount.microsoft.com --keep-open -u myuser@mytenant.com -kp accounts.kdbx -kpp keepassfilepassword

Interactive authentication with automatic PRT injection

The browserprtauth module makes it easy to perform browser based authentication with a PRT from disk or the commandline. The functioning is identical to the interactive authentication, but this module also intercepts requests made to login.microsoftonline.com and automatically injects the PRT cookie to authenticate using the PRT. If the PRT does not have an MFA claim you may still be prompted for MFA, but otherwise the authentication should be fully transparent. You can use the -url parameter to initiate browsing to an Azure AD authentication connected resource, any redirect to the login page will use SSO with the PRT. This module always pretends to be the Edge browser. If you do not specify a URL, it will use the PRT to perform browser based authentication to the specified resource with the specified client ID.

You can also use this (or any other PRT based module) with a stolen PRT that you obtained by running mimikatz. See this blog post for details or this post on roadtx for examples.

roadtx browserprtauth -url https://office.com

Using a PRT to transfer device compliance claims to sessions with other users

You can also use a PRT to add "device authentication" to another user's credentials. An example would be a stolen PRT for user A that originated from a compliant device, that you can use on your attacker device with the credentials of user B, to pass conditional access policies that require a certain device state.

The browserprtinject module does this, using the PRT to augment the sign-in of a different user. The credentials of the user you are authenticating can be specified on the command line or sourced from a KeePass as described above.

Example:

roadtx browserprtinject -u newlowpriv@iminyour.cloud -r msgraph -c msteams

Enriching a PRT with MFA claim

A PRT that was requested with a username + password combination does not have an MFA claim, and will not give tokens with an MFA claim when used. You can enrich this PRT by performing MFA and requesting a special refresh token. The prtenrich module requests this special refresh token. You can use KeePass backed credentials to automate the MFA prompt.

roadtx prtenrich -u newlowpriv@iminyour.cloud
Got refresh token. Can be used to request prt with roadtx prt -r <refreshtoken>

The resulting refresh token can be used with device credentials to request a PRT with MFA claim:

roadtx prt -r <refreshtoken> -c blogdevice.pem -k blogdevice.key

Logging in to Outlook Web Access with access tokens (roadtx owalogin)

Given an access token that is valid for https://outlook.office.com, roadtx will spawn a Selenium browser window that will be used to authenticate to Outlook Web Access, allowing you to browse the users mailbox for the validity of the token. Switching to any other application will trigger a login since we only have an OWA token. While authenticating to web applications is normally not possible, for OWA it works because of some interesting token handling. This is probably because the new Outlook client is essentially embedding the same interface. Not all tokens for OWA work with this, the msteams client ID is known to work with this technique. This command is essentially an implementation of the research from Lares.

Other roadtx commands

roadtx describe

The describe command can be used to describe an access token, either read from the .roadtools_auth file (default), from stdin (automatic if you pipe data into the command), or from the command line if the token is specified with -t <token>. For colours, I recommend piping the output to a tool such as jq. This tool also supports reading access tokens from .roadtools_auth files.

roadtx describe < .roadtools_auth | jq .
{
  "alg": "RS256",
  "kid": "2ZQpJ3UpbjAYXYGaXEJl8lV0TOI",
  "nonce": "8EBrQwUJKjliF8E3nca7GJwQe2Uqq6Hde9B7xDV_zgw",
  "typ": "JWT",
  "x5t": "2ZQpJ3UpbjAYXYGaXEJl8lV0TOI"
}
{
  "acct": 0,
  "acr": "1",
<cut>

roadtx decrypt

The decrypt command can decrypt JWE tokens (JSON Web Encryption) using the session key or the transport key of a device.

roadtx codeauth

This command exchanges an authorization code for an access / refresh token. This is essentially a helper method for the code grant flow, the most common flow in OAuth2 authentication in Azure AD.

roadtx listaliases

Lists all the aliases for client IDs and resource URLs.

roadtx getotp

Gets the current OTP code (6 digits) given an TOTP seed, or an identity in a KeePass file with otp property set. Useful for MFA if you are not using autofill or it does not work for some reason.

roadtx getscope

The getscope / findscope command can be used to find Microsoft first party clients with specific API permissions. It also supports filtering the clients to only FOCI clients that can use each others refresh tokens with the --foci flag. For example, the command below lists all the client IDs you can use to get a token with the mail.read scope on the Microsoft Graph:

roadtx getscope -s https://graph.microsoft.com/mail.read