2008/18 - 20.5.2008
Jednocestné zabezpečení citlivých údajů v databázi Ing. Jan Malý, Vysoké učení technické v Brně, Fakulta elektrotechniky a komunikačních technologií, Ústav telekomunikací, Purkyňova 118, 612 00 Brno, Česká republika email:
[email protected]
Abstrakt. Hašovací funkce jsou typickým zástupcem jednocestného zabezpečení dat, které se používá pro účely autentizace a ověřování. Tyto funkce převádí libovolné zdrojové texty o různé délce na konečné posloupnosti symbolů z konečné množiny znaků, které nazýváme haše. Jedno z jejich mnoha využití je zabezpečení citlivých údajů v databázi, které zejména s prudkým rozvojem webových aplikací stále získává na významu. V tomto článku se pokusíme analyzovat možnosti uplatnění hašovacích funkcí při uložení údajů do databáze a podíváme se na praktickou realizaci takto zabezpečeného systému na prostředí Apache / PHP při propojení s MySQL.
1
Úvod
Představa absolutní bezpečnosti v dnešním počítačovém světě je vždy idylická a prakticky neexistuje metoda, jak citlivé údaje dokonale ochránit. Prakticky všechny moderní systémy ukládání dat jsou založeny na reprezentaci pomocí databáze, která je nejčastěji relační. Taková databáze pracuje na principu dotaz – odpověď. Vzhledem ke komplexnosti webových řešení už bezpečnost databáze proti neoprávněným přístupům dávno nezáleží jen na samotném zabezpečení databázové aplikace – velmi často se setkáváme se zneužitím dotazu z nezabezpečeného systému, který má k databázi přístup povolen. Tyto útoky splňují všechny předpoklady podstrčení škodlivého kódu a typickým zástupcem je SQL Injection. Z tohoto důvodu je již nutné uvažovat o metodách, které útočníkovi znemožní odhalení citlivé informace i v případě, že získá přístup k údajům, uloženým v databázi. Pokud jsou tato citlivá data ekvivalentem přístupových hesel, pak můžeme ukládat jejich jednocestně zakódovaný tvar a přístupový údaj uživatele po stejném zakódování pouze srovnat s údajem v databázi. Obrovskou výhodou takového přístupu je, že nehledě na kvalitu zabezpečení nemá nikdo (ani administrátor systému) přístup k původnímu tvaru hesla. To je přínosné i z dalšího hlediska – typický uživatel moderního webu používá pouze několik málo hesel k přihlašování do celé škály aplikací a odhalení byť jen jednoho z nich mu může způsobit velké nepříjemnosti.
2
Hašovací funkce
Typickým zástupcem hašovacích algoritmů v moderních webových systémech jsou MD5 a SHA. Z obecného pohledu obvykle požadujeme u těchto funkcí následující vlastnosti: • jednosměrnost - označíme-li hašovací funkci H(), zprávu z a výsledný haš h, pak při platnosti H(z) = h (1) nesmí existovat postup, jak z haše h stanovit původní zprávu z. • bezkoliznost - dva různé řetězce nesmí mít stejný haš. Tohoto nelze v praxi nikdy docílit – je to způsobeno mapováním prakticky neomezené množiny řetězců znaků na množinu konečnou. Požadavek obvykle přeformulujeme tak, že pro praktické účely je nemožné dojít ke koliznímu stavu.
18 - 1
2008/18 - 20.5.2008
• lavinovitý efekt - velmi vítanou vlastností algoritmů je velmi vysoká míra dopadu malé změny ve zprávě z na výsledný hash h. Typicky se negací jednoho bitu zdrojové zprávy změní přibližně polovina bitů výsledného haše. Narozeninový paradox. Tento problém souvisí s kolizemi. Kolize označuje stav, kdy platí H(z1 ) = H(z2 ) ,
z1 6= z2
.
(2)
Vezmeme-li si konečnou skupinu různých osob, pak s jejich rostoucím počtem je statisticky dokázána rostoucí pravděpodobnost faktu, že alespoň dva jedinci mají narozeniny ve stejný den – přičemž tento růst je poměrně strmý [1]. Stejný pravděpodobnostní model se dá aplikovat také na hašovací funkce. Protože množina, ve které hledání kolize provádíme, je obrovská, můžeme si dovolit dokonce statistickou hypotézu, √ že kolizi s vysokou pravděpodobností nalezneme po vykonání hašovací funkce maximálně 1, 25 S-krát, kde S je počet různých výstupů se hašovací funkce se stejnou pravděpodobností. Hledání kolizních stavů není pro účely našeho článku smysluplné, neboť při odhalování původních zpráv z hašů mají smysl pouze útoky hrubou silou. Zmiňujeme ho z toho důvodu, že hraje nesmírně důležitou roli při autentizaci nebo autorizaci dat. Díky existenci kolize totiž můžeme podstrčit příjemci jiná data se stejným hašem, a i když spektrum změn, které můžeme mezi dvěma zprávami provést, je mizivé, stále jde o nebezpečný fakt, zejména pokud haš je jediným zabezpečením systému. Parametr bezkoliznosti je důležitým hodnotícím prvkem při analýze vlastností hašovací funkce.
2.1
Algoritmus MD5
Velmi oblíbený způsob (díky relativní jednoduchosti implementace) jednocestného kódování je MD5 [5]. MD5 generuje na základě původní zprávy 128-bitový haš. Princip jeho fungování je ilustrován na obrázku 1. Od MD5 se v poslední době spíše ustupuje vzhledem k jeho náchylnosti ke kolizím [2]. S ohledem na jeho nepříliš velkou výpočetní náročnost je také velmi vhodným kandidátem na útoky formou hrubé síly, především pro jednoduché zprávy s několika znaky z malé množiny. Díky všeobecnému povědomí o tomto systému existuje také celá řada online databází hašů a jejich odpovídajících zdrojových textů – tímto způsobem je možné realizovat tzv. slovníkový útok.
2.2
Algoritmus SHA
Kde MD5 selhává, nastupuje SHA (Secure Hash Algorithm). SHA existuje v několika verzích, nejpoužívanější SHA-1 má délku haše 160 bitů. Princip je popsán na obrázku 2. Pět algoritmů SHA (SHA-1, SHA-224, SHA-256, SHA-384 a SHA-512) bylo navrženo v National Security Agency (NSA) a publikováno jako U.S. standard [7]. Ačkoliv má větší odolnost proti kolizím než MD5, nedávno byl prolomen skupinou čínských vědců [6] a byly získány kolize již při výpočetní složitosti 261 proti původně předpokládaným 280 .
3
Model uložení dat
Základní model uložení citlivých dat do databáze je použít na data prostou hašovací funkci. Toto řešení ale nese s sebou následující rizika: • Bezpečnost je závislá na vstupu uživatele. Krátká hesla z malé množiny často používaných znaků jsou snadným terčem útoků hrubou silou nebo slovníkových útoků. • Problém existence stejných hašů. Nikde není řečeno, že dva uživatelé nebudou mít v databázi uložen stejný údaj. Pak ale také jejich haš bude stejný, a útočník již na první pohled ví, že jejich údaje jsou shodné, což mu zjednoduší situaci. 18 - 2
2008/18 - 20.5.2008
Obr. 1
Princip fungování hašovací funkce MD5. Při zpracování jednoho 512-bit bloku původní zprávy se využívá čtyř 32-bit slov A, B, C, D. G je nelineární funkce, která se v každém kroku mění, bloky se symbolem + představují modulo sčítačku, Xi je blok původní zprávy a Ki je konstanta, která se v každém kroku mění. Symbolem << označujeme bitovou rotaci doleva, velikost rotace se mění s každým krokem.
Druhá metoda spočívá v zabezpečení pomocí metody salted hash. Tento princip řeší naznačené problémy přidáním speciálního řetězce salt - ten jednak doplní vstupní řetězec na určitou minimální velikost, čímž zkomplikuje útok hrubou silou. Problém metody salted hash je nutnost pamatovat si onu sůl (salt), a to jak při vytváření hesla, tak při autentizaci. Salt by měl navíc být unikátní pro každého uživatele, abychom předešli druhému problému s duplicitou hašů při stejném údaji. Protože většinou salt uložíme v databázi spolu s ostatními údaji uživatele, stále může útočník najít relativně jednoduchý způsob, jak metodu hrubé síly využít. Klíčem je ono spojení salt a původní zprávy, které by nemělo být záležitostí čistého připojení řetězce. Lepší řešení je použít metodu HMAC (Hashed MAC nebo Keyed Hash, [3]), kdy jedním parametrem je původní zpráva a druhým sůl. HMAC je definována jako HMACH (m) = H ((K ⊕ opad) k H((K ⊕ opad) k m))
,
(3)
kde m je původní zpráva, H() je hašovací funkce, K je kombinační parametr (v našem případě salt) a opad a ipad jsou konstanty. Tato metoda, ačkoliv byla původně navržena k mírně odlišnému použití, již zvyšuje výpočetní náročnost případného útoku hrubou silou, nehledě na fakt, že útočník musí mít přehled o funkčnosti našeho systému. Příklad za pomoci blokového schématu je zabezpečení popsáno na obrázku 3. Uložení salted hash. Ideálním stavem této rozšířené metody jednocestného zabezpečení by byla možnost uložit si salt odděleně od údajů v hlavní databázi. Tuto možnost bohužel vždy nemáme, a jiná forma uložení dat by mohla být vzhledem k atomicitě operací a nativní víceúlohovosti webového prostředí také potencionálně nebezpečná, nehledě na rychlost a efektivitu. Logickým řešením je vytvoření parametru salt na základě unikátního údaje každého uživatele z
18 - 3
2008/18 - 20.5.2008
Obr. 2
Princip fungování hašovací funkce SHA-1. Při zpracování jednoho bloku původní zprávy se využívá pěti 32-bit slov A, B, C, D, E. g je měnící se nelineární funkce, bloky se symbolem + reprezentují 32-bit modulo sčítačku, Wt je rozšířený blok původní zprávy pro krok t a Kt je konstanta, která se pro každé t mění. Symbolem << označujeme bitovou rotaci doleva o daný počet bitů.
message
HMAC( ) sha-1
database
salt
Obr. 3
Příklad modelu uložení citlivého údaje message do databáze s generovaným salt
databáze pomocí matematického výrazu, který byl oběma stranami předem dohodnut, popřípadě využití symetrické / asymetrické metody šifrování. Všechny tyto metody ale závisí na neznalosti útočníka, který nesmí mít ponětí o operacích na pozadí vytváření hašů. Problémy jednocestného uložení. Jak již bylo zmíněno výše, největší výhodou práce s hašovacími funkcemi při ukládání dat do databáze je jednocestnost „legálníhoÿ režimu práce. To na druhé straně ale omezuje možnosti těchto algoritmů pouze na taková data, která nepotřebujeme v původním tvaru. Při ukládání přístupových hesel by častý argument pro jejich zachování ve zdrojovém tvaru byla možnost jejich obnovení v případě ztráty hesla uživatelem. Řešením je vygenerování nového přístupového hesla a jeho zaslání uživateli webové aplikace takovou cestou, jejíž bezpečnost nezpochybňujeme a která do jisté míry přebírá odpovědnost v bezpečnosti za nás – nejčastěji se využije email uživatele. Protože se stále vystavujeme nebezpečí zobrazením hesla ve zdrojovém tvaru, je nejlepší možností práce s aktivačními odkazy, který jsme popsali v [4]. Pro zajímavost uvádíme vývojový diagram celého řešení na obrázku 4.
18 - 4
2008/18 - 20.5.2008
Obr. 4
Komplexní model správy uživatelských hesel s maximálním zabezpečením proti prozrazení hesla. Zdroj: [4]
18 - 5
2008/18 - 20.5.2008
4
Praktická realizace hašování v PHP
Při realizaci webových aplikací na serveru Apache se nejčastěji dostaneme k použití skriptovacího jazyka PHP. Ten hašování velmi zjednodušuje hotovou implementací všech potřebných algoritmů. Je tedy možné přímo přistoupit k funkcím md5() nebo sha1() pro vytvoření výsledného haše ve formě řetězce, kdy jediným vstupním parametrem obou algoritmů je původní zpráva. Opatrnosti je nutno dbát zejména při uvažování implementačních rozdílů mezi různými formáty řetězců jako 8bit ASCII, UTF-7, UTF-8 a UNICODE – zejména je třeba dodržet stejný formát na obou stranách kódování, tedy při tvorbě hesla a jeho ověření. Použití algoritmu HMAC je možné za pomoci funkce hash hmac(), která je k dispozici od PHP verze 5.1.2, dříve ve formě PECL rozšíření hash. Její parametry jsou tři: hašovací algoritmus, vstupní data a klíč K. Všechny tři údaje jsou řetězce. Délka výsledného řetězce rovna standardní délce výsledku použité hašovací funkce. Při praktické realizaci je také důležité správným způsobem generovat náhodný údaj salt pro metodu salted hash. Vzhledem k síle hesla by měl tento náhodný řetězec obsahovat alespoň malá a velká písmena a čísla. Jen uvažováním velkých a malých písmen máme k dispozici 56n možností, kde n je maximální uvažovaná délka řetězce. Z tohoto důvodu je také vhodné, abychom se do webových systémů, které neznáme a o jejichž bezpečnosti máme pochyby, registrovali s dostatečně dlouhým heslem s maximálním využitím výše zmíněné množiny znaků. Při využití asymetrické kryptografie doporučujeme řešení OpenSSL v PHP, které je zcela nezávislé na SSL (Secure Socket Layer). Díky němu jsme schopni vytvořit velmi snadno pár veřejný klíč / privátní klíč a využít je pro zašifrování údajů. Na závěr uvedeme výpis krátkého kódu, který zabezpečí zdrojový text src pomocí soli salt: $src = "zdrojova zprava";
// zdroj
// vygenerovani 40 znaku dlouheho salt $chars = "abchefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ0123456789"; srand((double)microtime()*1000000); // nastaveni gen. nahodnych cisel $salt = ""; for($i=0; $i<40; $i++) { $num = rand() % 56; // nahodna pozice znaku $tmp = substr($chars, $num, 1); // ziskani znaku $salt = $salt . $tmp; // pridani znaku k retezci } // zakodovani $zakod = hash_hmac("sha1", $src, $salt);
5
Závěr
Zabezpečení databáze z hlediska webových aplikací se týká především jednocestného uschování přístupových údajů k pozdějšímu ověření autentizovaného přístupu. V článku jsme se zmínili o způsobech jednocestného zabezpečení zdrojových řetězců formou MD5 a SHA-1 hašů, naznačili princip HMAC a navrhli optimální model zabezpečení citlivých dat v databázi z hlediska potřeb a možností webové aplikace. V poslední části jsme se krátce věnovali praktické implementaci pomocí prostředí PHP / Apache. Z výše uvedeného textu je patrné, jaké základní útoky slouží k rozluštění přístupových údajů z uložených hašů, a je zřejmé, že v některých případech nejde o utopii, ale o velmi snadno realizovatelnou úlohu, jejíž nároky v některých případech nejsou utopické. Zejména při návrhu webových aplikací a jejich napojení na databázi bychom proto měli mít na paměti větu – bezpečnost systému není jeho vlastnost, ale vždy pouze míra.
18 - 6
2008/18 - 20.5.2008
Reference [1] Abramson, M., Moser, W. O. J. More birthday surprises. Amer. Math. Monthly, sv. 77, s. 856–858, 1970. [2] Klíma, V. Tunely v hašovacích funkcích: kolize md5 do minuty. In IACR ePrint archive Report, vol. 105, 2006. [3] Krawczyk, H., Bellare, M., Canetti, R. HMAC: Keyed-Hashing for Message Authentication. RFC 2104 (Informational), Únor 1997. [4] Malý, J., Kacálek, J. Zabezpečení webových aplikací ii. - databáze. Access Server, 2007. [5] Rivest, R. The MD5 Message-Digest Algorithm. RFC 1321 (Informational), Duben 1992. [6] Schneier, B. Sha-1 broken. Schneier on Security, 2005. [7] SECURE HASH STANDARD. Federal Information Processing Standards Publication 180-1, 1992.
18 - 7