0. Vsimnete si, ze v tomto pripade nemusi server vubec challenge posilat. Klient si muze challenge domyslet (je to aktualni cas). Proc se tedy server obtezuje s jejim generovanim? Pokud chcete challenge ze serveru, at je skutecne nahodna.
1. Naprosto to nechrani proti "grand chessmaster" problemu (on-line man-in-the-middle). U https mam moznost zkontrolovat certifikat druhe strany. Tady nemam nic.
2. Nevim, jestli pouzita funkce now() nema problemy s prechodem z letniho casu na zimni ("zopakuje se hodina", takze jde prehrat hodinu stare zpravy).
3. Obecneji, kazda synchronizace casu na serveru otevira prostor pro replay utok.
4. Kde je ochrana proti slovnikovemu utoku? Napriklad omezeni poctu pokusu za jednotku casu apod.
4b. Kde je ochrana proti slovnikovemu utoku II? Utocnik odposlechne challenge a ji odpovidajici heslo a potom off-line zkusi slovnikovy utok "uhodni heslo, aby z nej a ze znameho challenge vznikl znamy hmac". - Tohle je nesrovnatelne jednodussi nez napadnout nejakou variantu Diffie-Hellmana, kterou se zasifruje kanal jeste drive, nez nejaka autentifikace vubec probiha.
5. Ulozeny MD5 hash hesla je vlastne heslo do systemu. (To, co uzivatel chape jako "heslo", je jen mnemotechnicka pomucka pro vytvoreni skutecneho hesla.) Takze mame v databazi de facto ulozena skutecna hesla. To jsme si pomohli...
6. Zpusob, kdy overeni na serveru nepouzije odeslany challenge, ale challenge obdrzeny od klienta (tj. potencialne pozmeneny) rozhodne nevzbuzuje duveru. Kdyby nic, server by mel overit, ze tento challenge byl skutecne tomuto klientovi odeslan (tato vazba pritom v tabulce chybi!). A mel by overit, ze to neni prilis davny challenge.
7. Kdyz uz jsme u toho, pouziti MD5 take nevzbuzuje uplnou duveru :-) Ne ze by utoky byly prakticke (rychle hledani kolize je porad neco jineho nez invertovani hashe), ale u soudu vas kazdy trochu schopny pravnik roztrha :-)
Rekl bych, ze predevsim #4b je vyznamny duvod, proc bych cloveka s takovouto implementaci vyhnal. Existuji lepsi protokoly, ktere takto napadnout nelze. Jsou mozna implementacne slozitejsi, ale knihovny existuji (a navic clovek to pise jednou a pouziva mockrat).
6. Vazba klient-challenge by se jistě ukládat mohla, ale bezpečnost by to podle mě zvýšilo jen minimálně. Pokud bych challenge uložil do session proměnné a útočník by byl schopen odposlechnout challenge, jistě by byl schopen odposlechnout i session ID. Vazba přes IP adresu může být problematická (jeden člověk může používat více adres). Průběžné mazání starých challengů je v článku zmíněno.
7. Postup je na hashovací funkci nezávislý. MD5 jsem zvolil proto, že je nejznámější a známé útoky se k tomuto použití nedají nijak využít.
4b. Můžete tedy prosím popsat postup, který tímto problémem netrpí? Klidně formou honorovaného článku, redakce vám jistě vyjde vstříc.
The protocol referred to as "HTTP/1.0" includes the specification for
a Basic Access Authentication scheme[1]. That scheme is not
considered to be a secure method of user authentication, as the user
name and password are passed over the network in an unencrypted form.
This section provides the specification for a scheme that does not
send the password in cleartext, referred to as "Digest Access
Authentication".
The Digest Access Authentication scheme is not intended to be a
complete answer to the need for security in the World Wide Web. This
scheme provides no encryption of message content. The intent is
simply to create an access authentication method that avoids the most
serious flaws of Basic authentication.
Kupříkladu asi nejde dost dobře udělat volitelné přihlášení (jako například tady u přidávání příspěvku - můžu se přihlásit, ale nemusím).
Uživatelská přítulnost také poněkud trpí, protože pokud někdo přijde na chráněnou stránku, nejsem schopen mu rozumně a přehledně sdělit, proč musí být přihlášen (je možné, že je tu omylem), a navíc nedávám uživateli zrovna mnoho možností, jak případně zbloudění napravit (vyskočí na něj přihlašovací okno a dokud s ním něco neprovede, nemůže udělat back, zvolit z menu jinou stránku a podobně).
A v neposlední řadě, myslím, že neexistuje zaručená a ve všech prohlížečích funkční metoda, jak se odhlásit (kromě restartu prohlížeče).
Pripadne mouchy ma, ale to co jste uvedl je naprosto mimo misu
1) resi se tu BEZPECNOST prihlasovani
2) pokud uzivatel nevi proc se ma prihlasit tak evidentne leze nekam kde nema co delat - proto tam to prihlasovani je aby tam nelezl :-O
3) pote co neprojde overovacim mechanismem je mozne zobrazit stranku s informaci kde je, proc po nem bylo pozadovano prihlaseni a svete div se muze si pote kliknout na jakykoliv odkaz ktery mu predhodime, nebo si samozrejme muze kliknout ve svem prohlizeci "zpet"
Michal poukazuje na to, že použití HTTP autentizace je někdy jednoduše nevhodné. A např. chybějící možnost odhlášení bez zavření prohlížeče může být docela zásadní problém. Proto celá tato "šaškárna".
Pro vaše požadavky zmíněné problémy problematické nejsou (se zřejmě záměrným vynecháním problému odhlašování nebo možnosti volitelného přihlášení). To ale neznamená, že to není problematické pro nikoho.
Toto prohlížeče (přinejmenším Firefox 1.5 a IE6) k zapomenutí přihlašovacích údajů bohužel nepřiměje, při příštím zobrazení stránky se přihlašovací údaje opět pošlou. Kdysi fungovalo odhlášení pomocí odkazu http://logout:logout@www.example.com/, tyto odkazy jsou ale od IE6 pod XP-SP2 defaultně zakázané.
Asi nejzajímavější informace v článku podle mě je, že od IE6SP1 lze platnou autentizaci smazat pomocí <script>document.execCommand('ClearAuthenticationCache');</script>.
Ad 4b. Vetsinou jde o veci publikovane (a mnohdy patentovane :-)). Prislo by mi nefer postavit honorovany clanek na tom, ze neco opisu z literatury.
Zaklad problemu je v tom, ze uzivatele nejde donutit, aby pouzival silne heslo. Pocet bitu, ktere si clovek bezchybne zapamatuje, je silne omezen. Je pravdepodobne, ze vetsina systemu zalozenych na heslech podlehne slovnikovemu utoku.
Kdyz tohle bylo receno, porad jeste je moznost to utocnikovi velmi ztizit. Je velky rozdil, pokud muze otestovat desetitisice hesel za sekundu (z nich pocita jen "rychly" MD5 hash) nebo zda ho donutime hodne pocitat a overeni jednoho hesla trva sekundy. - Dokonce tomu jde i zabranit, pokud pomoci hesla (a i nasledne) podepisujeme jen nahodne stringy nebo pokud pripada v uvahu mnoho hesel.
Takze prvni napad, zalozeny na asymetricke sifre (uvadim ho proto, ze je z me hlavy; ostatni veci budu citovat z literatury :-)): Heslo se pouzije jako seed to dobreho generatoru pseudonahodnych cisel. Pomoci nej vygeneruji standardnim postupem key-pair. Server dostane public key. Prihlasovani vypada tak, ze v klientu do stejneho generatoru zadam heslo (tedy tentyz seed jako puvodne), vygeneruju privatni klic a zasifruju timestamp. Server to rozsifruje ulozenym klicem, overi, ze timestamp je v rozumnem rozsahu (aby nedoslo k replay stare zpravy), konkatenuje timestamp se svym timestampem, zasifruje to ulozenym klicem a posle nazpet. Klient to rozsifruje, overi, ze puvodni timestamp je rovny jeho timestampu a ze timestamp serveru je v rozumnem rozsahu (druha prevence replay). Vezme timestamp serveru, zasifruje jej svym klicem a posle to na server. Server overi, ze to odpovida jeho puvodni zprave a povazuje uzivatele za autentifikovaneho. (Z praktickych duvodu muze byt dobry napad padovat timestamp nebo konkatenaci timestampu nahodnymi bajty.)
Dalsi metody:
1. EKE (popsano v S.M.Bellovin, M.Merrit: Encrypted Data Exchange: Password-Based Protocols Secure Against Dictionary Attack. Proceedings of the 1992 IEEE Computer Society Conferenec on Research in Security and Privacy; viz tez B.Schneier, Applied Cryptography, kapitola 22.5; patentovany algoritmus). Myslenka je v tom, ze se pomoci hesla zasifruje nahodny public klic, odpovidajicim private klicem se sifruje dalsi nahodny klic, a pak si obe strany prokazou, ze tento druhy nahodny klic znaji tak, ze si vymeni zasifrovane nahodne stringy. (Klient posle sifrovany nahodny s1, server desifruje s1 a posle sifrovanou konkatenaci s1 a nahodneho s2, klient desifruje zpravu, overi spravnost s1 a posle zasifrovany s2, server desifruje a overi spravnost s2.) Slovnikovy utok je nemozny, nebot vse je nahodne. - K odstraneni man-in-the-middle se jeden z tech nahodnych klicu nevytvori nahodne, ale Diffie-Hellmanem. Man-in-the-middle si musi s kazdou stranou dohodnout vlastni klic, jinak bude uprostred jen smutne koukat na zasifrovane zpravy (tj. pasivne odposlouchavat). Vzhledem k tomu, ze ten klic si obe strany predavaji ve zprave a ze ke konstrukci zpravy je potreba znat to heslo, ma ten man-in-the-middle smulu.
2. Fortified Key Negotiation (popsano v R.J.Anderson, T.M.A.Lomas: Fortifying Key Negotiation Schemes with Poorly Chosen Passwords. Electronic Letters, v.30, n.13, 23 Jun 1994; viz tez B.Schneier, Applied Cryptography, kapitola 22.6). Myslenka je v tom, ze krome normalni hash funkce se jeste pouzije hash funkce s mnoha kolizemi (takze poslanemu hashi muze odpovidat velmi mnoho hesel. Touto funkci se hashuje neco, co obsahuje puvodni heslo a nahodne Diffie-Hellman-generovany klic. (Diffie-Hellman pripadneho in-the-middle-mana donuti, aby na obe strany pouzival jiny klic a tedy bude odhalen, kdyz si obe strany klic predavaji jako soucast hashe nebo sifry.) Odposlechnuti nestaci (zprave na drate odpovida mnoho moznych hesel) a man-in-the-middle nejde (bez znalosti hesla a vzhledem ke kolizi se nepodari na druhou stranu poslat spravnou zpravu). - Autentifikace pak probehne stejne jako v minulem bode - obe strany si navzajem dokazou, ze umeji zpravu s nahodnymi stringy desifrovat.
3. Schnorr (napr. C.P.Schnorr: Efficient Signature Generation for Smart Cards. Advances in Cryptology - EUROCRYPT, '88 Proceesings; viz tez B.Schneier, kapitola 21.3; patentovano). V tomto pripade jako private key zvolime hash hesla (pripadne modulo q), dopocteme public key a ten ulozime na serveru. Protokol je challenge-and-response - server posle dost velke nahodne cislo (Shnorr doporucuje 72-bitove cislo), klient posle odpoved a server overi, ze overovaci rovnice odpovedi vychazi. (Odolnost proti slovnikovemu utoku vychazi jen z pomalosti uvedenych vypoctu, podobne jako u mnou navrhovaneho schematu.)
Obecne ale myslim, ze utocnik pujde nejakou jinou cestou. Napriklad ze nabouchne prohlizec, ktery provadi ty javascripty, a ziska heslo tam odtud. Ale to uz je jina pohadka :-)
Mohl byste prosím popsat, proč se provádí jednotlivé kroky ve vašem schématu? Některé mi přijdou samoúčelné. Na druhou stranu mám dojem, že když bude náhodné číslo připojené k timestampu dostatečně velké a náhodné, tak je slovníkový útok prakticky nemožný (protože kromě hesla musím zkoušet i náhodná čísla).
Nevim presne, o kterych krocich mluvime. Je to ta oboustranna vymena nahodnych stringu (puvodne timestampu)? Ta zajistuje dve veci: Server vidi, ze uzivatel zna klic (protoze dokaze otevrit dlouhou zpravu, z ni vyndat substring a ten opet zasifrovat). Uzivatel vidi, ze server zna klic (a tedy ze nejakemu utocnikovi jen tak neposkytuje "munici" - zasifrovane pakety pro pozdejsi replay attack); pokud server nezna klic, uzivatel uz nic zasifrovaneho neposle.
(Pro timestampy ve skutecnosti je jeden z tech kroku nadbytecny - za predpokladu, ze se muzeme spolehnout na synchronizovane hodiny mezi klientem a serverem.)
Jestli to je to generovani public/private klice z hesla, tak to je ten zdrzujici krok, ktery ma odradit utocnika od slovnikoveho utoku. Pokud trva vygenerovani paru nekolik sekund, kolik hesel za den lze vyzkouset?
Djova, teda ted jsem to zmastil vsechno dohromady. Pouceni pro priste: Dam si kafe driv, nez budu takhle odpovidat. - Musim si ted odpovedet sam, jinak neusnu :-)
Nejdriv k rozpleteni man-in-the-middle: Normalne se o man-in-the-middle mluvi tehdy, kdyz sifruju a ten uprostred to resifruje. V nasem pripade se samozrejme o nic takoveho jednat nemuze. Samotna komunikace je nezabezpecena proti odposlechu a nezabezpecena proti manipulaci. Po prihlaseni muze teoreticky kdokoliv menit pakety, posilat za me prikazy a tak. Tohle vsechno plyne z rozhodnuti nepouzit SSL. (Obecne: Proti odposlechu je potreba sifrovat a pocatecni key exchange musi vyuzit sdileneho tajemstvi - hesla - aby MiM nemel sanci. Proti manipulaci staci pripojovat nejaky HMAC, zalozeny napriklad na vymenenem klici.)
V nasem pripade se snazime zabezpecit proti nasledujicim utokum:
- slovnikovy utok na heslo
- replay starych paketu
- "triknuti" uzivatele, aby pri zpracovani vhodne zvolene challenge prozradil neco o hesle.
K tomu memu protokolu: 1. Samozrejme tam neni potreba timestamp. Stejne jako v ostatnich protokolech, znalost klice (resp. jedne casti na klientu a druhe casti na serveru) staci posilat nahodne stringy a kontrolovat je. Klient posle s1 sifrovany svym klicem. Server desifruje s1 (nic s nim delat nemuze), pripoji k nemu s2 a zasifruje to svym klicem. Klient desifruje, odsouhlasi s1, zasifruje uz jen s2 a posle to serveru. Server to zkontroluje. Pokud s1 a s2 jsou dostatecne nahodne, replay se nepovede.
2. No a samozrejme neni *nutny* public/private klic. Jde to udelat i symetricky. Vyhoda pouziti public/private je v tom, ze na serveru ulozim jen jeden klic; i v pripade uniku dat ze serveru je utocnik nemuze pouzit na prihlaseni.
K EKE: S tim Diffie-Hellmanem jsem to zmastil neomluvitelne. Nic takoveho potreba neni. Jeste jednou shrnuti: Klient vytvori nahodny public/private par, public klic zasifruje pomoci sveho hesla a posle ho serveru. Server rozsifruje public klic, vygeneruje nahodny symetricky klic a zasifruje ho pomoci public klice a pak jeste pomoci hesla. Klient vse desifruje. Pak si oba stroje navzajem prokazou, ze ten symetricky klic znaji. Utocnik nemuze provest slovnikovy utok, nebot aby mu k necemu byl, musel by nasledne jeste prolomit asymetrickou sifru, aby se k symetrickemu klici dostal (az symetricky klic sifruje neco, kde lze zkouset poznat, zda mam spravny klic).
ad 0, 2: Challenge neni cas, ale poradove cislo, ten cas je v tabulce jenom proto, aby se dala dobre uklizet.
Ale nejlepsi reseni to neni, da se tim udelat DoS:
Uzivatel A dostane challenge X, uzvatel Z (zaskodnik) dostane X+1, ale zkusi odeslat svuj formular se svym heslem a challenge X, kdyz bude rychlejsi nez A, vymaze radek s challenge X z tabulky "challenges" a uzivatel A se neprihlasi. Kdyz tohle bude uzivatel Z opakovat dostatecne rychle, zabrani urcitemu procentu uzivatelu v prihlaseni. (ne ze se bude porad tupe prihlasovat, ale bude si opakovane nacitat prihlasovaci formular, dokud se mu challenge budou zvetsovat jen o 1, vidi, ze je tam sam, jakmile se mu challenge zvysi vice nez o 1, vi, na jake challenge ma utocit)
Obrana:
A. Limitovat pocet zobrazeni prihlasovaciho formulare na 1 adresu
+ zaroven to brani prilis rychlemu rustu tabulky challenges
- velka firma za http proxy s 1 IP adresu bude mit problem
- Porad jde udelat DDoS :-)
B. misto predikovatelne challenge z auto_incrementu pouzit neco jineho, napr.
$UNIQUE_ID (ovsem neresi nadmerny rust tabulky "challenge"). Pridelenou challenge
si ale misto do databaze muzu ulozit do $_SESSION a mam tim i zajistenu vazbu na browser, kteremu jsem challenge poslal (viz bod 6) a nemusim se starat o udrovani tabulky challenge v rozumnych mezich.
Co porad lidi maji s tou magickou $_SESSION ... proc se nerekne rovnou, ze se to ulozi do databaze nebo do souboru na disk a id zaznamu se posle klientovy v cookie ? Jenze pak by neslo machrovat s vetami typu "misto do databaze" ...
Na tohle (neukládání session na serveru) existuje jednoduchý trik: veškerá data poslat klientovi (např. v cookie) spolu s jejich digitálním podpisem (stačí k datům přidat tajné heslo a výsledek prohnat kvalitní hashovací funkcí). No a když klient pošle data s příštím požadavkem zpět, ověříme na serveru ten digitální podpis a pokud sedí, máme jistotu že jsou data autentická.