
11 oktober 2023 · 9 min read
Ondanks dat de benamingen erg op elkaar lijken en het vaker dan eens verkeerd gebruikt wordt, zijn het verschillende dingen. Zo is NTLM de benaming van het authenticatieprotocol waaronder NTLMv1 en NTLMv2 vallen, en wordt de NT-hash door heel veel mensen een NTLM-hash genoemd. In deze blogpost zetten we uiteen wat de verschillen en overeenkomsten zijn en leggen we uit hoe het NTLM protocol werkt.
LM (LAN Manager) is een verouderd authenticatieprotocol dat oorspronkelijk werd gebruikt in oudere versies van het Windows-besturingssysteem. Het werd geïntroduceerd in de jaren ’80 en ’90 en wordt nu als onveilig beschouwd vanwege de zwakke versleutelingstechnieken die het gebruikt. LM slaat wachtwoorden op in een zwak gehashte vorm, bekend als een LM-hash, wat het kwetsbaar maakt voor aanvallen. Sinds Windows Vista/Server 2008 staat LM ondersteuning standaard uitgeschakeld. Als er in een netwerk oudere systemen staan, of de optie specifiek is ingeschakeld dan kunnen er nog LM-hashes rondzwerven.
De LM-hash wordt als volgt geconstrueerd:
KGS!@#$% versleuteld, wat resulteert in twee 8-byte versleutelde waarden.Het LAN Manager protocol is een challenge-response protocol, waarbij de server een challenge stuurt. Dit werkt als volgt:
Op beveiligingsgebied zitten hier diverse pijnpunten in. Een aantal punten die meteen opvallen, het wachtwoord is niet hoofdlettergevoelig, dus de set met mogelijke wachtwoorden is significant kleiner. Daarnaast, als het wachtwoord gelijk aan of korter dan zeven karakters is, is het tweede deel van de hash altijd hetzelfde. Immers, het lege wachtwoord wordt aangevuld met nullbytes, vervolgens wordt hier een deskey van gemaakt en wordt de string KGS!@#$% versleuteld. Hieruit komt altijd 0xaad3b435b51404ee.
Het is belangrijk om te weten hoe LM werkt omdat het de basis is van de nieuwere authenticatieprotocollen, maar omdat LMv1 tegenwoordig (hopelijk) nergens meer gebruikt wordt gaan we niet nog dieper in op LM.
De NT-hash is een wachtwoordhash die wordt gebruikt in het NTLM-authenticatieprotocol van Windows-besturingssystemen. De NT-hash staat, eigenlijk onterecht, ook wel bekend als de NTLM-hash. In oudere versies van Windows werd binnen het LM-authenticatieprotocol de LM-hash gebruikt. De NT-hash is ten opzichte van de LM-hash een stukje veiliger. In plaats van de DES functies wordt er hier gebruik gemaakt van het MD4 hashingalgoritme. De mogelijke wachtwoorden worden daardoor niet meer beperkt tot de DOS karakterset maar alle UTF-16 karakters mogen worden gebruikt, er zit geen limiet meer op van 14 karakters en het wachtwoord wordt niet meer naar een bepaalde lengte opgevuld met nullbytes.
De NT-hash wordt als volgt geconstrueerd:
Het unicode (UTF16-LE) wachtwoord wordt omgezet naar hex.
Het MD4-algortime wordt toegepast. Dit is de NT-hash.
Welkom01! wordt 0x570065006c006b006f006d00300031002100
0x570065006c006b006f006d00300031002100 wordt 0xa958a3e244a682c7be90850c7a4e69eb
De NT-hash kan gebruikt worden om middels het NTLM-protocol te authenticeren. Het is in principe niet nodig om de hash te kraken en om te zetten naar een plaintext wachtwoord. Deze methode heet pass-the-hash.
NTLMv1 is net als LMv1 een challenge-response protocol. Sterker nog, het NTLM-response wordt op exact dezelfde wijze berekend. Het verschil zit hem in de startwaarde, waar bij LMv1 de LM-hash het beginpunt is, is dat bij NTLMv1 de NT-hash.
0x1122334455667788.Welkom01! wordt 0xa958a3e244a682c7be90850c7a4e69eb.0xa958a3e244a682c7be90850c7a4e69eb wordt 0xa958a3e244a682c7be90850c7a4e69eb00000000000xa958a3e244a682c7be90850c7a4e69eb0000000000 wordt 0xa958a3e244a682, 0xc7be90850c7a4e en 0x69eb0000000000.0xa958a3e244a682 wordt 0xA8AD297C25259B04, 0xc7be90850c7a4e wordt 0xC7DFA4105162E99D, 0x69eb0000000000 wordt 0x68F4C10101010101.0x1122334455667788 wordt dit 0xc8d035ab2a6bff25, 0x736d9a5749216e0a en 0x1179943b75b8f05b.0xc8d035ab2a6bff25736d9a5749216e0a1179943b75b8f05b.Tot slot behandelen we het NTLMv2 protocol, wat ook onder de overkoepelende noemer NTLM valt. Dit protocol is een iteratie op het NTLMv1 protocol en heeft een aantal extra beveiligingsmechanismes toegevoegd. Er wordt gebruik gemaakt van HMAC-MD5 en naast de server challenge is er ook een client challenge (ook wel client nonce). In de authenticatie-uitwisseling verschilt de client nonce, de timestamp en de server challenge iedere authenticatie-uitwisseling. Hierdoor zijn ze allemaal uniek. Het herhalen van een oude NTLMv2-response is hierdoor niet mogelijk. NTLMv2 wordt van de bovenstaande genoemde protocollen als het meest veilig beschouwd, maar kent ook zijn gebreken. Moderne authenticatieprotocollen zoals Kerberos zijn een stuk veiliger.
Het hergebruiken van een NTLMv2-response is dus niet mogelijk, maar wat wel mogelijk is, is het onderscheppen van een authenticatieverzoek van een client en deze doorsturen naar een andere server. Vervolgens de server challenge terugsturen naar de client en tot slot het NTLMv2-response van de client doorsturen naar de server. Dit wordt een relay attack genoemd. In een andere blogpost zullen we hier dieper op in gaan.
De NT-hash wordt op dezelfde manier geconstrueerd als bij NTLMv1, daar is niets aan veranderd. De verandering zit hem in het proces omtrent het construeren van het NTLMv2-response.
Dit kunnen we weer met een voorbeeld verduidelijken, maar eerst moeten we weten wat er precies in de genoemde blob moet komen te staan.
De blob met gegevens bestaat uit de volgende waardes:
| Blob signature | 0x01010000 |
| Gereserveerde waarde | 0x00000000 |
| Timestamp (64-bit little-endian hexadecimaal) | Pak de huidige timestamp van https://epochconverter.com/ldap |
| Random client nonce | 0x8877665544332211 |
| Onbekend wat het is, maar nullbytes werken | 0x00000000 |
| Targetinformatie | 0x020014004e0045005400570[...] |
| Onbekend wat het is, maar nullbytes werken | 0x00000000 |
De targetinformatie bestaat uit een domain name subblock (0x0200), server name subblock (0x0100), DNS domain name subblock (0x0400), DNS server name subblock (0x0300) en een Terminator subblock (0x00000000). Na de specificatie van het subblock staat de lengte van de data. Vervolgens komt de data (met de zojuist opgegeven lengte).
| Naam van subblock | Hex-waarde | Lengte in hex | Data | Data in hex (UTF-16LE) |
|---|---|---|---|---|
| Domain name subblock | 0x0200 | 0x1400 | NETWORKIFY | 0x4e004500540057004f0052004b00490046005900 |
| Server name subblock | 0x0100 | 0x0800 | DC01 | 0x4400430030003100 |
| DNS domain name subblock | 0x0400 | 0x2000 | NETWORKIFY.local | 0x4e004500540057004f0052004b004900460059002e006c006f00630061006c00 |
| DNS server name subblock | 0x0300 | 0x2a00 | DC01.NETWORKIFY.local | 0x44004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c00 |
| Terminator subblock | 0x0000 | 0x0000 |
Deze waardes worden achter elkaar geplakt, wat resulteert in de volgende targetinformatie: 0x020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c0000000000.
Om het NTLMv2-response te berekenen hebben we nog wat meer informatie nodig, we gaan van het onderstaande uit.
| Target | NETWORKIFY.local |
| Username | Jan |
| Password | Welkom01! |
| Server Challenge | 0x1122334455667788 |
| Random client nonce | 0x8877665544332211 |
| Targetinformatie | 0x020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c0000000000 |
0x1122334455667788.Welkom01! wordt 0xa958a3e244a682c7be90850c7a4e69eb.JAN wordt 0x4a0041004e00.NETWORKIFY.local wordt 0x4e004500540057004f0052004b004900460059002e006c006f00630061006c00.0x4a0041004e004e004500540057004f0052004b004900460059002e006c006f00630061006c00.0x2d231c43cbe51fc97bcb4de5e664633a.133354454190000000, in hex is dat 0x01e4b1c23c09ec00. De blob wordt dan 0x010100000000000001e4b1c23c09ec00887766554433221100000000020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c0000000000000000000x1122334455667788010100000000000001e4b1c23c09ec00887766554433221100000000020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c0000000000000000000xd724cf06040dfdde5bae09dd32fa51d6.0xd724cf06040dfdde5bae09dd32fa51d6010100000000000001e4b1c23c09ec00887766554433221100000000020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c000000000000000000Hashen is altijd eenrichtingsverkeer. Om te controleren of we het NTLMv2-response juist hebben samengesteld moeten we de hash proberen te kraken. Het makkelijkst is om dit via Hashcat te doen.
Hashcat kan met ontzettend veel verschillende algortimes overweg. De mode die we nodig hebben voor NTLMv2 is mode 5600. Het benodigde formaat wijkt iets af van ons gemaakte NTLMv2-response, het ziet er zo uit:
username::domain:server_challenge:NTLMv2-hash:blob
Als we de waardes invullen wordt de Net-NTLMv2-hash dus als volgt:
Jan::NETWORKIFY.local:1122334455667788:d724cf06040dfdde5bae09dd32fa51d6:010100000000000001e4b1c23c09ec00887766554433221100000000020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c000000000000000000
Het plaintext wachtwoord is bekend, dus het opgeven van een woordenlijst is niet nodig. Met onderstaand commando wordt de hash gekraakt. De berekening van het NTLMv2-response is dus correct uitgevoerd.
./hashcat -m 5600 "Jan::NETWORKIFY.local:1122334455667788:d724cf06040dfdde5bae09dd32fa51d6:010100000000000001e4b1c23c09ec00887766554433221100000000020014004e004500540057004f0052004b00490046005900010008004400430030003100040020004e004500540057004f0052004b004900460059002e006c006f00630061006c0003002a0044004300300031002e004e004500540057004f0052004b004900460059002e006c006f00630061006c000000000000000000" -a 3 "Welkom01!"
Naast NTLMv2 is er ook LMv2, ontwikkeld voor compatibiliteit met oude servers. Oudere servers sturen alleen het LM-response en verwachten dat de grootte hiervan exact 24 bytes is. LMv2 is eigenlijk een soort mini-implementatie van NTLMv2.
Er wordt gestart met een NT-hash en niet met een LM-hash. De NT-hash wordt op dezelfde manier geconstrueerd als bij NTLM.