Er is een veelvoorkomend misverstand dat hashing en encryptie hetzelfde zijn. Dat zijn ze niet. Hash is onomkeerbaar. Neem het volgende voorbeeld als voorbeeld:
$ echo-n Password123 | md5sum
42f749ade7f9e195bf475f37a44cafcb-
We geven de tekenreeks "Password123" door aan het MD5-algoritme (algo), dat wiskundige bewerkingen uitvoert en de gegenereerde hexadecimale gecodeerde hash retourneert. De enige manier om dezelfde hash-uitvoerwaarde te verkrijgen, is door de algo origineel in te voeren. Er zijn conflicten, maar we kunnen er later over praten.
De uitvoer van de meeste hash-algoritmen is een hexadecimaal gecodeerde binaire tekenreeks van vaste lengte. Anderen, zoals dit voorbeeld, gebruiken een Base64-gecodeerde tekenreeks als uitvoer. Merk op dat de lengte altijd hetzelfde is:
{SHA} uNF8eZRJ8jmr8WTjyocRJPVpe7w =
{SHA} lqdu/Zr6o2dgIER8Up1/7lcUtgw =
{SHA} qYUOwLMlDEuukA5HCT4LR1kQzco =
{SHA} MXZBCpyWJ7TTs1w2kgGJslwNwTg =
{SHA} 2sAPLaUh9Mz0bI + XxKEg7qyABe8=
TL; Dr.
Ik wil niet al te veel over encryptie praten (want die dingen zijn voor boeken), maar het is belangrijk om onderscheid te kunnen maken tussen hash strings en encrypted strings. Versleuteling vult meestal een tekenreeks in die voldoet aan een bepaalde lengte voordat codering plaatsvindt. Het vereist ook een sleutel (of wachtwoord) om te decoderen. Als u een gecodeerd wachtwoord gebruikt, verandert de reeks afhankelijk van de lengte van de invoer. Als u een stapel ciphertekstwachtwoorden ziet, variëren de lengtes en heeft u mogelijk te maken met codering in plaats van hash. AES-256-CBC Voorbeeld Versleutelde tekenreeksen en bijbehorende gewone tekst (met de sleutel "ASDF"):
foobar | U2FsdGVkX19G + KtytNHdj6yH2AVvX26pEmtunS/PRnU = foobarfoobar | U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog = foobarfoobarfoobar | U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX + ldatuqv2xexeaeoww0xg/EXJUe9aSUz $ kat gecodeerde_wachtwoorden U2FsdGVkX19G + KtytNHdj6yH2AVvX26pEmtunS/PRnU = U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog = U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX + lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz $ voor i in `cat encrypted_passwords`; Doe echo $i | openssl enc -base64 -d -aes-256-cbc -pass pas:asdf; echo; Klaar foobar foobarfoobar foobarfoobarfoobar
Nu denk je misschien: je hebt misschien gelijk. Het feit dat het sleutelmateriaal toegankelijk moet zijn voor het systeem betekent echter dat het in wezen een plain text master-wachtwoord ergens bevindt-of het nu als een RSA-sleutel of een wachtwoord in een bestand is, ingebed in een database, hard gecodeerd in een toepassing of een wachtwoord ergens in het geheugen. pfft, niemand ' gaat asdf gebruiken als sleutel om de wachtwoorden van hun gebruikers '
te coderen Gebruik dezelfde string voor MD5:
foobar | 3858f62230ac3c915f300c664312c63f foobarfoobar | 59faa421729e846dd800dce59943bfc0 foobarfoobarfoobar | 1352aadab322d1a033c27964be0965db
Het hash-wachtwoord is verre van perfect, in feite is het een beetje slecht, maar het is erger dan encryptie vanwege wat het probeert te bereiken. Gebruikers kiezen de absolute minimumvereiste vaker dan not en kunnen deze ook op meerdere sites gebruiken. Veel 'hacks' zijn eigenlijk niets meer dan aanvallen op het hergebruiken van credentials. Als het oorspronkelijke compromis is om codering te gebruiken, is de enige inspanning die de aanvaller moet doen om de sleutel te vinden om alle wachtwoorden te decoderen. Bij hashes moeten ze tenminste moeite doen om ze te kraken. Bij gebruik met moderne algoritmen zoals sha512crypt, bcrypt, scrypt of argon2 kan de hashwaarde veel moeite vergen om te kraken.
Het toevoegen van zout is het toevoegen van een string aan het wachtwoord vóór de hash. Het zout van elke hash moet uniek zijn en meestal willekeurig worden geselecteerd, omdat het belangrijk is om dezelfde "wachtwoord"-hash-waarde in duidelijke tekst elke keer anders te maken. Dit maakt het leven van wachtwoordkrakers moeilijk, want om het woord 'wachtwoord' voor elke gebruiker uit de 1.000 gebruikers te controleren, die elk een uniek zout hebben, moeten ze het werk 1.000 keer doen-één keer per gebruiker/zout. Dit betekent ook dat ze niet effectief kunnen werken met vooraf gecompileerde woordenboeken of regenboogtabellen (meestal...) omdat ze een aangepaste per zout nodig hebben.
Websites verpesten dit soms en gebruiken universeel zout voor alle gebruikers; Dit is in strijd met het doel.
Het volgende is de SHA1-hash met zout:
b353977827f67a4ae0318f3a9447fae1c13d9d90:b8d18ca |___________________________________________| hash | zout | separator
De duidelijke tekst van deze hash is "wachtwoord". De zoutwaarde is "b8d18ca" en wordt gebruikt in de API van SHA1 ($salt.$pass). Dit betekent dat het algoritme de gewone tekst van het wachtwoord krijgt, zout genereert en dit vóór de gewone tekst toevoegt. Wanneer een website of app probeert uw wachtwoord in de toekomst te verifiëren, neemt het uw gewone tekstwachtwoord als invoer, leest het de zoutwaarde in de opgeslagen Hash, voegt het toe aan het wachtwoord dat u hebt geselecteerd en vergelijkt het gegenereerde Hash met de opgeslagen Hash. Cracking Als je niet weet dat een deel ervan zout is, produceert de hash de volgende gewone tekst:
b8d18capassword
Omdat het algoritme gewone tekstinvoer maakt, zout en de gegenereerde hashwaarden kunnen transparant blijven voor de gebruiker. Bij het kraken, als het algoritme zout is, moeten we het zout kennen, zodat we het kunnen leveren bij het genereren van kandidaat-plaintext.
Als het goed wordt uitgevoerd, kan zouten het kraken tijdrovend maken. Met willekeurige zouten dwing je Cracker om tijd te verspillen door te proberen de hash te kraken die niet overeenkomt met zout. Dit voltooit ongeveer de inspanning die nodig is voor device_speed/number_of_salts, omdat we voor elk zout een kandidaat moeten genereren. Als het zout statisch is, is de wiskunde hetzelfde... speed_of_device/1. Een andere manier om dit te bekijken:
onze GTX 980 scheuren SHA1 ($zout.$pass) bij 3576,8 MH/s of 3,5 miljard kandidaten per seconde Onze hashlist bevat 1000 unieke zouten 3.500.000.000 / 1000 = 3.500.000 kandidaten per seconde
Dit is drie ordes van grootte langzamer, met een verlies van 99,9%. Met statisch zout ziet het er zo uit:
onze GTX 980 scheuren SHA1 ($salt.$pass) bij 3576,8 MH/s of 3,5 miljard kandidaten per seconde Onze hashlist bevat 1 unieke zout 3.500.000.000 / 1 = 3.500.000.000 kandidaten per seconde
Als dit geen zin heeft, lees dan verder, we zullen er later een mooie grafiek hebben...
Een andere veelvoorkomende verbetering in vergelijking met simpelweg "hash this plaintext" is dat "hash this plaintext, hash that result, and hash that result" duizenden keren wordt herhaald. Dit maakt het mogelijk om een enkel kandidaatwachtwoord te proberen, waarbij het wachtwoordkrakerprogramma duizenden keren moet werken. Dit wordt iteratie, lus of variabele kosten genoemd. Sommige wachtwoordhash-algoritmen gebruiken hardgecodeerde iteratierondes; Andere Git. Maak het configureerbaar in een deel van de Hash zelf. md5crypt () gebruikt bijvoorbeeld MD5, inclusief salt, en loopt precies 1000 keer. sha512crypt () gebruikt sha512, bevat een zout en loopt een configureerbaar aantal keren (standaard 5.000).
Iteraties beïnvloeden voornamelijk de rekencycluskosten van het hash-algoritme, niet het geheugengebruik of andere factoren. Dit zijn ook belangrijke aanvallen wanneer het ontwerp is geoptimaliseerd om bestand te zijn tegen bepaalde soorten hash-typen, maar dit is te onkruid om hier te bespreken.
Laten we eens kijken naar enkele voorbeelden om de invloed van de keuze van het hash-algoritme te demonstreren, of het nu gezouten is, het gebruik van meerdere iteraties, enz. Stel dat een aanvaller 1.000 hash-waarden van gebruikers verzamelt van een geïnfecteerde website en ze willen gewoon een eenvoudige aanval uitvoeren om elke wachtwoord-hash te testen-143 miljoen kandidaat-wachtwoorden.
Het type hash dat door de geïnfecteerde website wordt gebruikt, zal een enorme impact hebben op de tijd die de aanvaller nodig heeft om deze aanval te passeren. Dit is een (relatief, grofweg) grafiek van hoeveel seconden het duurt om deze aanval te voltooien, afhankelijk van het type hash dat wordt gebruikt, waarbij standaard grafische kaarten:
Nou, dat heeft geen zin! De sterkste hash-typen zijn veel langzamer, maar de snellere typen worden gewoon afgeplat tot niets. Laten we dezelfde dataschaal opnieuw proberen met behulp van logaritmische x-as tijd. Naarmate de balken van links naar rechts bewegen, zullen ze toenemen met de macht van 10:
Dus enkele punten zijn: als je een aantal wachtwoordhash wilt kraken, is een enkele ronde gemakkelijker dan meerdere rondes en zonder zout dan met zout. Omgekeerd, wanneer bepaalde bedrijven of websites een gegevensbreuk aankondigen die gebruikersgegevens bevat, is a) het wachtwoord het beste gehash en niet alleen gewone tekst; b) ze zijn bij voorkeur gezouten en niet alleen gehash; c) Het is beter dat ze krachtige zouthashes met meerdere rondes gebruiken in plaats van alleen enkele rondes.
Voordat hij een bepaalde wachtwoordhash probeert te kraken, is het aan de cracker om uit te zoeken welk hash-algoritme wordt gebruikt om dit te implementeren. Het identificeren van hash-typen is meestal eenvoudig, maar niet altijd. Crackers maken vaak geïnformeerde gissingen op basis van aanwijzingen zoals hashlengte en formaat. Uiteindelijk is de enige manier om er zeker van te zijn dat het hash-type correct is, of de hash is gekraakt.
Hier en hier worden enkele uitstekende bronnen voor deze taak aangeboden, en ze laten allemaal zien hoe gemeenschappelijke hashwaarden eruit zien.
Het pakket "hash-identifier" (beschikbaar hier) is beschikbaar in Kali Linux, dat helpt bij het identificeren van onbekende hash-typen.
Een conflict ontstaat wanneer twee verschillende inputs resulteren in dezelfde hash-uitvoer. Dat is erg (blijkbaar). Voor wachtwoorden betekent dit waarschijnlijk dat ik uw daadwerkelijke wachtwoord misschien niet heb gekraakt, maar omdat ik een invoer heb gevonden die dezelfde hash-waarde produceert, kan ik een gewone tekstwaarde gebruiken om het systeem te misleiden dat het wachtwoord legitiem is.
Microsoft Office gebruikt in zijn documentbeveiliging een algoritme dat al jaren gevoelig is voor conflicten. Het is niet ongebruikelijk om meerdere conflicten voor een enkele hash te ontdekken, die allemaal een document ontgrendelen.
Zodra een conflict wordt ontdekt, wordt het algoritme feitelijk vernietigd. Als het één keer gebeurt, is het statistisch gezien zeer waarschijnlijk dat het opnieuw zal gebeuren. Het enige wat ons in de weg staat is tijd en verwerkingskracht. Naarmate algoritmen robuuster worden, kost het genereren van kandidaat-algoritmen en het vergelijken van hash-outputs om ernaar te zoeken meer vermogen en tijd. Ontwerpers worden daarom steeds beter in het creëren van algoritmen die minder gevoelig zijn voor conflicten.