Det er en vanlig misforståelse om at hash og kryptering er det samme. Det er de ikke. Hash er irreversibel. Ta følgende eksempel som et eksempel:
$ echo-n Password123 | md5sum
42f749ade7f9e195bf475f37a44cafcb-
Vi sender strengen "Password123" til MD5-algoritmen (algo), som utfører matematiske operasjoner og returnerer den genererte heksadesimalkodede haschen. Den eneste måten å få den samme hash-utgangsverdien på er å skrive inn algo opprinnelig. Det er konflikter, men vi kan snakke om det senere.
Utgangen fra de fleste hash-algoritmer er en heksadesimalkodet binær streng med fast lengde. Andre, som dette eksemplet, bruker en Base64-kodet streng som utgang. Merk at lengden alltid er den samme:
{SHA} uNF8eZRJ8jmr8WTjyocRJPVpe7w =
{SHA} lqdu/Zr6o2dgIER8Up1/7lcUtgw =
{SHA} qYUOwLMlDEuukA5HCT4LR1kQzco =
{SHA} MXZBCpyWJ7TTs1w2kgGJslwNwTg =
{SHA} 2sAPLaUh9Mz0bI + XxKEg7qyABe8=
TL; Dr.
Jeg vil ikke snakke for mye om kryptering (fordi de tingene er for bøker), men det er viktig å kunne skille mellom hashstrenger og krypterte strenger. Kryptering fyller vanligvis en streng for å tilfredsstille en bestemt lengde før kryptering skjer. Det krever også en nøkkel (eller passord) for å dekryptere. Hvis du bruker et kryptert passord, vil strengen endres avhengig av lengden på inngangen. Hvis du ser en haug med krypteringspassord, varierer lengden, og du kan jobbe med kryptering i stedet for hash. AES-256-CBC Eksempel Kryptert streng og tilhørende vanlig tekst (nøkkelen er "ASDF"):
foobar | U2FsdGVkX19G + KtytNHdj6yH2AVvX26pEmtunS/PRnU = foobarfoobar | U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog = foobarfoobarfoobar | U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX + ldatuqv2xexeaeoww0xg/EXJUe9aSUz $ katt krypterte_passord U2FsdGVkX19G + KtytNHdj6yH2AVvX26pEmtunS/PRnU = U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog = U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX + lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz $ for i i `cat encrypted_passwords`; Gjør echo $i | openssl enc -base64 -d -aes-256-cbc -pass pass:asdf; ekko; Ferdig foobar foobarfoobar foobarfoobarfoobar
Nå tenker du kanskje: Du har nok rett. Det at nøkkelmaterialet må være tilgjengelig for systemet betyr imidlertid at det i hovedsak er et vanlig tekst hovedpassord som ligger et sted – enten det er som en RSA-nøkkel eller et passord eller et passord i en fil, innebygd i en database, hardkodet i en applikasjon eller et sted i minnet. pfft, ingen ' kommer til å bruke asdf som nøkkelen til å kryptere brukernes ' passord
Bruk samme streng for MD5:
foobar | 3858f62230ac3c915f300c664312c63f foobarfoobar | 59faa421729e846dd800dce59943bfc0 foobarfoobarfoobar | 1352aadab322d1a033c27964be0965db
Hashpassordet er langt fra perfekt, faktisk er det litt dårlig, men det er verre enn kryptering på grunn av hva det prøver å oppnå. Brukere velger absolutt minimumskrav oftere enn not, og kan også bruke det på flere nettsteder. Mange "hacks" er faktisk ingenting annet enn legitimasjonsgjenbruksangrep. Hvis det opprinnelige kompromisset var å bruke kryptering, var den eneste innsatsen angriperen måtte gjøre å finne nøkkelen som dekrypterte alle passordene. For hash må de i det minste gjøre en innsats for å knekke dem. Når det brukes sammen med moderne algoritmer som sha512crypt, bcrypt, scrypt eller argon2, kan hashverdier kreve mye innsats å knekke.
Å tilsette salt er å legge til en streng til passordet før hash. Saltet for hver hash skal være unikt, vanligvis tilfeldig valgt, fordi poenget er å få den samme klartekst "passord" hash-verdien til å ha en annen verdi hver gang. Dette gjør livet vanskelig for en passordknekker, for for å sjekke ordet "passord" for hver av de 1000 brukerne, som har et unikt SALT, må de gjøre dette 1000 ganger-en gang per bruker/SALT. Dette betyr også at de ikke kan bruke forhåndskompilerte ordbøker eller regnbuetabeller effektivt (vanligvis...) fordi de krever en tilpasset per salt.
Nettsteder roter til dette noen ganger og bruker generisk salt for alle brukere; Dette strider mot formålet.
Følgende er SHA1-hash med salt:
b353977827f67a4ae0318f3a9447fae1c13d9d90:b8d18ca |___________________________________________| hash | salt | separator
Klarteksten til denne hashen er "Passord". Dens saltverdier er "b8d18ca" og brukes i SHA1 ($salt.$pass) API. Dette betyr at algoritmen tar klarteksten til Passord, genererer salt og legger den til foran klarteksten. Når et nettsted eller en app prøver å bekrefte passordet ditt i fremtiden, vil det ta passordet ditt med klar tekst som input, lese saltverdien i den lagrede Hash, legge den til foran passordet du velger, og sammenligne den genererte hash-verdien med den lagrede hash-verdien. Cracking Hvis du ikke vet at en del av den er salt, vil hashen produsere følgende vanlig tekst:
b8d18capassword
Siden algoritmen skriver inn vanlig tekst, salt og generert Hashverdien kan forbli gjennomsiktig for brukeren. Ved sprekking, hvis algoritmen er salt, må vi kjenne saltet slik at vi kan gi det når vi genererer kandidatens klartekst.
Salting kan gjøre sprekkingen mer tidkrevende hvis den utføres riktig. Med tilfeldig salt tvinger du Cracker til å kaste bort tid på å prøve å knekke hashverdier som salt ikke samsvarer med. Dette fullfører omtrent innsatsen som kreves for enhet_hastighet/number_of_salter fordi vi må generere en kandidat for hvert salt. Hvis saltet er statisk, er den matematiske operasjonen den samme... speed_of_device/1. En annen måte å se dette på:
vår GTX 980 cracks SHA1 ($salt.$pass) ved 3576,8 MH/s eller 3,5 milliarder kandidater per sekund Vår hashliste inneholder 1000 unike salter 3.500.000.000 / 1000 = 3.500.000 kandidater per sekund
Dette er tre størrelsesordener langsommere, med et tap på 99,9 %. Ved bruk av statisk salt ser det slik ut:
Our GTX 980 cracks SHA1 ($salt.$pass) at 3576,8 MH/s eller 3,5 milliarder kandidater per sekund Vår hashliste inneholder 1 unik salt 3.500.000.000 / 1 = 3.500.000.000 kandidater per sekund
Hvis dette ikke gir mening, fortsett å lese, vi vil ha et vakkert diagram senere...
En annen vanlig forbedring sammenlignet med å bare "hash denne klarteksten" er at "hash denne klarteksten, deretter hash det resultatet, og deretter hash det resultatet" gjentas tusenvis av ganger. Dette gjør det mulig å prøve et enkelt kandidatpassord, som passordknekkingsprogrammet må gjøre tusenvis av ganger. Dette kalles iterasjon, loop eller variabel kostnad. Noen passordhashalgoritmer bruker hardkodede iterasjonsrunder; Andre Git. Gjør den konfigurerbar i en del av selve hashen. For eksempel bruker md5crypt () MD5, inkludert salt, og sykler nøyaktig 1000 ganger. sha512crypt () bruker sha512, inkluderer et salt og sykler et konfigurerbart antall ganger (standard er 5000).
Iterasjoner påvirker hovedsakelig beregningssykluskostnadene til hashalgoritmen, ikke minnebruken eller andre faktorer. Disse er også viktige angrep når designet er optimalisert for å motstå visse typer hashtyper, men dette er for ugress til å diskutere her.
La oss se på noen eksempler for å demonstrere effekten av valg av hash-algoritmer, enten det er saltet, ved bruk av flere iterasjoner, etc. Anta at en angriper samler inn 1000 brukerhash-verdier fra et infisert nettsted, og de vil bare utføre et enkelt angrep som tester hver passordhash-143 millioner kandidatpassord.
Typen hashing som brukes av et infisert nettsted vil ha stor innvirkning på hvor lang tid det tar for angriperen å passere angrepet. Her er et (relativ, omtrent) diagram over hvor mange sekunder det tar å fullføre angrepet, avhengig av hvilken type hash som brukes, hvor standard grafikkort:
Vel, det er ubrukelig! De sterkeste hash-typene er mye tregere, men de raskere typene blir bare flatt til ingenting. La oss prøve samme datastørrelse igjen ved hjelp av logaritmisk x-akse tid. Når barene beveger seg fra venstre til høyre, vil de øke med en potens på 10:
Så noen poeng er: Enkeltrunde er enklere enn flere runder og uten salt enn med salt når du vil knekke noen passordhash. Tvert imot, når noen selskaper eller nettsteder kunngjør et datainnbrudd som inneholder brukerdata, a) passordet er best hashet, ikke bare vanlig tekst; b) De er helst saltet, ikke bare hashet; c) Det er bedre at de har brukt kraftige multi-runder saltet hash hele tiden, ikke bare en enkelt rund.
Før du prøver å knekke en gitt passordhash, er det opp til knekkeren å finne ut hvilken hashalgoritme som brukes for å implementere den. Å identifisere hash-typer er vanligvis enkelt, men ikke alltid. Crackers gjør ofte velinformerte gjetninger basert på ledetråder som hashlengde og format. Til syvende og sist er den eneste måten å være sikker på om hashtypen gjetning er riktig, er om hashen er knekket.
Noen gode ressurser for denne oppgaven er tilgjengelig her og her, og de viser begge hvordan vanlige hashverdier ser ut.
Programvarepakken "hash-identifier" (tilgjengelig her) er tilgjengelig i Kali Linux som hjelper til med å identifisere ukjente hash-typer.
En kollisjon oppstår når to forskjellige innganger resulterer i samme hash-utgang. Det er dårlig (åpenbart). For passord kan dette bety at jeg kanskje ikke har knekket det faktiske passordet ditt, men siden jeg fant en inngang som produserte samme hash-verdi, kunne jeg bruke vanlige tekstverdier for å lure systemet til å tro at passordet er legitimt.
Microsoft Office bruker i sin dokumentbeskyttelse en algoritme som har vært utsatt for konflikter i mange år. Det er ikke uvanlig å oppdage flere konflikter for en enkelt hash, som alle låser opp dokumentet.
Når en konflikt er oppdaget, blir algoritmen faktisk ødelagt. Hvis det skjer én gang, er det statistisk sett mest sannsynlig at det vil skje igjen. Det eneste som holder oss i veien er tid og prosesseringskraft. Etter hvert som algoritmer blir mer robuste, tar det mer kraft og tid å generere kandidatalgoritmer og sammenligne hashutdata for å søke etter dem. Som et resultat blir designere stadig flinkere til å lage algoritmer som er mindre utsatt for konflikter.