Popis chyby, na základě které můžete na linkuj.cz hlasovat za jiné uživatele, aniž by o tom měli tušení.
Včera jsem náhodně zabloudil na Linkuj.cz a zde na první příčce uviděl MzKův článek. Nejen podle zmatených příspěvků v diskusi pod článkem jsem zjistil, že zde něco nehraje. To mi vzápětí potvrdil další MzKův článek, ve kterém ohlašuje, že na Linkuj.cz našel chybu, pomocí které lze hlasovat za jiné uživatele, aniž by o tom měli tušení. To mě nenechalo chladným a rozhodl jsem se, že se na linkuj.cz podrobně podívám. Ve večerních hodinách jsem chybu odhalil. Protože Mzk chybu stále nepopsal, rozhodl jsem se napsat tento článek.
Shodou okolností napsal nedávno o těchto chybách .cCuMiNn. výborný článek na Soom.cz. Nebudu zde tedy vysvětlovat teorii, kterou najdete dobře popsanou v jeho článku. Zmíním jen, že chyba se nazývá Cross-site request forgery a pěkně popsaná je také na wikipedii.
Nyní se vrhněme na praxi. Nejdříve si musíme vytvořit určitou stránku, článek, který na linkuj.cz zalinkujeme. Do článku můžete napsat co chcete. Důležitý je však tento kousek kódu, který do stránky vložíme:
Bude to neviditelný iframe. Jeho „neviditelnost“ zajistíme tím, že mu definujeme nulovou šířku, výšku i ohraničení. Obsah iframu se načte z odkazu, který je uvedený jako hodnota atributu src. „xxxxx“ značí číslo článku, které zjistíte, pokud na linkuj.cz najedete myší nad žlutý čtvereček obsahující počet hlasů (je to hodnota proměnné par). Sem tedy vložte číslo, které bude přiřazeno článku, pro něž mají uživatelé, aniž by o tom věděli, hlasovat.
Možná by ještě bylo dobré popsat, jak jsem zjistil adresu a proměnné skriptu zajišťujícího hlasování, když je hlasování na linkuj provádění pomocí javascriptu a hlasovací odkaz vidíte tedy pouze v tomto tvaru: javascript:add_link(xxxxx). Funkci add_link najdete zde: http://linkuj.cz/linkuj.js, ale z ní nevyčtete reálné umístění skriptu. Proto jsem pomocí FF pluginu Live HTTP Headers odchytil HTTP požadavek vyslaný vaším počítačem při hlasování. Z něho už adresu skritpu pohodlně zjistíte.
Teď si popišme, co se tedy celkově stane. Nic netušící uživatel se přijde na Linkuj.cz podívat, co nového nám sem lidé zalinkovali. Přihlásí se, aby mohl hlasovat. Pominu fakt, že do cookies se mu mimo uživatelského jména a PHPSESSID uloží i heslo v plaintextu(!). Poté uživatel uvidí váš článek se zajímavým nadpisem a popisem. Klikne na něj a tím se dostane na váš web. Zde se stáhne obsah iframu z vámi zadaného odkazu, což má stejný účinek, jako by uživatel kliknul na hlasovací odkaz na linkuj.cz. Zatímco si tedy čte váš článek, aniž by o tom věděl, hlasoval pro zalinkování tohoto článku.
Adminům Linkuj.cz bych poradil, aby do skriptu ajax.php začlenili kontrolu hodnoty referer. Jelikož odkazy i v iframu jsou na vašem webu a ne na linkuj, lze tak jednoduše odlišit, zda bylo hlasováno korektně přes webové rozhraní Linkuj.cz či zda je hlasování prováděno „nelegálně“ a takovýto hlas pak nezapočíst.
Takto bych chybu zneužil já. Verze od MzK je pravděpodobně ještě jiná, protože mi sám potvrdil, že na skript ajax.php, který se stará o započítaní hlasu ke konkrétnímu článku, nenarazil. Proto se těším na jeho verzi využití chyby na Linkuj.cz.