Dnes jsem se rozhodl proklepnout tento populární programátorský portál ohledně chyby Cross-site request forgery. Chcete vědět, jak jsem dopadl?
Nejdříve jsem se přihlásil ke svému účtu, který mám na Programujte.com již delší dobu. V pravém sloupci se mi otevřela nabídka nadepsaná mým jménem. Většina záložek se týká registrací do kurzů a věcí ohledně úkolů (btw. Tyto úkoly jsou pro nováčky výborná věc). Pro případného útočníka by největší cenu měla samozřejmě záložka Nastavení. Zde můžete měnit své osobní údaje, včetně hesla. Pro změnu hesla je však potřebná znalost původního. To znamená, že i v případě, že by CSRF na Programujte.com fungovalo, útočník by heslo změnit nemohl, protože by neznal heslo původní. Ověření původního hesla při jeho změně je z hlediska bezpečnosti nutnost. Pokud je tato otázka neřešena, je zde nebezpečí, že by to mohlo dopadnout jako před rokem na slovenském portálu Blackole.sk (paradoxně zabývajícím se IT security), kdy stačil jeden klik a mohli jste zcela přijít o svůj účet.
Na změnu hesla tedy musí útočníka přejít chuť. Ze zlomyslnosti by se však mohl snažit změnit jiný údaj, nevyžadující znalost hesla, jako například jméno, email, věk, adresu,... Kritická chyba by to sice nebyla, ale uživatelům by se jistě nelíbilo, kdyby se jim některý z těchto údajů měnil bez jejich přičinění. Zkouším si tedy změnit jeden z těchto údajů a přitom zachytit odesílané informace pomocí Firefox pluginu LiveHTTPHeaders. Odesílání dat na server se realizuje pomocí POST požadavku. To znamená, že útočník údaje sice nevyčte z URL, ale má jiné možnosti, jak je zjistit. Viz například již výše zmíněný FF plugin. Prohlížím si tedy parametry a jejich hodnoty, které se odesílají na server. Mé pozornosti neunikne hned druhý parametr s názvem ridc, jehož hodnota je totožná s hodnotou variabilního symbolu, který vám je konstantně přidělen. Viz obrázek:
Navíc hned další parametr je HASH vašeho hesla. To znamená, že ke vzdálené změně těchto údajů byste potřebovali vědět jak id, tak heslo (přesneji jeho HASH) oběti, což je velmi nepravděpodobné.
Zde má tedy Programujte.com další bod. Přidělování unikátního id každému uživateli je podle mě dokonalou ochranou proti Cross-site request forgery. Útočník si nemůže zjistit konstantní URL, kterou by podstrkoval všem návštěvníkům webu, kam by umístil svůj zákeřný kód. Tímto id nejsou chráněny pouze akce vedoucí ke změně osobních údajů uživatele, ale také akce vedoucí k registraci do kurzů. Chráněno je tedy vše, co by útočník mohl vzdáleně změnit a URL pro změnu osobních údajů je navíc chráněna HASHem uživatelova hesla.
Jeden druh útoku by však stále byl možný. Představme si situaci, že útočník chce poškodit přímo konkrétního uživatele, registrovaného na Programujte.com. Nějakým způsobem získá jeho id. Se znalostí cizího id se mu otevřou dveře k záložkám ohledně kurzů a úkolů. URL pro výkon těchto akcí totiž nejsou chráněny tak jako URL pro změnu osobních údajů pomocí HASHe hesla. Vše co útočník potřebuje, je znalost id oběti. To nějakým způsobem získá. Nyní si na Programujte.cz založí svůj účet, ze kterého bude provádět útoky. Poté rekonstruuje URL vedoucí k určité HASHem nechráněné změně (například přihlášení se do kurzu), své id nahradí id oběti a odešle. Co se stane? Oběti se skutečně nastavení změní. Znovu připomínám, že tímto způsobem lze měnit jen nabídky ohledně kurzů a úkolů, protože ostatní jsou chráněné pomocí parametru URL, ve kterém se předává HASH hesla oběti. Tato chyba sice není kritická, nelze měnit heslo ani osobní údaje, ale i tak není pro uživatele příjemná. Jediná překážka pro útočníka je tedy pouze zjistit id oběti. Jako příklad uvedu URL, pomocí které lze uživatel pod daným id přihlásit do kurzu C++, aniž by o tom měl ponětí:
http://programujte.com/kurzy.php?akce=pridat&id=ID_OBETI&celkem=32&kurz%5B0%5D=0&idkurz%5B0%5D=8&kurz%5B1%5D=0&idkurz%5B1%5D=25&kurz%5B2%5D=0&idkurz%5B2%5D=21&kurz%5B3%5D=0&idkurz%5B3%5D=32&kurz%5B4%5D=1&idkurz%5B4%5D=9&kurz%5B5%5D=0&idkurz%5B5%5D=34&kurz%5B6%5D=0&idkurz%5B6%5D=18&kurz%5B7%5D=0&idkurz%5B7%5D=11&kurz%5B8%5D=0&idkurz%5B8%5D=38&kurz%5B9%5D=0&idkurz%5B9%5D=33&kurz%5B10%5D=0&idkurz%5B10%5D=41&kurz%5B11%5D=0&idkurz%5B11%5D=27&kurz%5B12%5D=0&idkurz%5B12%5D=20&kurz%5B13%5D=0&idkurz%5B13%5D=10&kurz%5B14%5D=0&idkurz%5B14%5D=31&kurz%5B15%5D=0&idkurz%5B15%5D=15&kurz%5B16%5D=0&idkurz%5B16%5D=24&kurz%5B17%5D=0&idkurz%5B17%5D=42&kurz%5B18%5D=0&idkurz%5B18%5D=43&kurz%5B19%5D=0&idkurz%5B19%5D=23&kurz%5B20%5D=0&idkurz%5B20%5D=28&kurz%5B21%5D=0&idkurz%5B21%5D=22&kurz%5B22%5D=0&idkurz%5B22%5D=39&kurz%5B23%5D=0&idkurz%5B23%5D=29&kurz%5B24%5D=0&idkurz%5B24%5D=12&kurz%5B25%5D=0&idkurz%5B25%5D=40&kurz%5B26%5D=0&idkurz%5B26%5D=36&kurz%5B27%5D=0&idkurz%5B27%5D=30&kurz%5B28%5D=0&idkurz%5B28%5D=17&kurz%5B29%5D=0&idkurz%5B29%5D=13&kurz%5B30%5D=0&idkurz%5B30%5D=35&kurz%5B31%5D=0&idkurz%5B31%5D=37
S vědomím, že tento portál o programování není plně zabezpečen, jsem se odhlásil (btw, odhlašování doprovázela chyba headers already sent, což by si také zasloužilo ošetřit) a již jsem chtěl zavřít okno Firefoxu. Všiml jsem si však ankety v levém sloupci. Všiml jsem si jí sice již dříve, ale nevěnoval jsem jí pozornost. Po zkušenostech s Blueboard anketami jsem si řekl, že vyzkouším, jak jsou na tom ankety na Programujte.com. Hlasování se posílá přes GET požadavek, čili URL odpovědi je stejně lehce čitelná jako u Blueboardu. Zkouším tedy hlasovat. Můj hlas započten. Zkouším znovu. Další hlas započten. Zkouším hlasovat zadáním konkrétní URL odpovědi, hlas započten. Překvapení. Anketa je ještě více odfláknutá než u Blueboardu. Žádná kontrola přes IP či cookie čili nulová ochrana proti vícenásobnému hlasování. Ani snad nemusím dodávat, že CSRF je na tuto anketu také použitelné. Pokud by toho však někdo hodlal zneužít, CSRF je pro tento případ zbytečně komplikované. V tomto případě by si stačilo napsat skript, který by neustále odesílal požadavek na danou URL, čímž by automaticky hlasoval. Anketa si tedy zaslouží opravu.
Neošetřená anketa však na Programujte.com není taková chyba jako neošetřená anketa u Blueboard. U portálu Programujte.com je totiž anketa pouze jednou z vychytávek (přesto by tu alespoň ta kontrola přes IP být měla), kdežto u společnosti Blueboard jsou ankety jednou z jejich služeb, proto je v zájmu dobrého jména společnosti, aby byly zabezpečeny co nejlépe.
Jaký je tedy závěr? Anketa zcela propadla, avšak ta nebyla hlavním předmětem testování. Uživatelské rozhraní znemožňuje útočnikovi vzdáleně měnit osobní údaje a heslo diky parametru s HASHem hesla. Náchylné k útoku jsou však volby k příhlášení uživatele do kurzu. Přitom k ošetření této chyby by pomohla stejná metoda jako u osobního nastavení. Curo, admin portálu, byl na tento článek upozorněn a věřím, že všechny výše jmenované chyby a nedostatky budou brzy opraveny.

Předcházející článek: (Ne)bezpečné ankety Blueboard.cz
Následující článek: Hra had v jazyce C
| egazam | ||
inac ked si pozorne preskumas tu anketu zistis ze nejde hlasovat do nekonecna, mne to islo asi 5-6 krat a potom napise ze uz si hlasoval ![]() |
||
7.8.2007 14:56:26 |
91.127.180.* |
|
| Martasko | martasko(zavinac)pobox.sk |
|
Kamil radsej nekomentuj a pis ten slubeny clanok o Azete ![]() |
||
7.8.2007 18:48:21 |
91.127.75.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
| egazam: jj, taky jsem si vsiml ze v jednom okamziku hlasovat uz dale neslo (po 6 odhlasovanich). Druhy den vsak muzete znovu 6x hlasovat. Ve spojeni s CSRF by to melo na objektivitu ankety drtivy dopad.
Martasko: Uz jsem ho smazal. Vypada to, ze se z te "uzasne" chyby na Azete trochu pomatl ![]() |
||
7.8.2007 18:52:25 |
195.47.46.* |
|
| kamil | kamik2(zavinac)azet.sk |
|
| uz sa na clanku pracuje... | ||
8.8.2007 13:36:51 |
194.73.99.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
| "h4x0r", co se neumi ani podepsat: Tak na to lze rict asi jen tak LOL. Sam jsi tady prave ted ten postup napsal, tak nevim proc ho tak moc chces udrzet v tajnosti. Na jednu stranu ses chtel pred lamama pochlubit, jak "drsne" ovladas cookie stealing a zaroven ses posranej z toho, ze ti tu chybicku opravili a ty by sis nemohl zvedat sebevedomi ctenim cizich mailu, co? Btw, nevim kde jsi vzal, ze mam nejaky team, mozna mas lepsi info nez ja, ale co ja o sobe vim, tak pracuji zasadne sam. Radim ti, vrat se k cmuchani po cizich mailech a neotravuj tady.
2all: Priste bude kazdy nepodepsany komentar bez upozorneni vymazan. |
||
12.8.2007 13:12:08 |
195.47.46.* |
|
| Orin | OrinOrin(zavinac)seznam.cz |
|
To Stoyan: Možná by to vyřešila malá podmínka a každý by musel minimálně něco do kolonky nick napsat. ![]() |
||
12.8.2007 21:04:03 |
82.100.62.* |
|
| Vasek | ||
| Ty jsi psal pro programujte ne? proč jsi přestal nebo jak to s tebou a programujte je? | ||
12.8.2007 23:15:30 |
213.211.60.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
Vasek: Byl a stale jsem redaktorem Programujte.com a to redaktorem velice pasivnim. Kdyz uz clanek, tak na Stoyan's Page
Phuck3r: Rekl bych, ze ten vypadek byl zpusobeny spise prechodem na novou verzi RS nebo to byl obycejny vypadek serveru, ja (alespon co vim) s tim nemam nic spolecneho
Orin: Jisteze stacila, ale jsem liny ji napsat ![]() |
||
12.8.2007 23:20:40 |
195.47.46.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
| Myslim, ze to spise ty by ses mel naucit cist, protoze nevim co je tak nepochopitelneho na poslednim radku tohoto komentare.
Taky sis mohl vsimnout, ze s kazdkou objevenou chybu take kontakuji poverene osoby, takze i kdyby mi kamil clanek dodal, chybu bych oznamil, nebo bych to nechal udelat jeho. Tak nebo tak, pokud by chyba byla kriticka, urcite by ji na Azetu opravili. No a pak nehrozi, ze ji budou zneuzivat lamy, ne? ![]() |
||
13.8.2007 9:54:46 |
195.47.46.* |
|
| Orin | OrinOrin(zavinac)seznam.cz |
|
| To Stoyan: No, chtěl jsi říct že se ti nechce přihlašovat na FTP server ne?
if($_POST["nick"]==""){ echo "<p>Nebyl vyplňen nick</p>";} Protože jinak Ti blahopřeji, jsi línější než Já a to je co říct.
Dva řádky... |
||
13.8.2007 12:30:31 |
82.100.62.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
Orin: Diky za praktickou ukazku, ale ja PHP minimalne na teto urovni zvladam Btw, po tom, co pan "noname", znovu napsal komentar bez nicku, jsem dnes rano tu podminku napsal, klidne muzes vyzkouset ![]() |
||
13.8.2007 12:33:26 |
195.47.46.* |
|
| Orin | OrinOrin(zavinac)seznam.cz |
|
To Stoyan: Jistě že zvládáš, jinak bys asi těžko mohl napsat tento CMS (Pokud bys nevykradl třeba MiniRS, viď MzK? ) , nechtěl jsem tě nijak urazit, jenom mne trochu překvapila lenost napsat dva řádky Nemám potřebu zkoušet, věřím ti. |
||
13.8.2007 12:50:14 |
82.100.62.* |
|
To Stoyan : Ja som sa predca podpisal , len ty nevies citat
Som ti to uz vravel , ale neveril si mi , dufam ze mi teraz uveris ... |
||
13.8.2007 13:41:23 |
84.47.88.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
WTF, zase! Asi se nekde stala chyba Zrovna odchazim, ale az prijdu, tak si me vy "bezejmennii" neprejte ![]() |
||
13.8.2007 13:42:06 |
195.47.46.* |
|
| Orin | OrinOrin(zavinac)seznam.cz |
|
Cituji: Diky za praktickou ukazku, ale ja PHP minimalne na teto urovni zvladam...
No co, malá chybka se občas vloudí... ![]() |
||
13.8.2007 13:58:09 |
82.100.62.* |
|
| Stoyan | stoyan(zavinac)tiscali.cz |
|
| Ok, takze ted uz fakt opraveno. Konecna podminka kontroly nicku vypada priblizne takto:
if(trim($_POST["nick"])==""){ echo "<p>Nebyl vyplňen nick</p>";} Dulezita je ona funkce trim, ktera odstrani prazdne znaky (ze ano pane noname )
Orin: Na toto se krasne hodi dve ceska prislovi "I mistr tesar se obcas utne" a "Kovarova kobyla chodi bosa" ![]() |
||
13.8.2007 19:50:36 |
195.47.46.* |
|
| MzK | ||
Orin: (#komentar175) Mírni se s výrazy. Zaměňuješ slovo "vykradl" se významem "mrknul se, jak se takový jednoduchý RS tvoří a lehce se inspiroval a původní přepsal, mnohonásobně vylepšil a napsal od základu znova" ![]() |
||
13.8.2007 21:55:42 |
85.132.154.* |
|
| Orin | OrinOrin(zavinac)seznam.cz |
|
MzK: je jednodušší napsat vykradl, nechtěl jsem se moc rozepisovat. Do zdrojáku ti nevidim, tak nemůžu posoudit, ale ta "inspirace" je znát. ![]() |
||
14.8.2007 11:30:37 |
82.100.62.* |
|
| anonym | drdisk(zavinac)azet.sk |
|
| No ten azet je fakt deravy ako reseto pred nedavnom na nom prebehli nejake zmeny v prehladnosti, ale nielen pre navstevnikov ale aj pre h4ck3rOv...
...poviem len tolko ze staci poslat viac ako sto chybnych mailov a azetom to riadne otrasie... To Kamil: Dakujem za clanok, ale bola to len idea, programovaciu podstatu som musel dodat ja... ![]() |
||
14.8.2007 14:00:05 |
194.73.99.* |
|
| Phuck3r | Phuck3r(zavinac)s3zn4m.cz |
|
2 Tokan: Tak to sem na tu paradu zvedavej.. ![]() |
||
15.8.2007 2:09:45 |
89.24.4.* |
|
| <> | ||
2Orin & Stoyan: nejenze je treba testovat hodnotu promene po osetreni fcí TRIM, ale také všemi funkcemi, které z textu odstraňují tagy (strip_tags); samozřejmě to neplatí u těch fcí které tagy mění na html entity. To v pripade, ze by jmeno bylo "<>"
___________stupid_test_____SMAZAT www.sg11.tk" onMouseOver="alert('timhle sem otravoval (jini to nazývajů velkým XSS hackééém) na mnoha strankach, ktere mely ochranu v nicku, zprave, ale nemeli osetrenu adresu a mail.'); |
||
24.1.2008 13:32:50 |
79.127.172.* |
|