Komentáře k článku
Neautorizovaný přístup k datům

V posledních dnech, týdnech a měsících jsem několikrát slyšel a četl o tom, že velkým hráčům unikla nějaká data, případně se někdo dostal k informacím, které vidět neměl, a to naprosto jednoduchým způsobem. „Útočník“ pouze změnil nějaké číslo v adrese stránky a v prohlížeči se mu najednou ukázaly údaje, k jejichž prohlížení nebyl autorizován. Jak je to jen možné?
Jak se bránit?
Například před vrácením odpovědi kontrolovat, že je zalogován ten uživatel, který tu odpověď požaduje. Pokud to není on, tak vrátit login dialog…
User_id v kazdom dotaze je overkill
Do kazdeho SQL query pridavat id pouzivatela je asi overkill. Prava pouzivatela staci overovat v metode controllera (MVC architektura), alebo niekde v uvode kodu.
Re: User_id v kazdom dotaze je overkill
Hmm, ale jak chcete ověřit práva uživatele? Asi takhle: Patří tohle číslo faktury, na které se tento uživatel ptá, tomu uživateli? Čili jedním SQL dotazem navíc?
(Ikdyž nadruhou stranu, když předpokládáme normální workflow aplikace, tak aby uživatel kliknul na svou fakturu, musel před tím vidět seznam faktur, takže je máme v nějaké cache, takže by to spíš bylo: Dej mi všechny faktury toho uživatele (z cache), a z nich vyber tu hledanou).
Re: User_id v kazdom dotaze je overkill
Implementační detail :)
To je staré
Při práci s fakturami pro uživatele je skutečně nutné do každého dotazu vrazit where na ID uživatele a pokud možno ID uživatele vůbec neposílat na klienta, ale schovat ho třeba v session, jinak dochází přesně k tomu co je v článku. Překvapuje mě, že to v roce 2013 stále není všem jasné.
opakování taťka moudrosti
Staré a osvědčené věci se musí opakovat znovu a znovu, jinak je další generace nepřijme a vymizí.
Re: Neautorizovaný přístup k datům
Tímto trpěla samoobsluha Vodafonu pěkných pár měsíců. Člověk mohl měnit číslo v URL adrese a viděl přesně kolik Kč na které telefonní čislo bylo uhrazeno.
Automatická kontrola
Moje zkušenost je taková, že na co se dá zapomenout, na to se taky zapomene. Proto je důležité používat šablonovací systém s automatickým ošetřováním předávaných dat (jako obrana proti XSS, např. Nette Latte) a nějaký sestavovač dotazů, opět s automatickým ošetřováním dat (jako obrana proti SQL Injection, např. NotORM).
Tenhle problém je k vyřešení těžší, ale napadají mě dva možné přístupy, jak mu systémově zabránit:
get_order(user_id, id)
. V administraci, kde potřebuji přístup ke všem objednávkám, použijeme jiného databázového uživatele, který má přístup i k samotné tabulce. To neztrácí výhody globálního ID, ale je trochu těžší na nastavení a používání.Pak je tu samozřejmě ještě případ, kdy žádné ID uživatele nemám. Tam se dá aplikovat druhé řešení, jen místo
user_id
použijeme náhodnýtoken
. Použití GUID je v této situaci také možné, ale je potřeba dodat, že v jiných případech je spíš nevhodné. Inkrementace nebo hádání ID totiž není jediný způsob, jak se útočník může k datům dostat – ta můžou někde uniknout a pokud na jejich neuhodnutelnosti stavím zabezpečení, tak jde o pouhé Security by Obscurity.Re: Automatická kontrola
1. Primární klíč na fakturu je vždy ID z generátoru nebo autoincrementu a přes to nejede vlak. Navíc pořadové číslo faktury nelze u nové faktury před jejím commitem stanovit spolehlivě, proto ho nelze ani vrazit do primárního klíče a proto se faktury číslují dodatečně v druhém kroku.
2. Do databáze chodí webový server celou dobu pod jedním uživatelem.
Pro URL faktur lidí bez účtu se použije něco jako magic + údaje pro vyhledání faktury + salt dohromady 64 a víc byte to celé zašifrované solidním algoritmem se solidně dlouhým heslem + převod do tvaru vhodného pro URL. Bezpečnost je pak garantována kvalitou šifrovacího algoritmu a kvalitou hesla.
GUID je možné také, ale to se pak musí někde ukládat a opečovávat.
Re: Automatická kontrola
2. Že je to takhle na většině hostingů, ještě neznamená, že to není možné.
Cílem bylo navrhnout řešení, které by fungovalo automaticky, aniž bych na něco mohl zapomenout. Vámi popisované řešení je nejen zbytečně překomplikované, ale této podmínce se ani neblíží.
Re: Automatická kontrola
2. bezpecnost na urovni databaze je zaklad kazde seriozni aplikace. To, ze cela aplikace pouziva jednu uroven opravneni se da jete akceptovat u nejakeho soukromeho webu, kam si pise majitel co mel zrovna k obedu ale u business critical aplikaci je to naprosto neakceptovatelne.
HMAC
Proč tak složitě? Já osobně jsem pro takové věci implementoval „kontrolní“ hash pomocí nějaké HMAC funkce (hashovací fce s klíčem), který se hodil do URL v mailu. Má to tu výhodu, že to umožňuje i anonymní požadavky (ve smyslu objednávky), což někdy může zákazník chtít.
Re: HMAC
Protože kreativita útočníků je vskutku neuvěřitelná a čím méně toho ví, tím lépe.
Samozřejmě na jednoduchý webshop jde HMAC použít také.
Userid když neexistují uživatelé
Nejjednodušší je opravdu dotazy psát stylem „where orderno = .. and userid = …“ nebo „where orderno = … and user_authorized(…)“. Přičemž to userid zná jen server, v URL se neobjevuje. Server si ho může zapamatovat buď při přihlášení uživatele, nebo ho může vygenerovat při „přihlášení uživatele“. V uvozovkách je proces, kdy uživatel na serveru vlastně žádný účet nemá. V tomto procesu si server vygeneruje dvojici – userid a randomid. Do databáze si uložím tuto dvojici, na klienta jako cookie předám randomid (nebo bude součástí url). Když se pak někdo dotáže, tak já si přeložím randomid na userid a dotaz provedu. Jakmile dojdu k názoru, že už se na to podívat nesmí, tak jen smažu záznam z překladové tabulky, takže už nikdo ani „správné“ userid nepodvrhne.
K přístupu k „cizím datům“ je tedy potřeba znát číslo objednávky a randomid. Randomid má jen omezenou časovou platnost (např. datum dodání + 1 den) a navíc může být (narozdíl od čísla objednávky) skutečně náhodné. V případě potřeby se k němu dá přidat něco dalšího, co není snadné podvrhnout – například IP adresu. I v systému, kde se uživatelé neregistrují, tak není problém zabránit cizím lidem si číst data. Problém je ovšem v tom, že si pak ta data po čase nepřečte ani původní objednatel. To je ale daň za anonymitu.
Což takhle...
Napadá mě řešení – každá objednávka dostane ID, které je unikátní pouze pro daného uživatele – může např. existovat více objednávek č. 3.
Je to jen malinko upravené, ale pomůže to taky…
Docasna url s generovanym id
mapovanym na skutecne id v tabulce 1:1 a selecty z joinu, co?
nikdo neslyšel o ACL?
To si děláte srandu že http://www.damejidlo.cz nepoužívá nějaké ACL, ne? IMHO se bez objektového ACL větší tohoto typu aplikace neobejde. Vždyť je na to i tutoriál v Nette pro začátečníky.
Re: nikdo neslyšel o ACL?
Si robite srandu, ze sa autorizacia bez objektov neda naprogramovat?
Ale pokial je tam Nette ok :)
Nautorizovaný přistup k datům DameJidlo
Rád bych tady pod článkem ještě jednou poděkoval panu Průšovi za report chyby. Chyba byla na základě jeho podnětu opravena.
Odborný názor
„Hausnumera“ a GUID jsou jen obskurnost, která neřeší primární problém — uhodnout GUID je sice těžší než uhodnout vzestupně rostoucí ID, ale problém je jinde – v tom, že útočník na základě znalosti nějakého ID obdrží data, která obdržet nemá. Navíc je to systémové špatné řešení, protože míchá dohromady dvě věci: identifikaci objektu a autorizaci uživatele resp. řízení přístupu k obejktu. Je to asi jako kdybyste na disku schovali data do souboru, jehož název nikdo nezná (nebo si to alespoň myslíte). Chyba. Správné řešení je použít příkaz „chmod“ – jednoduché a čisté.
Vložení UID do podmínky v SQL dotazu je naopak dobrá cesta – nepotřebná data se do aplikace ani nedostanou a nelze je zneužít. Má to ale jednu nevýhodu: nelze rozlišit, zda objekt neexistuje nebo zda k němu jen uživatel nemá práva. Většinou je to v pořádku, protože ošklivému útočníkovi nepotřebujeme sdělovat, zda trefil ID objektu nebo ne. Ale někdy je to na škodu – uživatel potřebuje vědět, že nemá práva, aby si o ně mohl zažádat a nebyl zmatený/vyděšený z toho, že daný objekt neexistuje.
Používání databázových procedur však nijak nepomůže. Uložené procedury jsou sice užitečné a jsem pro jejich používání, ale tento problém neřeší – je implementační detail, jestli tohle vyřešíme na úrovni aplikace nebo databáze – zapomenout na kontrolu je možné na obou místech. Stejně je potřeba ošetřit případy, kdy data nežádá běžný uživatel, ale správce nebo systémová úloha.
Re: Odborný názor
A kam si opravdový odborník schová UID pro objednávky vytvořené ad-hoc, tedy uživatel nemá účet, když se mu Hausnumera a GUID nelíbí ?
Re: Odborný názor
Každý uživatel má účet resp. záznam v naší databázi, i když třeba nezná svoje heslo. Je zbytečné (a nebezpečné) vytvářet nějakou alternativní cestu pro přístup k datům pro neregistrované uživatele.
Re: Odborný názor
A jak se pak dostane k faktuře když nezná heslo a GUID a Hausnumera nejsou povoleny, nějak takhle ?
https://xxx.cz/faktury.php?uid=42&faktura=4242
Re: Odborný názor
To byste si měl jít někam dostudovat, když to nevíte. Ale budu tak hodný a řeknu vám to.
Uživatel bude už přihlášený (relace v prohlížeči – cookies) nebo se přihlásí pomocí jednorázového tokenu (ano, „hausnumero“), nicméně tento token slouží k přihlášení, nikoli k identifikaci objektu (např. objednávky).
Tyto dvě činnosti (přihlášení uživatele vs. identifikaci objektu) je potřeba oddělit (byť to můžou být dva parametry v témže HTTP požadavku, nicméně jsou na sobě nezávislé).
Re: Odborný názor
No já to právě vím, proto čekám co z vás vypadne a vypadlo hausnumero :-)
Problém přihlašování hausnumerem je identický jako problém zobrazování faktury přes hausnumero. Pravděpodobnost uhodnutí 32-bit id faktury + 64-bit hausnumera je +- stejná jako pravděpodobnost uhodnutí 96-bit hausnumera přímo na fakturu.
Re: Odborný názor
1) „hausnumero“ není jediná ani první možnost, o které jsem psal.
2) O uhodnutelnost tu vůbec nejde (v obou případech je potřeba použít kvalitní generátor náhodných čísel a dostatečně dlouhé číslo, aby to bylo o několik řádů výš, než co se dá „uhodnout“). O co tu jde je vnitřní složitost aplikace – přístupová práva ověřujeme jednotně (podle aktuálně přihlášeného uživatele) a nevznikají nám tu alternativní větve a dodatečná složitost způsobená tím, že bychom za určitých okolností (přítomnost hausnumera) ověřovala přístupová práva jinak. Kromě toho až příště bude potřeba povolit přístup k jiné entitě, bude se nám duplikovat kód i data. Může to být další objednávka téhož uživatele se třeba bude chtít podívat nejen na fakturu, ale i na objednávku – nakonec to dopadne tak, že datový model bude zaneřáděný a v každé tabulce bude nějaký sloupeček s „hausnumerem“ – místo abychom evidovali jen ID uživatele a tokeny měli jednoduše na jednom místě napojené na uživatele. Proto jsem psal, že je dobré oddělit autentizaci/autorizaci od identifikátorů objektů.
Re: Odborný názor
Tomu rozumím, mě celou dobu jenom zajímalo jak jste to dokázal bez hausnumer a tedy jenom jste převedl hausnumero z objednávky na usera a říkáte tomu token.
Problém s eliminací zaneřádění datového modelu řeší můj příspěvek z 23.1. 12:22, tokeny ani hausnumera vůbec není třeba do DB ukládat.
Re: Odborný názor
Použití kryptografie (v tomto případě spíš hashování než šifrování) může být elegantní (ale i zrádně nebezpečné, pokud se to udělá špatně), ale pořád to neřešít ten problém, že máme více způsobů, jak ověřit práva uživatele k objektu. Z architektonického hlediska mi to přijde špatně a zbytečná složitost – v prvním kroku bych „přihlásil“ uživatele (to může být víc způsobu – klasické jméno/heslo nebo token nebo ještě něco jiného) a v dalším kroku ověřoval práva a dělal všechny ostatní věci (už vždy stejným způsobem – jednotně – bez ohledu na to, jak se uživatel přihlásil). Další věc, na kterou jste zapomněl, je, že je dobré umět spárovat různé objekty patřící jednomu uživateli (více objednávek, více faktur, otázky odeslané přes kontaktní formulář, dotazy ve fóru atd. – vše je dobré mít propojené a evidovat tu entitu „uživatel“).
Re: Odborný názor
Zeby mel uzivatel trebas session ID co? A ze bych trebas tu session overoval pri praci s tim, co zrovna tvori, co? Nejaky IDcka v linku sou naprosto nezajimavy.
Náhodný hash
Čo je zlé na metóde kde url je v tvare: /detail-objednavky/?hash=sha1(uniqid(microtime(), true)) ?
(za predpokladu že každá objednávka má stĺpec s náhodným hashom, ktorý je unique)
Pravdepodobnosť že by niekto uhádol 40 miestny kód je velmi malá, netreba žiadne id užívateľa (len málo užívatelov si v obchode vytvorí účet).
Re: Náhodný hash
Mas poneti, jak funguje hashovani? Pak bys nenapsal takovou blbost. I sebelepsi hash je tak bezpecny, jak nahodny (velky) je jeho vstup.
Predpokladat, ze se bezpecnost zvysi, kdyz ze vstupu ‚xmvkfdkl‘ hashovanim vypocitam vystup ‚csdckliovjevjioajdsasnkjasvnjk‘ je samozrejme blbost.
Hash ma smysl jen tehdy, je-li definicni obor mnozina vetsi nez mnozina oboru hodnot hashovaci funkce. Je zrejme, ze uniqid(microtime(), true) negeneruje vetsi mnozinu nez sha1(uniqid(microtime(), true)).
Frameworky
Tady se dobře projevilo, že psát si aplikace na koleně (bez frameworku) je bezpečnostní hazard. Třeba v Drupalu je to jen o konfiguraci, všude pak hlídá, jestli uživatel má oprávnění k stahovanému souboru přistupovat.
Re: Frameworky
No ale co kdyz nejsi ten, kdo pise ty aplikace, ale ten framework?
Re: Frameworky
Tak by ten framework měl být odkázán na to, že ho bude používat na složitější aplikace jen pár šílenců (WordPress, Joomla :-)).
Žijeme ale v realitě, kde kvalita ne vždy vítězí a tak musí vycházet tyto články. :-)
Re: Frameworky
Aha, takže vy říkáte „je hazard, abych zabezpečení dělal já, je lepší se spolehnout na framwork“. Čili vy zabezpečení nerozumíte a neumíte to, tak tam radší dáte framework, protože ten to má vyřešené.
Jestli to berete takhle, tak je největší hazard, abyste na to vůbec sahal, protože slepým nabastlením frameworku lidmi, kteří tomu vůbec nerozumí, vznikají nejhorší paskvily.
Framework je dobrý sluha, ale zlý pán – pokud mu rozumíte a víte přesně, co dělá, tak je správné ho využít, protože vám ušetří práci. Pokud je ale framework chytřejší než vy, tak ho nepoužívejte, protože ho použijete špatně a výsledek bude (ne)fungovat úplně jinak než si představujete.
Re: Frameworky
Jiste, framework vyresi bezpecnost sam od sebe … lol … tohle muze psat opravdu leda mamlas. Framework vyresi proste podle vyjadrovani nekterych tady uplne vsechno … a proto mame tisice frameworkovych webu a miliony der v nich.
Re: Frameworky
DámeJídlo používá framework, konkrétně Nette. V článku přesně na toto téma jsem napsal:
Použití jakéhokoliv nástroje, ať už je to webový framework nebo bouchač z reálného světa s východním přízvukem automaticky nezaručí bezpečnost vašich webových aplikací, nezávisle na tom, co tvrdí autor daného nástroje. Nebo váš nejlepší kamarád. Nebo váš šéf. Vždy se naučte, jak daný nástroj pracuje, jaké má omezení, jaké vlastnosti a kdy je vhodné jej použít a kdy ne. Vše pečlivě otestujte a hlavně věřte pouze svému úsudku a svojí hlavě. Tedy pokud nějakou máte.
A to se vztahuje i na frameworky.
zlobivy googl
K te bezpecnosti spousta vyvojaru si verzuje sve scripty bohuzel ne uplne chytre napriklad radi pouzivaji neco.php.bak nebo cislovani, na tom by nebylo nic zleho kdyzby upravily htaccess, protoze se mi parkrat stalo ze sem na podobne stranky narazil kdyz sem neco hledal v googlu.
Googl mi takto jednou hezky ukazal zdrojovy kod jednoho eshopu. A co sem nevidel diru v sql, a ma temna strana se taktez probrala k zivotu, netrvalo dlouho a sesmolil sem asi 30znakovy text, vlozil jej do inputu pro zaslani hesla na email, a zachvyli mi server poslal vypis vsech svych uzivatelu vcetne hesel.
Re: zlobivy googl
Zdrojak v principu ale neni problem, problem je prece ta dira, a na tu by se dalo prijit i bez nej, i kdyz mozna by to trvalo, ze … ostatne, v pripade php a spol (tedy interpretovanych jazyku) s tim clovek proste musi pocitat. Nemusi to byt chyba v nastaveni, staci kdyz nekde neco z nejakeho duvodu zbuchne … a to muze dycinky.
Re: zlobivy googl
V dobe GITu a podobnych udelatek mi prijde kazdy, kdo si dela verzovaci system zpusobem file.0.1.1.bak jako blazen!
Vzdyt staci mit 2 adresare – 1 testovaci a jeden „produkcni“.
Ani to nemusite zalohovat, ale predpokladam, ze budete mit git na serveru (kvuli testovani) a u sebe na pracovni pc/ntb a mate rovnou i „zalohu“.
Re: zlobivy googl
Mít verzovací systém na serveru je jen o trošku menší bastl. Je to použitelné maximálně tak při vývoji/testování (v rámci vývoje, ne AT). Pro seriózní práci se používají balíčky, které se na server nasadí/nainstalují.
Validace || Repository
Pouzivam 2 pristupy:
1. Validuji vstupy – a to nejen, ze ID je cislo, ale i to jestli je validni pro prihlaseneho uzivatele. Je to o 1 query navic, kazdopadne z hlediska performance to nestoji temer nic. Vetsim problemem je, jak uz bylo zmineno, ze na to muze clovek zapomenout.
2. Nepouzivam primo SQL dotazy, ale dotazuji se objektu. Takze pokud chci treba objednavku ID 123 tak napisu $orders->query->where(„id = ?“, 123) s tim, ze $orders je treba OrdersForUser(‚franta‘) a metoda getQuery zajisti, ze tam bude pokazde i where(„user = ?“, „franta“). Pak se nemuze nikdy stat, ze vratim neco spatne – staci pohlidat, ze $orders je spravne skonstruovan, ale to je temer jistota, protoze se to deje jen na 1 miste v cele aplikaci.
Na čí straně je chyba a jak to vysvětlit normálním lidem
Přijde mi nesmyslné, že je trestné změnit si číslo v URL a dostat se tak k cizím datům. Pokud má někdo nést odpovědnost za to, že takto někdo neoprávněně získal data, tak by to měl být snad provozovatel aplikace / webu. Nezabezpečil totiž pořádně data jemu svěřená.
Díky tomuto článku by se snad i laická veřejnost mohla dozvědět, že ono slavné hackování není žádná magie a super extra nelegální činnost, ale že je to ve skutečnosti úplně jednoduché.
Re: Na čí straně je chyba a jak to vysvětlit normálním lidem
Je to trestné ze stejného důvodu, jako je trestné ukrást odemčené auto. To, že to jde snadno neznamená, že by to nemělo být trestné.
Re: Na čí straně je chyba a jak to vysvětlit normálním lidem
Tady je ale zcela odlišná „obvyklá praxe“. Zatímco auta nebývají volně k dispozici pro kolemjdoucí, u informací na Internetu je to naopak zcela běžné.
Re: Na čí straně je chyba a jak to vysvětlit normálním lidem
Vy opravdu nejste schopen poznat, jestli v případě DámeJídlo ta data pro vás byla nebo ne?
Re: Na čí straně je chyba a jak to vysvětlit normálním lidem
Když bych přijel na parkoviště, dal hlídačovi klíče a on mi odpověděl: „Vaše auto jsme zaparkovali na místě 133“. Já bych pak přišel a řekl: „Mám auto na místě 134 a on mi to auto dal“. A ještě bych dodal „a pak mám taky auta na místech 135, 136, 137, …“
Re: Na čí straně je chyba a jak to vysvětlit normálním lidem
Ano, i toto by bylo trestné (pro vás a nejspíš i pro toho hlídače).
chybí mi ještě 2 patra
Když chceme zajistit autorizovaný přístup k datům jen dotyčnému uživateli
1.uživatel je bezpečně autorizovaný, to tu nepadlo, chtěl bych si napsat javascript generátor jednorázových hesel, poprvé se pošlou hashe, pak se už stále pozná že jis tem, za kterého se vydáváš.
2. uživatel vidí virtuálnmí tabulky s právy SELECT a INSERT (nikoli UPDATE a DELETE)
3. má k nim systémový p
Dělám eshopy a můj framework osCommerce používá kombinace sessions_id a tokenu. Mě to zatím stačilo (když jsem zhruba ve stejné době jako autoři OSC pochopil že je třeba mít token aby se sessions nekradly) a soustředil jsem se na dvě další patra.
– zámek na úrovni řádků databáze, který tady mezi jinými okrajově zmínil Jabub Vrána
pomocí view, ve kterém se uživateli založenému pro zákazníka filtrují do virtuální tabulky jeho data), možná že Jakub Vrána to dělá chytřeji, já pro jistotu zakládám nového uživalte, která má neuhodnutelné nejen heslo ale i username, kdyby se zase v MySQL objevil podobný bug jako když bylo možné heslo známéhjo uživalele uhodnout… )
– citlivá data jsou zašifrována Vernamovou šifrou (znak po znaku je transponován náhodným řetězcem, matematicky neprolomitlené) k rozšifrování dojde po autorizaci každého požadavku zvlášť a rošifrované data jsou klienetem po přečtení smazána.
Tohle všecho mi více-méně funguje za cenu zatím obvykle nooo až několikahodinové konfigurace … trápí mně ještě problém vstupní autentizace, aby byla softwarová a dvoufaktorová, třeba skvencí jednorázových hesel…
shrnuti problemu autentizace
1.uživatel je BEZPECNE autorizovaný
2. uživatel ma prava jen k virtualnim tabulkam
3. citliva data jsou zasifrovana
ad 3. Ja jeste resim, ze fozsifrovani rozhoduje pro kazdy jednotlivy SQL dotaz samostatny crypt server jako nezavisla instance, ktera se rozhoden, jestli je pozadavek na rozsifrovani duveryhodny a nebo podvrzeny.
Takže je možné, že i vy, moji milí čtenáři, tento zákon právě porušujete.
– Nikoho tady nemusí nějakej amíckej zákon zajímat, takže to je absurdní tvrzení.