Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Tiivistealgoritmit

Sivun loppuun

Triton [12.05.2010 17:52:20]

#

Eli ihan halusin herätellä keskustelua eri tiivistealgoritmeista. Itse en ole enää käyttänyt md5:sta lainkaan vaan lähinnä SHA1, mutta jostain luin, että esim. Blowfish olisi kumpaakin noista vahvempi, pitääkö paikkansa? Olen tekemässä ihan tavallista salasanasuojausskriptiä ja aloin miettiä, että sitähän voisi kerralla valita istuntotunnisteita ja salasanojen hashausta varten oikein todella vahvan algoritmin. Onko kellään tietoa, mitä tiivistealgoritmeja esim. pankit tai muut vastaavat "suurempaa suojausta" vaativat järjestelmät käyttävät? Itseäni kiinnostaisi tuo SHA2 eli SHA512, mutta webhotellini ei sitä nähtävästi tue...

Antti Laaksonen [12.05.2010 19:34:13]

#

Tiivistefunktioon T voi liittyä kaksi erilaista heikkoutta:

1. Voidaan muodostaa tiivistettä vastaava merkkijono. Toisin sanoen tiedossa on merkkijono X ja voidaan löytää merkkijono Y niin, että T(Y) = X.

2. Voidaan löytää kaksi merkkijonoa, jotka saavat saman tiivisteen. Toisin sanoen voidaan löytää merkkijonot A ja B niin, että T(A) = T(B).

Kohdat 1 ja 2 onnistuvat helposti käymällä läpi riittävän määrän merkkijonoja. Kuitenkin esimerkiksi MD5:ssä ja SHA-1:ssä määrä on luultavasti niin suuri, että menetelmä ei ole käytännössä mahdollinen nykyisillä tietokoneilla.

MD5:n ja SHA-1:n ongelma on, että on keksitty tapoja, joilla kohta 2 onnistuu nopeammin. On pystytty esimerkiksi käytännössä löytämään merkkijonot A ja B niin, että MD5(A) = MD5(B). Kuitenkaan ei tunneta menetelmiä, joilla kohta 1 onnistuisi tehokkaasti.

Jos tehtävänä on selvittää salasana tiivisteestä, kyseessä on kohta 1 eikä kohdasta 2 ole apua. Nimittäin jos tiedossa on tiiviste salasanasta "yxqqrwfmvo", murtamista ei auta tieto, että salasanat "npzlzyleci" ja "hlybjhisaj" tuottavat saman tiivisteen, koska tämä ei liity mitenkään asiaan.

Tässä on MD5-tiiviste eräästä merkkijonosta:

6170e3d76f0a9d3e6fde1617e8764d53

Kohta 1 ei nykytiedon mukaan onnistu tehokkaasti, eli kukaan ei saa selville, mistä merkkijonosta on kysymys.

Metabolix [12.05.2010 20:19:15]

#

Jos ulkopuolinen käyttäjä saa käsiinsä edes salasanan tiivisteen, järjestelmässä on jotain vikaa. Ehdotan siis ensisijaiseksi suojausmenetelmäksi hyvin tehtyä järjestelmää, jossa käyttäjän salaiset tiedot eivät missään tilanteessa näy muille. Tiivisteen (ja suolan!) käyttäminen on vain keino minimoida vahinkoja virheen sattuessa.

Pankkien tietoturva perustuu nähdäkseni kahteen melko triviaaliin asiaan: järjestelmässä ei saa olla bugeja (kuten SQL-injektioaukkoja) ja yhteyden pitää olla salattu (SSL tai TLS). Näillä pääsee pitkälle, vaikka salasanat tallennettaisiin tietokantoihin selkokielisinä. Suurempia ongelmia ovat asiat, joille pankki ei voi mitään: käyttäjän typeryys ja erilaiset huijaukset sekä vakoiluohjelmat. (Kertakäyttöiset tunnusluvut tosin suojaavat jossain määrin näiltäkin.)

Triton [12.05.2010 20:42:08]

#

No sql-injektio on kyllä pois suljettu, sillä käytän PDO:ta ja sehän automaattisesti puhdistaa syötteen. Mietin nimenomaan tilannetta, jossa hakkeri saa hashit käsiinsä...

Edit. Onkos sitten evästeiden ja istuntojen tietoturvalla suurta eroa? Tietenkin istunnoissa on se hyvä puoli, että varsinainen data tallennetaan palvelimelle, mutta hyvin usein palvelut kuitenkin käyttävät pelkästään evästeitä...

Metabolix [12.05.2010 21:36:28]

#

Triton kirjoitti:

No sql-injektio on kyllä pois suljettu, sillä käytän PDO:ta ja sehän automaattisesti puhdistaa syötteen.

SQL-injektio on vain yksi esimerkki tietoturva-aukosta. Monella teoriassa kunnollisellakin sivustolla tietoja voi kalastella vaikka epäilyttävillä linkeillä. (Antti, kannattaisikohan tämä jotenkin estää?)

Triton kirjoitti:

Onkos sitten evästeiden ja istuntojen tietoturvalla suurta eroa?

Istunnon tunniste on yleensä voimassa vain vähän aikaa, joten ei ole yhtä vaarallista, vaikka joku pääsisikin tonkimaan toisen vanhoja evästeitä. (Toisaalta jos kirjautumisen halutaan pysyvän voimassa, kuten täällä voi profiilista valita, tätä etua ei voi hyödyntää.) Samasta syystä myös verkkoliikenteen vakoilu on pienempi ongelma, koska salasana lähetetään vain kerran.

Merkittävämpi hyöty istunnoista saadaan käyttäjän omaa kieroilua vastaan: käyttäjä voi muokata evästeitään aivan vapaasti, joten esimerkiksi pelin pistemäärän tai verkkokaupassa maksetun rahamäärän tallentaminen evästeeseen olisi typerää.

Triton [12.05.2010 21:54:41]

#

Miten SSL-sertifikaatti sitten suojaa sitä liikennettä? Kryptataanko headerin tiedot jotenkin?

Metabolix [12.05.2010 22:27:36]

#

Nykyään kannattanee puhua ennemmin TLS:stä, joka on SSL:n seuraaja. Lisätietoa protokollasta on Wikipediassa. Salauksesta sovitaan jo TCP-yhteyden alussa eli ennen minkään HTTP-spesifisen datan siirtoa. Tämän jälkeen aivan kaikki data on salattua. Sertifikaatti taas toimii tunnistusvälineenä: koneelta löytyy valmiiksi kokoelma luotettujen tahojen sertifikaatteja, ja selain tarkistaa, onko palvelimen sertifikaatti jonkin näistä myöntämä eli aito ja luotettava.

Grez [13.05.2010 12:20:53]

#

Triton kirjoitti:

Miten SSL-sertifikaatti sitten suojaa sitä liikennettä? Kryptataanko headerin tiedot jotenkin?

SSL/TLS:n tarkoitus ja ainoa hyöty on estää kolmatta osapuolta lukemasta tietoja käyttäjän ja palvelimen välisestä liikenteestä.

Eli kryptografian vakiintuneella nimistöllä Carol ei pysty selvittämään mitä Alice ja Bob juttelevat, mutta se ei estä Alicea ja Bobia huijaamasta tai kiusaamasta toisiaan.

Sitten itse kysymykseen, eli SSL/TLS-sertifikaattiin. Sen tarkoituksen on estää "man in the middle" -hyökkäys. Eli salattua yhteyttä muodostettaessa palvelin lähettää julkisen avaimensa, jolla käyttäjä voi suojata palvelimelle lähetettävän tiedon. Sertifikaatissa eli varmenteessa on tämä julkinen avain ja tiettyjä vakiotietoja (nimi yms) jonka luotettu varmenteidenmyöntäjä on allekirjoittanut omalla salaisella avaimellaan. Selaimissa on vakiona tiettyjen varmenteidenmyöntäjien julkiset avaimet, ja selaimet pitävät siis näiden myöntäjien varmenteita oletuksena luotettavina.

Ilman sertifikaattia Carol voisi pistää oman palvelimen pystyyn, ohjata Bobille tarkoitetun liikenteen sinne ja ottaa taas itse yhteyden Bobiin, jolloin Alice voisi luulla keskustelevansa suoraan Bobin kanssa vaikka liikenne kiertäisi Carolin kautta ja Carol pystyisi kuitenkin seuraamaan heidän "keskusteluaan".

timoh [13.05.2010 17:39:40]

#

Tästä olikin jo Mureakuhassa juttua, mutta tämä aihe on mielenkiintoinen, niin kirjoittelen tännekin.

Tuossa olet aivan oikeassa, että Blowfish on tällä hetkellä paras vaihtoehto salasanojen tiivisteiden luontiin (ja Extended DES toiseksi paras).

Sitten noista muista eri algoritmeistä, niin itse algoritmin valinta ei ole oleellista (MD5, SHA2, jne.). Oleellista on iteraatioiden määrä (ja suolaus).

Tätä asiaa täytyy lähteä ajattelemaan pahimman mahdollisen tilanteen kannalta, eli esim. järjestelmän kiintolevyt pihistetään ja hyökkääjä saa haltuunsa käytännössä kaiken muun paitsi käyttäjän salasanan. Tässä tapauksessa hyökkääjä voi lähteä murtamaan salasanaa etsimällä pelkästään loppukäyttäjän salasanaa (laskee tiivisteitä samalla lailla kuin murrettun sovelluksen autentikointi-implementaatio).

Nyt tulee isoin ongelma hyökkääjän kannalta. Jos tiiviste on iteroitu esim. 100000 kertaa, hyökkääjä joutuu ajamaan (esim. MD5) tiivisteen 100000 kertaa ennen kuin yksi salasana on kokeiltu. Ja tämä on tietenkin hitaampaa kuin pelkästä suolasta ja salasanasta koostuvan tiivisteen murtaminen.

Käytännössä siis autentikointi-implementaation tulisi olla mahdollisimman tehokas, jotta iteraatiomäärä saadaan mahdollisimman suureksi (kuitenkin niin, että salasanojen tarkistus ei tule liian isoksi ongelmaksi). Tässä esim. ihan PHP:n plain md5-funktion "raw output" auttaa asiaa. Iteroidaan tyyliin:

<?php
for ($i = 0; $i < 100000; $i++)
{
    $hash = md5($hash . $password, true)
}
?>

Ja kannattaa sekin huomata, että tuo plain md5-funktio on nopeampi, kuin hash('md5',...).

Ylempänä olikin jo sanottu, että nuo collisionit eivät vaikuta tässä tapauksessa, joten MD5 on aivan käypä salasanojen tiivistämiseen.

Täällä oli vielä hiukan laajemmin esimerkein asiasta: http://wiki.mureakuha.com/wiki/Turvallisten_www-sovellusten_koodaus_php:llä­#Salasanojen_tallentaminen_tietokantaan

Mutta näin vinkkinä vielä loppuun, kannattaa käyttää tiivisteiden luontiin ja tarkistamiseen Portable PHP password hashing frameworkia, http://www.openwall.com/phpass/

Metabolix [13.05.2010 21:14:12]

#

timoh: Pystytkö esittämään jonkin järkevän perustelun, miksi tuollaisesta toistosta olisi hyötyä? Krakkerin ei suinkaan tarvitse ajaa 100000 iteraatiota (mistä hän edes tietäisi, että järjestelmä on toteutettu noin?), vaan riittää, että hän onnistuu arvaamaan viimeiseksi MD5-funktiolle syötetyn datan ($hash.$password), josta salasanan saa suoraan poimittua.

Mikä tahansa lisäsuojaus (suola, base64, kirjainten sekoittaminen) tuottaa yksittäistapauksessa saman tuloksen: törmäys ei riitä, koska MD5-funktiolle ei olekaan syötetty salasanaa sellaisenaan. Sen sijaan lisäsuojauksesta riippuu, miten helposti viimeisestä tekstistä saa salasanan: suolaa käytettäessä ($suola.$salasana) pitää arvata, missä menee suolan ja salasanan raja. Esitetyssä $hash.$salasana-systeemissä tilanne on sama mutta arvaaminen jo silmämääräisesti helpompaa. Sen sijaan jokin mystisempi algoritmi vaatisi krakkerilta enemmän mielikuvitusta.

Käytännössä siis timoh:n esittämällä metodilla päästään yksittäisen salasanan turvallisuuden kohdalla täsmälleen samaan tulokseen kuin käyttämällä 128-bittistä suolaa. Usean salasanan kohdalla turvallisuus on hieman vakiosuolaa parempi, koska yhden salasanan murtaminen ei paljasta muiden salasanojen suoloja.

Esimerkki mainitsemastani mystisemmästä algoritmista: Kun salasanan XOR-kryptaisi omalla tiivisteellään ja sitten tiivistäisi uudestaan, krakkeri ei pystyisi mitenkään purkamaan salausta arvaamatta algoritmia. (Jos sitten tätä haluaisi vielä kovettaa, voisi käyttää tuota iteraatiotekniikkaa – nyt, kun siitä olisi hyötyäkin.) Muita vastaavia kikkoja on sadoittain.

Antti Laaksonen [13.05.2010 21:47:14]

#

Oletus oli tämä:

timoh kirjoitti:

Tätä asiaa täytyy lähteä ajattelemaan pahimman mahdollisen tilanteen kannalta, eli esim. järjestelmän kiintolevyt pihistetään ja hyökkääjä saa haltuunsa käytännössä kaiken muun paitsi käyttäjän salasanan.

Nyt suolasta tai oudosta algoritmista ei ole hyötyä, koska ne saa selville kirjautumissivun lähdekoodista. Mutta jos MD5-funktiota on käytetty 100000 kertaa, salasanan arvaaminen on hidasta.

Tietenkin jos käytössä on nimenomaan timoh:n koodi ja onnistuu keksimään 100000. tiivisteestä 99999. tiivisteen, siitä voi lukea salasanan. Mutta tämän suunnan ei pitäisi olla käytännössä mahdollinen. Toisaalta joka kierroksella ei ole mikään pakko lisätä salasanaa tiivistefunktion parametriin.

Metabolix [13.05.2010 23:38:40]

#

Antti Laaksonen kirjoitti:

Oletus oli tämä: ...

Minulta jäi tosiaan tämä oletus huomaamatta. Silti menetelmän hyöty on minusta hyvin kyseenalainen: jos jonkin tärkeän järjestelmän kovalevy varastetaan, käyttäjän salasanan paljastuminen lienee huolista pienimpiä.

timoh [14.05.2010 17:01:53]

#

Metabolix kirjoitti:

timoh: Pystytkö esittämään jonkin järkevän perustelun, miksi tuollaisesta toistosta olisi hyötyä? Krakkerin ei suinkaan tarvitse ajaa 100000 iteraatiota (mistä hän edes tietäisi, että järjestelmä on toteutettu noin?), vaan riittää, että hän onnistuu arvaamaan viimeiseksi MD5-funktiolle syötetyn datan ($hash.$password), josta salasanan saa suoraan poimittua.

Tosiaan tuo salasanan etsiminen käy hitaammaksi kun hyökkääjän täytyy yhden salasanan kokeilemiseksi ajaa tiivistefunktio x kertaa (yhden kerran sijasta).

Tuossa että hyökkääjä suoraan etsisi tuota 128 (+salasana) bittistä bittijonoa, on vaihtoehtoja niin hirveä määrä, että käytännössä siihen ei hyökkääjän kannalta kannata lähteä. Mutta ihan totta, että salasanaa on turha lisätä joka kerta tiivistettävään merkkijonoon (tällä ei voiteta mitään, mutta teoreettisesti hävitään). Parempi ilman muuta olisi näin:

<?php
for ($i = 0; $i < 100000; $i++)
{
    $hash = md5($hash . $salt, true)
}
?>

Salasanan tiivistämisessä tiivistealgoritmin nopeus on perimmäinen ongelma, tämän takia PHP:n Blowfish-pohjainen crypt()-toteutus on parempi vaihtoehto salasanan tiivistämiseen.

Tuo kovalevyn varastaminen oli vain yksi esimerkki, minkä ensimmäisenä keksin. Esim. työntekijän vakoilu, erotettu (suuttunut) työntekijä, vihamielinen työntekijä jne. Ongelmakohtia löytyy kyllä. Varsinkin tietoturvan saralla ei pitäisi ikinä luottaa "Security through obscurity":yyn, vaan järjestelmä tulisi tehdä kattavasti turvalliseksi. Toki ei tietenkään tuosta metodista haittaa ole, kunhan vaan järjestelmän tietoturva ei ole sen pohjalla.

Metabolix [14.05.2010 18:13:44]

#

timoh kirjoitti:

Esim. työntekijän vakoilu, erotettu (suuttunut) työntekijä, vihamielinen työntekijä jne. Ongelmakohtia löytyy kyllä.

No onhan niitä. En kuitenkaan usko, että MD5-tiivisteen murtaminen olisi silti suurin ongelma, jos käyttäjä on keksinyt kunnollisen salasanan eikä käytä samaa tunnusta ja salasanaa joka paikassa. Enemmän olisin yhä huolissani tietokannan salaamattomista tiedoista (nimet, osoitteet, puhelinnumerot, jopa tilitiedot ja henkilötunnukset).

timoh kirjoitti:

Varsinkin tietoturvan saralla ei pitäisi ikinä luottaa "Security through obscurity":yyn, vaan järjestelmä tulisi tehdä kattavasti turvalliseksi.

Eiköhän siinä ole monelle niin paljon tekemistä muutenkin, ettei kannata liikaa panostaa tällaisiin kikkailuihin ja kuvitella niiden ansiosta olevansa turvassa. Useimmissa tapauksissa tietoja haetaan järjestelmän ulkopuolelta SQL-injektioiden tai muiden aukkojen kautta, joten ensisijaisesti kannattaisi kohdistaa voimavarat näiden estämiseen. Varsinkin pienessä järjestelmässä vihamielisen työntekijän todennäköisyys on pieni, ja kuten sanoin, hänelle noita kiusantekovälineitä olisi tarjolla jo muutenkin vaikka millä mitalla.

timoh [14.05.2010 21:52:33]

#

Tietysti "tietoturva" on monialainen kokonaisuus ja jokainen itse miettii mitä asioita pitää tärkeinä ja mitä vähemmän tärkeinä. Mutta en kuitenkaan tätä "key stretching":iä kutsuisi kikkailuksi ;) Kyseessä siis ihan yleinen ja käytetty tekniikka: http://en.wikipedia.org/wiki/Key_strengthening Ja tosiaan tässä alkuperäinen kysyjä nimenomaan kysyi tästä salasanojen hashauksesta (sen takia tämä enemmän in depth turina).

Kysyin myös Solar Designeriltä tekniseltä kantilta tuosta, että onko kryptografisesti millaista haittaa jos salasana syötetään joka kerta iteroidessa hash-funktiolle. Laitan tähän loppuun vielä tuon, melko mielenkiintoisen, vastauksen (yllä minun kysymykseni ja alla Solar Designerin vastaus):

Solar Designer kirjoitti:

Timo kirjoitti:

> ... attacker could bypass the
> > whole iteration process and just try to find $hash . $password
> > (where $password is plaintext)?
> >
> > I mean this part of the phpass code:
> > $hash = md5($hash . $password, TRUE); // $salt should be used here
> > instead $password?
> >
> > Of course even this will be difficult for the attacker, since he has to
> > find the 128 bit $hash + plaintext password. But doesn't this allow the
> > attacker to bypass the iteration process?

In theory, yes, but it is infeasible and currently impossible to do so.
$hash is 128-bit, which is beyond the amount of entropy contained in a
password. Even if you add the stretching (converted to its equivalent in
bits of entropy) to the password's entropy, you will nevertheless get a
number below 128 bits, unless your password is "unreasonably strong".
Thus, computing the stretched hashes for each reasonable candidate
password is a more efficient attack.

Moreover, the attack, if it ever becomes possible, will be of little to
no help in determining the original password (which you'd need for
logging in to the application). This is because the final hash returned
by phpass is also "only" 128 bits long. It is just not enough to
reliably determine the exact 128-bit $hash + $password string. Even if
you're ever able to search a keyspace this large (which is unrealistic),
you'll get a match when you have tested about 2 to the 128th power of
possibilities. This could correspond to an empty $password or to almost
any other $password - you would not know if you have found the one. And
the $hash + $password string that you would have found would be unusable
to you - well, unless you repeat the process for all previous stretching
iterations, in which case you do not bypass the stretching loop (instead
you sort-of handle it in the reverse order, also increasing your total
cost to an unacceptable level).

There's really no issue here.

tkok [15.05.2010 14:23:03]

#

timoh kirjoitti:

Tätä asiaa täytyy lähteä ajattelemaan pahimman mahdollisen tilanteen kannalta, eli esim. järjestelmän kiintolevyt pihistetään ja hyökkääjä saa haltuunsa käytännössä kaiken muun paitsi käyttäjän salasanan.

Tätä varten pitää käyttää kovalevyn kokonaisuudessaan salaavia ohjelmia. Esimerkiksi Utimacon safeguardi: http://go.utimaco.com/products/.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta