🛡️ Bezpečnost databází

Klíče od školy

O čem to je

Školník má klíče od všech místností. Učitel jen od svého kabinetu a tříd, žák od své skříňky. Nikdo nemá víc klíčů, než potřebuje. Když žák klíč ztratí, zloděj se nedostane do ředitelny.

Databáze funguje stejně. Obsahuje známky, adresy, rodná čísla, hesla. Každý uživatel smí jen to, co nutně potřebuje. Tady se naučíš, jak se oprávnění nastavují a jak data chránit.

Nové pojmy

Uživatelský účet databázeJméno a heslo, pod kterým se člověk nebo aplikace připojuje k SŘBD. Každý účet má svá oprávnění.Účet ucitel pro aplikaci žákovské knížky.
Oprávnění (privilegium)Povolení provést určitou operaci s určitým objektem.Smí číst (SELECT) tabulku znamky.
DCL (Data Control Language)Příkazy SQL pro řízení přístupu: GRANT (přiděl oprávnění) a REVOKE (odeber oprávnění).GRANT SELECT ON znamky TO zak;
RolePojmenovaná skupina oprávnění. Přidělíš ji uživatelům a nemusíš každému nastavovat vše zvlášť.Role ucitele: čtení a zápis známek.
Princip nejmenších oprávněníKaždý účet dostane jen ta oprávnění, která nutně potřebuje ke své práci. Nic navíc.Aplikace, která jen zobrazuje rozvrh, nesmí mazat tabulky.

Přidělení a odebrání

  • GRANT SELECT ON znamky TO zak;
  • GRANT SELECT, INSERT, UPDATE ON znamky TO ucitel;
  • REVOKE UPDATE ON znamky FROM ucitel;

Žák smí známky jen číst. Učitel je smí číst, vkládat a měnit. Poslední příkaz učiteli právo měnit zase odebere. (Přesný zápis jména uživatele se mezi SŘBD liší, třeba v MySQL 'ucitel'@'localhost'.)

Další ochrana dat

OpatřeníProti čemu chrání
oprávnění a roleneoprávněnému čtení a změnám
hesla ukládat jen jako hash (Argon2, bcrypt), nikdy čitelněúniku hesel při krádeži databáze
šifrované spojení (TLS) a šifrování diskuodposlechu a krádeži nosiče
pravidelné zálohy a jejich zkušební obnovaztrátě dat (havárie, chyba, ransomware)
protokolování (logy) přístupůnevysledovatelnému zneužití

Databáze s osobními údaji (jména, adresy, známky žáků) spadají pod GDPR, nařízení EU 2016/679. Správce musí údaje chránit a zpracovávat jen v nutném rozsahu.

Aplikace e-shopu se k databázi připojuje účtem root se všemi právy. Co je špatně?
Porušuje princip nejmenších oprávnění. Když útočník aplikaci zneužije, může smazat celou databázi i ostatní databáze na serveru. Aplikace má mít vlastní účet jen s právy SELECT, INSERT, UPDATE (a případně DELETE) na své tabulky.
Proč se hesla neukládají jako text, ale jako hash?
Hash je jednosměrný otisk: z hesla ho spočítáš snadno, zpátky to prakticky nejde. Při přihlášení se spočítá hash zadaného hesla a porovná s uloženým. Když někdo databázi ukradne, hesla nezíská přímo. Používají se pomalé algoritmy s „solí“ (Argon2, bcrypt), ne rychlé MD5.
✗Zálohu máme, protože databáze běží na dvou discích v RAID.
✓Záloha je samostatná kopie dat na jiném místě. RAID chrání jen před selháním disku.

Když někdo omylem smaže tabulku nebo data zašifruje ransomware, RAID tu změnu okamžitě provede na obou discích.

Přístup řídí DCL: GRANT přiděluje, REVOKE odebírá oprávnění, role je seskupují. Platí princip nejmenších oprávnění. Hesla ukládej jako hash, dělej zálohy a chraň osobní údaje podle GDPR.

SQL injection

O čem to je

Na přihlašovací stránce napíše útočník do pole heslo podivný text s apostrofy. A je přihlášený, aniž by heslo znal. Tomuto útoku se říká SQL injection (vložení SQL kódu). Patří dlouhodobě k nejčastějším zranitelnostem webových aplikací.

Pochopíš, jak útok funguje, a naučíš se jedinou spolehlivou obranu. Každý programátor, který pracuje s databází, ji musí znát.

Nové pojmy

Dotaz SQLPříkaz pro databázi, např. SELECT * FROM uzivatele WHERE jmeno = 'eva';. Text v něm je v apostrofech.Aplikace dotaz sestaví a pošle SŘBD.
SQL injectionÚtok, při kterém útočník vloží do vstupu (formulář, adresa) kus SQL kódu. Aplikace vstup slepí do dotazu a SŘBD ho provede jako příkaz.Do pole heslo napíše ' OR '1'='1.
Parametrizovaný (připravený) dotazDotaz se zástupnými znaky (? nebo %s) místo hodnot. Hodnoty se pošlou zvlášť a SŘBD je vždy bere jen jako data, nikdy jako kód.WHERE jmeno = ? AND heslo_hash = ?
Validace vstupuKontrola, že vstup odpovídá očekávání (číslo je číslo, e-mail má zavináč). Doplňková ochrana, sama nestačí.ID objednávky musí být celé číslo.

Jak útok funguje

Aplikace v Pythonu skládá dotaz spojováním řetězců:

  • dotaz = "SELECT * FROM uzivatele WHERE jmeno = '" + jmeno + "' AND heslo = '" + heslo + "'"
Poctivý uživatel zadá jméno eva a heslo tajne. Dotaz: … WHERE jmeno = 'eva' AND heslo = 'tajne'. Vše v pořádku.
Útočník zadá jméno eva a heslo ' OR '1'='1.
Po slepení: … WHERE jmeno = 'eva' AND heslo = '' OR '1'='1'.
AND má přednost před OR. Podmínka zní: (jméno eva a prázdné heslo) nebo 1 = 1. Druhá část platí vždy.
Dotaz vrátí všechny uživatele a aplikace útočníka přihlásí.

Obrana

  • cur.execute(
  •     "SELECT * FROM uzivatele WHERE jmeno = ? AND heslo_hash = ?",
  •     (jmeno, heslo_hash)
  • )

Hodnoty jdou do SŘBD odděleně od textu dotazu. Útočníkův vstup ' OR '1'='1 se pak hledá jako obyčejný (divný) text a nic se nestane. Navíc se tu neporovnává heslo, ale jeho hash.

  • Vždy parametrizované dotazy (nebo knihovna ORM, která je používá).
  • Nejmenší oprávnění účtu aplikace: i úspěšný útok pak napáchá méně škody.
  • Validace vstupu jako doplněk.
  • Nevypisuj uživateli chybové hlášky databáze, prozrazují její strukturu.
Adresa e-shopu je …/zbozi?id=15 a aplikace dělá "SELECT * FROM zbozi WHERE id = " + id. Co když útočník zadá id=15; DROP TABLE zbozi?
Pokud SŘBD a knihovna dovolí víc příkazů najednou, provede se i DROP TABLE a tabulka zmizí. I když ne, útočník může přidat OR 1=1 a vypsat všechno. Obrana: parametr WHERE id = ? a kontrola, že id je celé číslo.
Stačí jako obrana z textu odstranit apostrofy?
Ne. Číselné parametry apostrofy vůbec nepotřebují (id = 15 OR 1=1) a různé SŘBD a kódování mají různé triky. Filtrování je křehké. Spolehlivou obranou jsou parametrizované dotazy.
✗Formulář má v prohlížeči kontrolu v JavaScriptu, takže SQL injection nehrozí.
✓Vstup vždy ošetři na serveru a dotazy posílej parametrizované.

Kontrolu v prohlížeči útočník snadno obejde, třeba tím, že pošle požadavek přímo bez prohlížeče.

SQL injection vzniká, když aplikace slepí uživatelský vstup do textu dotazu. Spolehlivě ji zastaví parametrizované dotazy. Doplňkem je nejmenší oprávnění, validace na serveru a skryté chybové hlášky.