Internal Monologue – Verkrijg NTLM Hashes
Wanneer een kwaadwillende gebruiker een NTLM hash in handen krijgt kan deze misbruikt worden voor het verkrijgen van (elevated) toegang. De NTLM hash kan gekraakt worden of de hash kan onderdeel worden van een replay attack. De replay attack (pass-the-hash) zorgt ervoor dat het kraken van de hash niet nodig is. Mimikatz is een ontzettend nuttige en veelgebruikte tool voor o.a. dit doeleinde. Echter door zijn bekendheid is Mimikatz ook prime-target geworden van allerlei security systemen die Mimikatz activiteit ontdekken. Windows 10 en 2016 kennen de “Credential Guard” feature welke middels virtualisatie technologie secrets ontsluit in een secure environment waardoor het onmogelijk wordt voor tools als Mimikatz om de credentials te verkrijgen. Dit is waar Internal Monologue een uitkomst kan bieden. Internal Monologue gebruikt namelijk in tegenstelling tot Mimikatz niet het LSASS Windows object. De Internal Monologue aanval ziet er anders uit. Hoe Internal Monologue werkt, lees je hieronder!
Voordat we Internal Monologue kunnen bespreken moeten we het eerst over NTLM hebben, waar dit voor gebruikt wordt en hoe NTLM globaal functioneert.
NTLM staat voor “New Technology LAN Manger” en is een suite van Microsoft security protocollen om de integriteit, vertrouwelijkheid te bieden wanneer gebruikers authentiseren. NTLM is de opvolger van LAN MAN (Lan Manager / LM). NTLM bestaat uit verschillende versies. NTLMv1, NTLMv2, NTLM2 Session. En hoewel NTLM nog regelmatig gebruikt wordt in situaties waar Kerberos niet gebruikt kan worden, toch adviseert Microsoft het niet meer te gebruiken omdat de meest recente cryptografische mogelijkheden (AES, SHA-256) niet in NTLM aanwezig zijn. NTLM gebruikt namelijk RC4 voor zijn encryptie en CRC of Message Digest algoritmes voor integriteitscontrole. NTLM is voornamelijk aanwezig als backwards compatibility protocol in scenatio’s waar Kerberos niet gebruikt kan worden. Denk aan:
- Authenticatie op een server welke niet behoord tot een domein (workgroup of peer-to-peer)
- Als de server welke authenticeerd SMB ondersteund zoals printers, NAS devices, Webservers etc.).
- Wanneer Kerberos niet gebruikt kan worden zoals b.v. bij authenticatie middels een IP i.p.v. een reversed name, wanneer authenticatie naar een ander AD forest gebeurt met een Legacy NTLM Trust of wanneer de firewall de Kerberos poorten (88) blokkeert).
LM (Lan Manager) hashes zijn de oudste hashes en dateren uit 1980 (OS/2), De LM hashes hebben een beperkte karakterset en zijn juist daarom relatief gemakkelijk te kraken.
Waar: SAM Database op Windows syteem of NTDS database op een domain controller.
Voorbeeld (Hashcat’s example hashes page):
299BD128C1101FD6 |
Het algoritme van LM is als volgt:
- Alle kleine letters > hoofdletters
- Vul wachtwoorden aan tot 14 karkaters (met NULL karakters)
- Verdeel het wachtwoord in 2 delen van 7 karakters
- Maak van elk van de 2 delen een DES sleutel
- Encrypt de string “KGS!@#$%” met de 2 DES keys
- Voeg de 2 versleutelde delen samen. Dit is de LM Hash.
Om de hash te kraken zou het volgende commando kunnen worden uitgevoerd:
john --format=lm hashfile.txt hashcat -m 3000 -a 3 hashfile.txt |
LM staat standaard uit maar kan gewoon ingeschakeld en gebruikt worden via Group Policy. In sommige oudere netwerken zal de LM Hashj nog gewoon gebruikt worden. Denk aan legacy compatibility of simpel… vergeten!
Na LM kwam de opvolger genaamd de NTHash. Sommige mensen refereren naar deze hash als de NTLM hash maar dat is misleidend en fout. De NTHash is het slachtoffer van de meeste Mimikatz aanvallen en is de hash die we gebruiken voor “Pass-the-Hash” attacks.
Waar: SAM Database op Windows syteem of NTDS database op een domain controller.
Voorbeeld (Hashcat’s example hashes page):
B4B9B02E6F09A9BD760F388B67351E2B |
Het algoritme de NTHash is volgens het MD4 (UTF-16-LE(password)) principe. UTF-16-LE is het “kleine endian UTF-16” karkaterset. Windows gebruikte dit in plaats van het standaard “big endian” karakterset.
Om de hash te kraken zou het volgende commando kunnen worden uitgevoerd:
john --format=nt hashfile.txt hashcat -m 1000 -a 3 hashfile.txt |
Bovenstaande NTHash is een belangrijk onderdeel van het NTLM protocol. In versie 1 van het NTLM protocol wordt de NTHash gebruikt in deen challenge/response tussen een server en zijn client. Versie 1 van het NTLM protocol gebruikt afhankelijk van de gebruikte configuratie niet alleen de NTHash maar eventueel ook de LM hash.
Voorbeeld (Hashcat’s example hashes page):
u4-netntlm::kNS:338d08f8e26de93300000000000000000000000000000000:9526fb8c23a90751cdd619b6cea564742e1e4bf33006ba41:cb8086049ec4736c |
Het algoritme van NTLM is als volgt:
C = 8-byte server challenge, random K1 | K2 | K3 = LM/NT-hash | 5-bytes-0 response = DES(K1,C) | DES(K2,C) | DES(K3,C) |
Dit betekend dat de client-response procedure als volgt is opgebouwd:
- Client vraagt aan de server om te authentiseren
- Er vindt een protocolonderhandeling plaatst
- De server zend een 8-byte challenge (random) naar de client (de nonce)
- De client stuurt een 24-byte response retour
- De server authentiseert de client
De 24-byte response van de client is als volgt gegenereerd (de encryptie)
- Splits de lokaal opgeslagen 16-byte hash (LM Hash voor LANMAN challenge / response of NT Hash voor NTLMv1) in drie delen van 7-bytes. Om 16 bytes te verdelen over 7 moet het derde deel aangevuld worden met 5 NULL karakters. Nu zijn er 21 karakters in het totaal en kunnen we deze dus verdelen over 3 delen. Dit betekend ook dat het derde deel een ontzettend zwak deel is en in enkele seconden gekraakt kan worden. De 3 gemaakte delen vormen nu 3 DES sleutels.
- Nu wordt de random 8-byte server challenge 3x versleuteld middels de 3 DES keys.
- Voeg alle 3 de delen samen. Dit is de NTLMv1 response.
Om de hash te kraken zou het volgende commando kunnen worden uitgevoerd:
john --format=netntlm hashfile.txt hashcat -m 5500 -a 3 hashfile.txt |
De opvolger van NTLMv1 is het NTLMv2 protocol. Dit is de verbeterde versie van het NTLMv1-protocol en is wat moeilijker om te kraken. NTLMv2 is al geïntroduceerd in Windows Server NT 4. Het concept van NTLMv2 is hetzelfde als van NTLMv1 met als grote verschil dat er een ander algoritme gebruikt wordt en dat er andere “responses” naar de server gestuurd worden.
Voorbeeld (Hashcat’s example hashes page):
admin::N46iSNekpT:08ca45b7d7ea58ee:88dcbe4446168966a153a0064958dac6:5c7830315c7830310000000000000b45c67103d07d7b95acd12ffa11230e0000000052920b85f78d013c31cdb3b92f5d765c783030 |
Het algoritme van NTLM is als volgt:
SC = 8-byte server challenge, random CC = 8-byte client challenge, random CC* = (X, time, CC2, domain name) v2-Hash = HMAC-MD5(NT-Hash, user name, domain name) LMv2 = HMAC-MD5(v2-Hash, SC, CC) NTv2 = HMAC-MD5(v2-Hash, SC, CC*) response = LMv2 | CC | NTv2 | CC* |
De encryptie verloopt als volgt:
- Client vraagt aan de server om te authentiseren
- Er vindt een protocolonderhandeling plaatst
- De server zend een 8-byte challenge (random) naar de client (de nonce)
- De client neemt de 8-byte nonce en versleuteld deze 2x als volgt:
- CC = De client genereerd een random client-based challenge van 8-bytes
- CC* = De client genereerd een random client-based challenge van variabele lengte op basis van de huidige tijd, een variabele 8-bits waarde (CC2), de domainnaam en nog wat overige eigenschappen.
- v2-hash= De client genereerd een HMAC-MD5-hash van 8-byte welke de zijn eigen wachtwoord evenals andere identificerende informatie bevat
- De client versleuteld nu zijn random 8-byte client respons, toegevoegd aan de 8-byte v2-hash alsmede een HMAC-MD5 hash van de server challenge. Dit zijn in totaal 24-bytes (net zoals NTLMv1). Dit noemen we onofficieel de LMv2 response.
- De client genereerd nu een respons van variabel format bestaande uit de variabele client respons, de 8-byte v2-hash alsmede een HMAC-MD5 hash van de server challenge. Deze response noemen we onofficieel de NTv2 response.
- De client verstuurt nu zijn response (van variabel formaat) naar de server. Deze bestaat uit de LMv2 waarde, de client response, de NTv2 waarde en de variabele client response.
- De server authentiseert de client
Om de hash te kraken zou het volgende commando kunnen worden uitgevoerd:
john --format=netntlmv2 hashfile.txt hashcat -m 5600 -a 3 hashfile.txt |
Een fantastische tool om NTLMv1 en NTLMv2 hashes te verkrijgen is door de LLMNR Responder tool te gebruiken: https://jarnobaselier.nl/llmnr-responder-poinsoner.
Dan kennen we ook nog het NTLMv2 Session protocol. Dit protocol is vergelijkbaar met MS-CHAPv2. NTLMv2 Session bestaat uit NTLMv1 authenticatie en NTLMv2 sessiebeveiliging. Bij NTLMv2 Session authenticatie wordt de 8-byte clientuitdaging toegevoegd aan de 8-byte serveruitdaging en vervolgens middels MD5 gehasht. De laatste 8-bytes van het hash resultaat is de server uitdaging welke volgens het NTLMv1-protocol gehashed is.
Dit is een versterkte vorm van NTLMv1 die de mogelijkheid behoudt om de bestaande Domain Controller-infrastructuur te gebruiken maar een dictionary attack door een frauduleuze server voorkomt.
Om bovenstaande processen af te handelen kent Windows een aantal processen die belangrijk zijn om te weten. De client en server negotiations over welk authenticatieprotocol gebruikt gaat worden gebeurt via de “Microsoft negotiate Security Support Provider” (SSP). Er zijn verschillende support providers. Voor NTLM is dit de NTLMSSP. SSP kent ook een API genaamd de SSPI (Security Support Provider Interface). Bij Kerberos is het KDC (Key Distribution Center) een belangrijke schakel in het genereren en valideren van Kerberos Tickets. LSASS (Local Security Authority Subsystem Service) is een belangrijke Windows service en is verantwoordelijk voor domeinverificatie, active directory-beheer en het handhaven van de security policy. LSASS genereert processen die verantwoordelijk zijn voor het authentiseren van gebruikers middels NTLM en verifieert de geldigheid van logins en is verantwoordelijk voor het aanvragen en doorsturen van Kerberos tickets. LSASS heeft dus vaak een proxy-functie en ziet nooit unencrypted verkeer. LSASS ziet echter wel de hashes en daarom is het verkrijgen van LSASS inhoud vaak het primaire doel van een aanval.
Om de zwakheden van NTLM te laten zien wil ik nog de “Relay” Attack en de “Pass-the-Hash” Attack uitleggen. Daarna gaan we kijken waarbij Internal Monologue ons kan helpen!
NTLM Relay Attack
De NTLM Relay Attack is feitelijk een NTLM Man-In-The-Middle aanval. NTLM-relaying is een techniek waarbij de aanvaller tussen een client en een server staat om acties op de server uit te voeren terwijl u zich voordoet als de client. De NTLM Relay Aanval is in sommige situaties een hele effectieve methode om de controle over een Active Directory-domein over te nemen vanuit een black box-context (waarbij je dus niet over inloggegevens beschikt).
Normaliter ziet een NTLM Authenticatie tussen client en server er als volgt uit:
Hoe deze authenticatiestappen gaan staat hierboven beschreven. Tijdens een NTLM-authenticatie kan een cliënt zijn identiteit bewijzen tegenover de server door een stukje informatie dat door de server wordt geleverd (challenge) met zijn wachtwoord te coderen (encryprted challenge) en terug te sturen naar de server. Bij een NTLM relay moet de “Man-in-the-Middle” dus de berichten van de client doorsturen naar de server, en visa versa. Dus alle informatie die tussen client naar de server verstuurd worden zullen ook ontvangen worden door de MitM (aanvaller). Dit ziet er als volgt uit:
Vanuit het oogpunt van de server heeft de MitM (aanvaller) zichzelf geverifieerd met behulp van het geheim van het slachtoffer (client). Aan het einde van de NTLM Authentication exchange is de aanvaller op de server geverifieerd met de inloggegevens van de client.
Een tool om deze aanval uit te voeren is b.v. “ntlmrelayx.py”.
Pass-the-Hash Attack
Een aanval die we geregeld uitvoeren met Mimikatz is een “Pass-the-Hash” aanval. Hierbij worden de LanMan- of NTLM-hashes van het wachtwoord van een gebruiker gebruikt om the authenticeren bij AD of een andere bron. De aanvaller hoeft de hash niet te decrypten om het wachtwoord in plain text te verkrijgen. Pass-the-Hash aanvallen maken gebruik van het authenticatieprotocol. De hash voor sessie wachtwoorden is namelijk statisch (blijft hetzelfde) totdat het wachtwoord wordt geroteerd. Hashes worden meestal verkregen door het actieve geheugen van een systeem uit te lezen. Pass-the-Hash (PtH) aanvallen kunnen voorkomen op Linux, Unix en andere platformen maar komen meestal voor op Windows-based systemen. In Windows maakt SSO (Single Sign-On) gebruik van deze hashes. Pass-the-Hash is dus hetzelfde als SSO via NT Lan Manager (NTLM), Kerberos en andere verificatieprotocollen waardoor de hash als sleutel dient voor vele resources en het niet meer nodig is om via omslachtige procedures de hash te kraken. Wanneer een wachtwoord wordt gemaakt in Windows, wordt het gehasht en opgeslagen in de Security Accounts Manager (SAM), het Local Security Authority Subsystem (LSASS) procesgeheugen, de Credential Manager (CredMan) store of in de NTDS.DIT database in Active Directory. Dus wanneer de content van deze databases achterhaald kan worden dan kunnen de hashes weder gebruikt worden voor authenticatie.
Internal Monologue
Nu bovenstaande theorie duidelijk is en je weet dat Windows Credentials Guard en andere security controls het erg lastig maken om Mimikatz of andere tools te gebruiken voor het verkrijgen van hashes vraag je jezelf misschien af of er dan geen andere methodes zijn. Uiteraard wel! Een van deze methodes is Internal Monologue, de titel van deze post 🙂
Internal Monologue is gemaakt door Elad Shamir en is een zogenaamde downgrade attack welke uitgevoerd kan worden in de context van de gebruiker. Vanuit de gebruikerscontext worden een local procedure-call gedaan naar het NTLM Authention Package (MSV1_0) via SSPI. Hiermee wordt het NTLM antwoord berekent. Dit betekend dat de berekening van de hash in-memory plaatsvindt en dat deze berekende hash vervolgens gekraakt en gebruikt kan worden om een Pass-the-Hash uit te voeren. De Internal Monologue flow ziet er als volgt uit:
- 1. Het uitschakelen van de NTLMv1 preventieve controles door LMCompatibilityLevel, NTLMMinClientSec en RestrictSendingNTLMTraffic te wijzigen in de juiste waardes
- 2. Haal alle non-network logon tokens op via actieve processen en impersonate deze gebruikers.
- 3. Communiceer voor elke “impersonated” gebruiker lokaal met de NTLM SSP om een NTLMv1-reactie op de gekozen challenge op te vragen in de beveiligingscontext van de impersonated gebruiker.
- 4. Herstel de oorspronkelijke waardes van LMCompatibilityLevel, NTLMMinClientSec en RestrictSendingNTLMTraffic.
- 5. Kraak de NTLM-hashes van de opgeslagen responses met behulp van rainbow tables.
- 6. Gebruik de gekraakte NTLM hash voor een Pass-the-Hash aanval.
Laten we Internal Monologue installeren en gebruiken. Internal Monologue komt standaard met een precompiled DLL en EXE file maar eigenlijk willen we Internal Monologue zelf compilen. Internal Monologue is C# applicatie voor Windows. Om windows applicaties te compilen op Linux hebben we “Mono” nodig incl. de C# compiler (Mono-Roslyn). Laten we eerst de juiste repo toevoegen aan onze Kali machine:
sudo apt install gnupg ca-certificates sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list sudo apt update |
En vervolgens Mono en dependencies installeren:
sudo apt install mono-complete msbuild mono-roslyn |
Nu zijn we klaar om Internal Monologue te downloaden en te compilen:
wget https://github.com/eladshamir/Internal-Monologue.git cd Internal-Monologue msbuild InternalMonologue.sln |
Let op, standard wordt Internal Monologue ge-compiled voor .NET versie 3.5. Wanneer je target een andere .NET heeft (b.v. .NET 4.5) dan gebruik je het commando met de “-p” flag:
msbuild InternalMonologue.sln -p:TargetFrameworkVersion=v4.5 |
De logging output laat zien waar de bestanden geplaatst worden:
Nu is het een kwestie van de juiste EXE (of DLL) uploaden naar de gewenste (Windows) machine en uitvoeren. Wanneer alles succesvol is ziet dit er als volgt uit (de letters en cijfers op de rode lijn zijn bewust uit het screenshot verwijderd):
Beide hashes zijn hetzelfde. Zoals je ziet is dit een NTLMv1 (ofwel Net-NTLMv1) hash welke we vervolgens kunnen kraken. Internal Monologue heeft het volgende gedaan
- De NTLMv1 preventieve controles (LMCompatibilityLevel, NTLMMinClientSec en RestrictSendingNTLMTraffic) uitgeschakeld.
- Alle non-network logon tokens opgehaald via actieve processen en deze gebruikers ge-impersonate.
- In-Memory (lokaal) deze “impersonated” gebruikers gecommuniceerd met de NTLM SSP om een NTLMv1-reactie op de gekozen challenge op te vragen in de beveiligingscontext van de impersonated gebruiker. Dit is de NTLMv1 hash die we hierboven in het screenshot zien.
- Herstellen van de oorspronkelijke waardes van LMCompatibilityLevel, NTLMMinClientSec en RestrictSendingNTLMTraffic.
Zoals je ziet gebruikt Internal Monologue altijd dezelfde NTLM server-side challenge (1122334455667788). Internal Monologue is geen malafide proces en triggert geen virusscanners.
De hash die we gekregen hebben is een hash zonder SSP (Security Support Provider – het binary messaging protocol welke door de Microsoft Security Support Provider Interface (SSPI) gebruikt wordt). Een hash met SSP zou er als volgt uitzien (let op de nullen):
Administrator::S01-JBASELIER:5AA37877:85D5BC2CE95161CD00000000000000000000000000000000:892F905962F76D323837F613F88DE27C2BBD6C9ABCD021D0:1122334455667788 |
Het kraken van een NTLM hash met SSP duurt vele malen langer dan een hash zonder SSP. Om een NTLM (met of zonder SSP) hash te kraken met de DES Mode 14000 in Hashcat kun je de “ntlmv1 Multitool” van Evilmog gebruiken.
Zonder SSP (x is een verwijderde letter / cijfer)
python3 ntlmv1.py --ntlmv1 "Administrator::S01-JBASELIER:7c8e2aad9f08eec5b075519xxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxx5b075519c97025b3522e6c74b72b02397:1122334455667788" |
De tool breekt de hash open en maakt er een DES hash van welke je met Hashcat kunt kraken. De tool geeft zelfs het te gebruiken commando retour. Ook wordt de NTHash berekend welke je zou kunnen laten kraken door een externe tool (zoals crack.sh):
Wanneer je toch een SSP based hash veranderd de server challenge. Je gebruikt dan hetzelfde commando:
python3 ntlmv1.py --ntlmv1 " Administrator::S01-JBASELIER:5AA37877:85D5BC2CE95161CD00000000000000000000000000000000:892F905962F76D323837F613F88DE27C2BBD6C9ABCD021D0:1122334455667788" |
Om het wachtwoord vervolgens met Hashcat te kraken maak je dus een hashcat file aan en ga je deze brute-forcen met de DES (14000) optie:
echo "7c8e2aad9f08eec5:1122334455667788">>14000.hash echo "b075519c97025b35:1122334455667788">>14000.hash ./hashcat -m 14000 -a 3 -1 charsets/DES_full.charset --hex-charset 14000.hash ?1?1?1?1?1?1?1?1 |
Conclusie
Zelf met alle veiligheidsmechanismen in-place kan NTLM in veel gevallen misbruikt worden om hashes te verkrijgen die middels een pass-the-hash methode gebruikt kunnen worden om toegang te krijgen tot gebruikers resources. Als Mimikatz de hash niet uit het geheugen kan halen dan kunnen tools als Internal Monologue toch helpen om in-memory de hashes te berekenen. Internal Monologue is een prachtige tool die laat zien dat wanneer een algoritme lokaal berekend kan worden de uitkomst verkregen kan worden zonder tussenkomst van de tegenpartij en waarbij dus ook de veiligheidsmechanismes van de tegenpartij niet in de weg kunnen zitten.
Hopelijk hebben jullie genoten van dit artikel over Internal Monologue. Zo ja, dan zou het fantastisch zijn om dit terug te zien in een reactie, like of share (op eigen website, LinkedIn, Facebook, Twitter…. whatever). Deze positieve reacties geven me voldoende inspiratie voor een volgend artikel. Dus… op naar de volgende 🙂 Dankjewel! ❤