Útok clickjacking

Útok „clickjacking“ umožňuje zlé stránce kliknout na „stránku oběti“ jménem návštěvníka .

Tímto způsobem bylo napadeno mnoho stránek, včetně Twitteru, Facebooku, Paypalu a dalších stránek. Všechny byly samozřejmě opraveny.

Nápad

Myšlenka je velmi jednoduchá.

Zde je návod, jak probíhal clickjacking s Facebookem:

  1. Návštěvník je nalákán na zlou stránku. Nezáleží na tom, jak.
  2. Na stránce je neškodně vypadající odkaz (například „zbohatněte hned“ nebo „klikněte sem, velmi vtipné“).
  3. Přes tento odkaz umístí zlá stránka průhledný <iframe> s src z facebook.com, a to tak, že tlačítko „To se mi líbí“ je přímo nad tímto odkazem. Obvykle se to provádí pomocí z-index .
  4. Při pokusu o kliknutí na odkaz návštěvník ve skutečnosti klikne na tlačítko.

Ukázka

Zde je návod, jak vypadá zlá stránka. Aby to bylo jasné, <iframe> je poloprůhledný (na skutečných zlých stránkách je zcela průhledný):

<style>
iframe { /* iframe from the victim site */
 width: 400px;
 height: 100px;
 position: absolute;
 top:0; left:-20px;
 opacity: 0.5; /* in real opacity:0 */
 z-index: 1;
}
</style>

<div>Click to get rich now:</div>

<!-- The url from the victim site -->
<iframe src="/clickjacking/facebook.html"></iframe>

<button>Click here!</button>

<div>...And you're cool (I'm a cool hacker actually)!</div>

Úplná ukázka útoku:

Resultfacebook.htmlindex.html
<!DOCTYPE HTML>
<html>

<body style="margin:10px;padding:10px">

 <input type="button" onclick="alert('Like pressed on facebook.html!')" value="I LIKE IT !">

</body>

</html>
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">
</head>

<body>

 <style>
 iframe {
 width: 400px;
 height: 100px;
 position: absolute;
 top: 5px;
 left: -14px;
 opacity: 0.5;
 z-index: 1;
 }
 </style>

 <div>Click to get rich now:</div>

 <!-- The url from the victim site -->
 <iframe src="facebook.html"></iframe>

 <button>Click here!</button>

 <div>...And you're cool (I'm a cool hacker actually)!</div>

</body>
</html>

Zde máme poloprůhledný <iframe src="facebook.html"> , a v příkladu můžeme vidět, že se pohybuje nad tlačítkem. Kliknutí na tlačítko ve skutečnosti klikne na prvek iframe, ale uživatel to nevidí, protože prvek iframe je průhledný.

Výsledkem je, že pokud je návštěvník na Facebooku autorizován (obvykle je zapnuto „zapamatovat si mě“), přidá „To se mi líbí“. Na Twitteru by to bylo tlačítko „Sledovat“.

Zde je stejný příklad, ale bližší realitě, s opacity:0 pro <iframe> :

Resultfacebook.htmlindex.html
<!DOCTYPE HTML>
<html>

<body style="margin:10px;padding:10px">

 <input type="button" onclick="alert('Like pressed on facebook.html!')" value="I LIKE IT !">

</body>

</html>
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">
</head>

<body>

 <style>
 iframe {
 width: 400px;
 height: 100px;
 position: absolute;
 top: 5px;
 left: -14px;
 opacity: 0;
 z-index: 1;
 }
 </style>

 <div>Click to get rich now:</div>

 <!-- The url from the victim site -->
 <iframe src="facebook.html"></iframe>

 <button>Click here!</button>

 <div>...And you're cool (I'm a cool hacker actually)!</div>

</body>
</html>

Vše, co potřebujeme k útoku – je umístit <iframe> na zlé stránce takovým způsobem, že tlačítko je přímo nad odkazem. Takže když uživatel klikne na odkaz, skutečně klikne na tlačítko. To je obvykle proveditelné pomocí CSS.

Clickjacking je pro kliknutí, ne pro klávesnici

Útok ovlivňuje pouze akce myši (nebo podobné, jako je klepnutí na mobilu).

Přesměrování vstupu z klávesnice je velmi obtížné. Technicky vzato, pokud máme textové pole k hacknutí, můžeme umístit iframe tak, aby se textová pole navzájem překrývala. Když se tedy návštěvník pokusí zaměřit na vstup, který vidí na stránce, ve skutečnosti se zaměří na vstup uvnitř prvku iframe.

Ale pak je tu problém. Vše, co návštěvník zadá, bude skryto, protože prvek iframe není viditelný.

Lidé obvykle přestanou psát, když neuvidí, jak se na obrazovce tisknou nové znaky.

Obrana ze staré školy (slabá)

Nejstarší obranou je JavaScript, který zakazuje otevírání stránky v rámci (tzv. „framebusting“).

Vypadá to takto:

if (top != window) {
 top.location = window.location;
}

To znamená:pokud okno zjistí, že není nahoře, automaticky se stane horním.

Toto není spolehlivá obrana, protože existuje mnoho způsobů, jak kolem toho hackovat. Podívejme se na několik.

Blokování horní navigace

Můžeme zablokovat přechod způsobený změnou top.location v obslužné rutině události beforeunload.

Horní stránka (přiložená, patřící hackerovi) na ni nastavuje obslužnou rutinu zabránění, jako je tato:

window.onbeforeunload = function() {
 return false;
};

Když iframe se pokusí změnit top.location , návštěvník dostane zprávu s dotazem, zda chce odejít.

Ve většině případů by návštěvník odpověděl záporně, protože o prvku iframe neví – vidí pouze horní stránku, není důvod odcházet. Takže top.location se nezmění!

V akci:

Resultiframe.htmlindex.html
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">
</head>

<body>

 <div>Changes top.location to javascript.info</div>

 <script>
 top.location = 'https://javascript.info';
 </script>

</body>

</html>
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">

 <style>
 iframe {
 width: 400px;
 height: 100px;
 position: absolute;
 top: 0;
 left: -20px;
 opacity: 0;
 z-index: 1;
 }
 </style>

 <script>
 function attack() {

 window.onbeforeunload = function() {
 window.onbeforeunload = null;
 return "Want to leave without learning all the secrets (he-he)?";
 };

 document.body.insertAdjacentHTML('beforeend', '<iframe src="iframe.html">');
 }
 </script>
</head>

<body>

 <p>After a click on the button the visitor gets a "strange" question about whether they want to leave.</p>

 <p>Probably they would respond "No", and the iframe protection is hacked.</p>

 <button onclick="attack()">Add a "protected" iframe</button>

</body>
</html>

Atribut izolovaného prostoru

Jedna z věcí, které omezuje sandbox atributem je navigace. Iframe v izolovaném prostoru se nesmí změnit top.location .

Můžeme tedy přidat prvek iframe s sandbox="allow-scripts allow-forms" . To by uvolnilo omezení a povolilo skripty a formuláře. Ale vynecháme allow-top-navigation takže změna top.location je zakázáno.

Zde je kód:

<iframe sandbox="allow-scripts allow-forms" src="facebook.html"></iframe>

Existují i ​​jiné způsoby, jak obejít tuto jednoduchou ochranu.

Možnosti X-Frame

Záhlaví na straně serveru X-Frame-Options může povolit nebo zakázat zobrazení stránky uvnitř rámce.

Musí být odeslána přesně jako hlavička HTTP:prohlížeč ji bude ignorovat, pokud ji najde v HTML <meta> štítek. Takže <meta http-equiv="X-Frame-Options"...> nic neudělá.

Záhlaví může mít 3 hodnoty:

DENY
Nikdy nezobrazovat stránku uvnitř rámce.
SAMEORIGIN
Povolit uvnitř rámce, pokud nadřazený dokument pochází ze stejného původu.
ALLOW-FROM domain
Povolit uvnitř rámce, pokud je nadřazený dokument z dané domény.

Například Twitter používá X-Frame-Options: SAMEORIGIN .

Zde je výsledek:

<iframe src="https://twitter.com"></iframe>

V závislosti na vašem prohlížeči iframe výše je buď prázdný, nebo vás upozorňuje, že prohlížeč nepovolí navigaci této stránky tímto způsobem.

Zobrazuje se s vypnutou funkcí

X-Frame-Options hlavička má vedlejší účinek. Jiné weby nebudou moci naši stránku zobrazit v rámci, i když k tomu mají dobré důvody.

Takže existují i ​​jiná řešení... Například můžeme „zakrýt“ stránku kódem <div> se styly height: 100%; width: 100%; , takže zachytí všechna kliknutí. To <div> má být odstraněn, pokud window == top nebo když zjistíme, že ochranu nepotřebujeme.

Něco takového:

<style>
 #protector {
 height: 100%;
 width: 100%;
 position: absolute;
 left: 0;
 top: 0;
 z-index: 99999999;
 }
</style>

<div id="protector">
 <a href="/" target="_blank">Go to the site</a>
</div>

<script>
 // there will be an error if top window is from the different origin
 // but that's ok here
 if (top.document.domain == document.domain) {
 protector.remove();
 }
</script>

Demo:

Resultiframe.htmlindex.html
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">

 <style>
 #protector {
 height: 100%;
 width: 100%;
 position: absolute;
 left: 0;
 top: 0;
 z-index: 99999999;
 }
 </style>

</head>

<body>

<div id="protector">
 <a href="/" target="_blank">Go to the site</a>
</div>

<script>

 if (top.document.domain == document.domain) {
 protector.remove();
 }

</script>

 This text is always visible.

 But if the page was open inside a document from another domain, the div over it would prevent any actions.

 <button onclick="alert(1)">Click wouldn't work in that case</button>

</body>
</html>
<!doctype html>
<html>

<head>
 <meta charset="UTF-8">
</head>
<body>

 <iframe src="iframe.html"></iframe>

</body>
</html>

Atribut souboru cookie stejného webu

samesite cookie může také zabránit útokům clickjacking.

Soubor cookie s takovým atributem je odeslán na web pouze v případě, že je otevřen přímo, nikoli prostřednictvím rámce nebo jinak. Více informací v kapitole Cookies, document.cookie.

Pokud web, jako je Facebook, měl samesite atribut na jeho ověřovacím souboru cookie, například takto:

Set-Cookie: authorization=secret; samesite

…Taková cookie by se pak neodeslala, když je Facebook otevřen v iframe z jiného webu. Takže útok by selhal.

samesite Atribut cookie nebude mít vliv, pokud se soubory cookie nepoužívají. To může ostatním webům umožnit snadno zobrazovat naše veřejné, neověřené stránky v prvcích iframe.

To však může také umožnit, aby útoky clickjacking fungovaly v několika omezených případech. Webová stránka s anonymním hlasováním, která zabraňuje duplicitnímu hlasování například kontrolou IP adres, by byla stále zranitelná vůči clickjackingu, protože neověřuje uživatele pomocí souborů cookie.

Shrnutí

Clickjacking je způsob, jak „napálit“ uživatele, aby klikli na web oběti, aniž by věděli, co se děje. To je nebezpečné, pokud existují důležité akce aktivované kliknutím.

Hacker může poslat odkaz na svou zlou stránku ve zprávě nebo nalákat návštěvníky na svou stránku nějakým jiným způsobem. Existuje mnoho variant.

Z jedné perspektivy – útok „není hluboký“:vše, co hacker dělá, je zachycení jediného kliknutí. Ale z jiného úhlu pohledu, pokud hacker ví, že se po kliknutí objeví další ovládací prvek, pak může pomocí mazaných zpráv přimět uživatele, aby na ně kliknul také.

Útok je docela nebezpečný, protože když vytváříme uživatelské rozhraní, obvykle nepředpokládáme, že by hacker mohl kliknout jménem návštěvníka. Takže zranitelnosti lze nalézt na zcela neočekávaných místech.

  • Doporučuje se použít X-Frame-Options: SAMEORIGIN na stránkách (nebo celých webových stránkách), které nejsou určeny k prohlížení uvnitř rámců.
  • Použijte krycí <div> pokud chceme povolit zobrazování našich stránek v prvcích iframe, ale přesto zůstat v bezpečí.