Internet Info, s.r.o. Lupa Root Měšec Podnikatel DigiZone Slunečnice Vitalianew Bomba Navrcholu Weblogy Jagg Woko Dobrý web Computer.cz SK: MojeLinky

Hlavní navigace

Co je Cross-Site Request Forgery a jak se mu bránit

Je vaše webová aplikace zabezpečená proti Cross-Site Request Forgery (CSRF)? V článku se dozvíte, co znamená CSRF. Vysvětlíme, proč se jedná o bezpečnostní riziko nezávisle na tom, zda vaše formuláře používají metodu GET nebo POST. A dále ukážeme způsob, jak se můžete vůči tomuto problému bránit.

V nedávném článku Přehled útoků na webové aplikace jsme vám představili seznam základních bezpečnostních problémů, se kterými se můžete setkat. Dnes se zaměříme na jeden z nich, a sice na CSRF. Pro pochopení článku budeme vyžadovat alespoň základní znalost formulářů v HTML.

Co je CSRF

CSRF je typ útoku na webovou aplikaci nebo službu. Zkratka CSRF (Cross-Site Request Forgery) znamená „podvržení požadavku mezi různými stránkami“. Někdy se také můžeme setkat i s dalšími termíny jako XSRF, Cross-Site Reference Forgery, Session Riding nebo Confused Deputy attacks.

Co CSRF není

Mnoho lidí spojuje CSRF s XSS (Cross Site Scripting). To ale není správné, protože se jedná o zcela jiné zranitelnosti. Takže ještě jednou: CSRF není XSS!

Popis útoku

Popis CSRF útoku si předvedeme na příkladu. Abychom mohli začít útočit, musíme mít na co. To je také jeden ze základních předpokladů úspěšného CSRF útoku – musíme znát aplikaci, na kterou útočíme.

Pro demonstrační použití nám poslouží fiktivní aplikace webmailu (webového rozhraní pro práci s e-mailem), konkrétně část pro odesílání e-mailu. Ta obsahuje následující formulář:

<form action="poslat" method="get">
  <input type="text" name="komu">
  <input type="text" name="predmet">
  <textarea name="obsah"></textarea>
  <input type="submit" name="Poslat email">
</form> 

Jedná se o jednoduchý formulář, kterým můžeme poslat e-mail. Bude se posílat na adresu serveru složenou ze jména serveru a hodnoty „action“ ve značce „form“ – tedy „http://webma­il/poslat“. Formulář má dále 3 políčka: komu, predmet a obsah. Pojďme na tento formulář zaútočit – poslat e-mail automaticky bez vědomí uživatele.

Využijeme toho, že formulář odesílá své položky metodou GET. Stačí vědět, že jakýkoliv obrázek na webové stránce generuje GET požadavek a jména formulářových prvků i jejich hodnoty jsou v takovém případě součástí URL. Pak si útočník může vložit na své stránce následující kód pro „zobrazení obrázku“. Jako URL obrázku ale vloží GET požadavek, který je totožný s vyplněným a odeslaným formulářem webmailu, na který útočí.

<img src="http://webmail/poslat?komu=nejakyEmail@server&predmet=test&obsah=textemailu"> 

Když si nyní zobrazíme útočníkovu stránku se „zákeřným obrázkem“, tak se odešle e-mail na adresu „nejakyEmail@ser­ver“ bez našeho vědomí. Předpokladem je, že ve chvíli, kdy zobrazujeme útočníkovu stránku, jsme zároveň do webmailu přihlášeni.

Rozšíření útoku na metodu POST

Kdyby server zpracovával jen požadavky poslané metodou POST, útočníkovi k úspěšnému útoku stačí zapnutý JavaScript v prohlížeči oběti a následující kód:

<body onload="document.forms[0].submit();">
  ...
  <form action="http://webmail/poslat" method="post">
    <input type="text" name="komu" value="nejakyEmail@server">
    <input type="text" name="predmet" value="test">
    <textarea name="obsah">obsah emailu</textarea>
  </form> 

Zpracování požadavku na straně serveru je jednou z nejdůležitějších částí aplikace. Aplikace se může rozhodnout, které požadavky přijme a které zahodí. Základním zabezpečením může být přihlášení uživatele a uchovávání informace o přihlášení (session) v cookies prohlížeče (požadavky od nepřihlášených uživatelů bude aplikace ignorovat). Další „zabezpečení“ může být ve zpracovávání požadavků na straně serveru. Například ve skriptovacím jazyce PHP je pravidlem nepoužívat proměnnou $_REQUEST (obsahuje totiž hodnoty z POST, GET i COOKIE). Dalším pravidlem je odesílat a přijímat formuláře výhradně metodou POST místo GET, protože GET požadavek lze jednoduše odeslat např. atributem „src“ v HTML značce „img“, jak jsme si již ukázali.

Další reálné hrozby CSRF

Mezi další reálné útoky může být vytvoření trvalého platebního příkazu na útočníkův bankovní účet z bankovního účtu oběti. Smyšlený formulář na smyšlenou banku může vypadat takto:

<html>
  <body onload="document.forms[0].submit();">
    <form action="http://smyslena-banka/novy-prikaz" method="post">
      <input type="text" name="ucet-prijemce" value="1231231231-3210">
      <input type="text" name="ucet-odesilatele" value="1234567890-0123">
      <input type="text" name="castka" value="1000">
      <input type="text" name="typ-prikazu" value="trvaly">
      <input type="text" name="opakovani" value="mesicni">
    </form>
  </body>
</html> 

Dalším příkladem může být sledování elektronické pošty oběti. Útočník opět musí vědět, jakou webovou aplikaci pro přístup k elektronické poště oběť používá a jak se v ní mění nastavení účtu. Připraví si tedy formulář pro přidání pravidla „automatického přeposílání všech emailů oběti na adresu útočníka“:

<html>
  <body onload="document.forms[0].submit();">
    <form action="http://smysleny-mail-server/nastaveni" method="post">
      <input type="text" name="preposilat-na" value="utocnikuv@email">
      <input type="text" name="preposilat-co" value="vse">
    </form>
  </body>
</html> 

Poslední příklad bude destruktivní. Mějme redakční systém, do kterého můžeme psát články. Jednoduchým požadavkem můžeme smazat veškeré články daného redakčního systému:

<html>
  <body onload="document.forms[0].submit();">
    <form action="http://redakcni-server/sprava-clanku" method="post">
      <input type="text" name="smazat" value="vse">
    </form>
  </body>
</html> 

Mnoho webových aplikací trpělo a stále trpí touto zranitelností. Také Google ještě nedávno trpěl CSRF zranitelností. Bylo možno změnit bez vědomí uživatele používaný jazyk na stránkách vyhledávače. Taková automatická změna jazyka do arabštiny byla docela smutná a je s podivem, že Google danou chybou poměrně dlouho trpěl. Příklad automatické změny preferovaného jazyka vyhledávače na němčinu (již nefunguje):

<img src="http://www.google.com/setprefs?hl=de"> 

Shrnutí faktů o CSRF

  • Automatický útok na webovou aplikaci je možný, pokud oběť navštíví útočníkovu stránku, která odešle předem připravený formulář (např. akce typu „smaž vše“).
  • Je jedno, zda-li se použije metoda POST či GET pro odesílání formulářů. Metoda GET je více zranitelnější, protože pro automatický útok není nutné mít zapnutý JavaScript, viz následující ukázka (automatické odeslání formuláře metodou POST naopak zapnutý JavaScript vyžaduje):

    <img src="http://redakcni-server/sprava-clanku?smazat=vse"> 
  • I když webová aplikace zpracovává požadavky pouze pro přihlášené uživatele, samotný zabezpečovací mechanismus pomocí uložené relace (session) v cookies nás neochrání. Pokud je uživatel přihlášen a zároveň navštíví útočníkovu stránku, cookies se webové aplikaci stejně odešlou. Útok totiž proběhne z prohlížeče oběti (která je přihlášena do aplikace) a odeslání formuláře směřuje do aplikace oběti (do které je oběť přihlášena).
  • Útočník musí znát webovou aplikaci. Musí připravit formulář s akcí, která se provede, až oběť navštíví útočníkovu stránku.
  • Útočník musí oběť nějak přesvědčit, aby navštívila jeho stránku. Asi nejjednodušším příkladem je e-mail s odkazem a textem: „už jsi viděl dnešní vtip na mém blogu?“

Jak se proti CSRF bránit?

Obran proti tomuto útoku bylo popsáno mnoho, ale jen některé jsou účinné.

Neúčinné obrany

Webová aplikace může kontrolovat tzv. HTTP referer, jedná se o hlavičku HTTP protokolu, kterou prohlížeč odesílá společně s požadavkem na danou stránku. Jejím obsahem je URL předchozí stránky. HTTP referer jde ale falšovat a dokonce se nemusí vůbec odesílat (nebo se může ztratit někde cestou – třeba v proxy). V takovém případě nemáme co kontrolovat.

Některé zdroje dokonce radí, aby se kontroloval User-agent řetězec. To je ale úplný nesmysl, protože CSRF útok využívá prohlížeč oběti; User-agent řetězec proto pro přihlášeného uživatele je stejný i během útoku.

Účinná obrana proti CSRF

Základní obranou je používat takzvané „podepsané“ formuláře. Podepsaným formulářem rozumíme formulář s nějakou „tajnou“ hodnotou, kterou generuje server. Vraťme se k našemu příkladu s posíláním e-mailu, do kterého takovou hodnotu přidáme:

<form action="poslat" method="get">
  <input type="text" name="komu">
  <input type="text" name="predmet">
  <textarea name="obsah"></textarea>
  <input type="hidden" name="tajna-hodnota" value="0123456789ABCDEF">
  <input type="submit" name="Poslat email">
</form> 

Serverová část aplikace při generování formuláře vygeneruje i pole s tajnou hodnotou a tu si zapamatuje. Uživatel při odeslání formuláře odesílá i tajnou hodnotu. Serverová část aplikace přijme jen takový formulář, pokud přijatá tajná hodnota odpovídá zapamatované, nedávno vygenerované hodnotě.

Pokud chceme mít tajnou hodnotu pod kontrolou na serveru, tak je nutné se rozhodnout, zda generovat pro každý formulář jinou hodnotu, nebo při přihlášení uživatele vygenerovat jen jednu hodnotu a tu používat po celou dobu platnosti uživatelské relace (session).

Trvalou tajnou hodnotu používá například webmail na Seznamu. Používá k tomu proměnnou „hashId“ odesílanou s každým formulářem. Dříve byla tato hodnota stejná i po novém přihlášení uživatele, nyní se při každém přihlášení generuje hodnota nová.

Pokud si nechceme na straně serveru žádnou tajnou hodnotu pamatovat, můžeme ji také vygenerovat na klientské straně a uložit ji do cookies. Cookies se automaticky odesílají s každým dotazem na server a klientská část aplikace pak musí připojit ke každému odesílanému dotazu na server tajnou hodnotu. Na serverové části aplikace pak stačí zkontrolovat, zda se obě hodnoty shodují. Tento typ ochrany považuji za nejjednodušší na implementaci.

Pro obranu je velmi důležité nedovolit útočníkovi tajnou hodnotu zjistit. Ten ji může zjistit například na nezabezpečené WiFi síti (data jdou jednoduše odposlechnout, např. pomocí nástroje Wireshark) nebo pokud se tajná hodnota vyskytuje v GET požadavku (GET požadavek je vidět v refereru a může být zalogován na různých serverech).

Obrana na straně uživatele

Existuje i nějaká obrana na straně uživatele? Ano, stačí, když se bude chovat „opatrně“. Např. pokud je přihlášen do banky přes webové rozhraní, nebude otevírat žádná další okna nebo záložky ve stejném prohlížeči (nebo ve stejné instanci prohlížeče), dokud se z banky neodhlásí. Pokud totiž otevře stránku obsahující CSRF útok (tedy formulář, který se automaticky odesílá) a není právě přihlášen k webové aplikaci, k žádnému útoku nemůže dojít.

Užitečné nástroje vztahující se k problematice CSRF

  • Tamper Data – jednoduché rozšíření pro Firefox, které umožňuje zobrazit a pozměnit veškeré odesílané formuláře.
  • CSRF Protector – rozšíření pro Firefox ochraňující před některými CSRF útoky.
  • Wireshark – sledování veškerého síťového provozu.

Shrnutí

V článku jsme se pokusili vysvětlit princip CSRF útoku, vyvrátit některé mýty, které okolo něj panují, a předvést způsob, jak se proti němu bránit (ať již na straně vývojáře aplikace nebo na straně uživatele). Pokud se budete držet rad uvedených v článku, neměl by pro vás (resp. pro vaše aplikace) již CSRF být problémem. Nezapomeňte ovšem, že CSRF je jen jedním z mnoha útoků, na které by měly být vaše aplikace připraveny.

Zdroje


Autorem článku je Jan Pejša, vývojář webových aplikací ve společnosti Kerio Technologies s.r.o., která je jedním z hlavních výrobců bezpečnostního internetového softwaru pro malé a středně rozsáhlé sítě, se specializací na síťové firewally a bezpečnost interní firemní komunikace.

Anketa

Je vaše webová aplikace zabezpečena proti CSRF?

       

Jan Pejša

Absolvent ZČU v Plzni. V současné době pracuje jako vývojář webových aplikací ve společnosti Kerio Technologies s.r.o..

Přehled názorů

Tajná hodnota ve formuláři nefunguje
BLEK. 24. 11. 2008 07:13
├ 
clickjacking
Martin Hassman 24. 11. 2008 07:20
│
└ 
Re: clickjacking
pepak 24. 11. 2008 07:36
│
 
└ 
Re: clickjacking
Martin Hassman 24. 11. 2008 07:51
│
 
 
└ 
Re: clickjacking
pepak 24. 11. 2008 08:06
│
 
 
 
└ 
Re: clickjacking
Martin Hassman 24. 11. 2008 08:20
│
 
 
 
 
└ 
Re: clickjacking
pepak 24. 11. 2008 10:36
│
 
 
 
 
 
└ 
Re: clickjacking
Martin Hassman 24. 11. 2008 13:50
│
 
 
 
 
 
 
└ 
Re: clickjacking
pepak 24. 11. 2008 16:27
│
 
 
 
 
 
 
 
├ 
Re: clickjacking
Martin Hassman 24. 11. 2008 16:46
│
 
 
 
 
 
 
 
└ 
Re: clickjacking
Jakub Vrána 24. 11. 2008 16:47
│
 
 
 
 
 
 
 
 
└ 
Re: clickjacking
Martin Hassman 24. 11. 2008 16:54
│
 
 
 
 
 
 
 
 
 
└ 
Re: clickjacking
pepak 24. 11. 2008 17:14
│
 
 
 
 
 
 
 
 
 
 
└ 
Re: clickjacking
Martin Hassman 24. 11. 2008 17:37
│
 
 
 
 
 
 
 
 
 
 
 
├ 
Re: clickjacking
pepak 24. 11. 2008 19:54
│
 
 
 
 
 
 
 
 
 
 
 
└ 
Re: clickjacking
pepak 24. 11. 2008 19:58
└ 
Re: Tajná hodnota ve formuláři nefunguje
pepak 24. 11. 2008 07:35
 
└ 
Re: Tajná hodnota ve formuláři nefunguje
anonymní uživatel 24. 11. 2008 19:10
 
 
└ 
Re: Tajná hodnota ve formuláři nefunguje
pepak 24. 11. 2008 20:07
 
 
 
└ 
Re: Tajná hodnota ve formuláři nefunguje
BLEK. 24. 11. 2008 21:08
 
 
 
 
└ 
Re: Tajná hodnota ve formuláři nefunguje
pepak 24. 11. 2008 22:01
 
 
 
 
 
├ 
Re: Tajná hodnota ve formuláři nefunguje
Martin Hassman 24. 11. 2008 22:53
 
 
 
 
 
│
└ 
Re: Tajná hodnota ve formuláři nefunguje
pepak 25. 11. 2008 08:18
 
 
 
 
 
└ 
Re: Tajná hodnota ve formuláři nefunguje
BLEK. 25. 11. 2008 01:57
OT: CSRF podle nového TRZ...
uživatel si přál zůstat v 24. 11. 2008 08:31
├ 
Re: OT: CSRF podle nového TRZ...
Martin Malý 24. 11. 2008 08:45
│
└ 
Re: OT: CSRF podle nového TRZ...
Pořád v anonymitě 24. 11. 2008 09:06
│
 
└ 
Re: OT: CSRF podle nového TRZ...
Martin Malý 24. 11. 2008 09:21
│
 
 
└ 
Re: OT: CSRF podle nového TRZ...
Pořád v anonymitě 24. 11. 2008 09:37
│
 
 
 
└ 
Re: OT: CSRF podle nového TRZ...
Martin Malý 24. 11. 2008 10:04
└ 
Re: OT: CSRF podle nového TRZ...
Věra Pohlová 25. 11. 2008 14:31
AJAX a cookies
Tomáš Brukner 24. 11. 2008 08:57
├ 
Re: AJAX a cookies
Martin Hassman 24. 11. 2008 09:04
│
└ 
Re: AJAX a cookies
Tomáš Brukner 24. 11. 2008 09:25
│
 
└ 
Re: AJAX a cookies
Martin Hassman 24. 11. 2008 09:31
│
 
 
├ 
Re: AJAX a cookies
Tomáš Brukner 24. 11. 2008 09:35
│
 
 
└ 
Re: AJAX a cookies
anonymní uživatel 24. 11. 2008 14:52
│
 
 
 
└ 
Re: AJAX a cookies
Jakub Vrána 24. 11. 2008 15:09
│
 
 
 
 
└ 
Re: AJAX a cookies
prispivatel45421 24. 11. 2008 18:39
│
 
 
 
 
 
└ 
Re: AJAX a cookies
Jakub Vrána 25. 11. 2008 01:39
│
 
 
 
 
 
 
└ 
Re: AJAX a cookies
anonymní uživatel 29. 11. 2008 15:04
├ 
Re: AJAX a cookies
Daniel Tlach 24. 11. 2008 13:49
│
└ 
Re: AJAX a cookies
Tomáš Brukner 24. 11. 2008 19:11
├ 
Re: AJAX a cookies
repli 24. 11. 2008 21:13
└ 
Re: AJAX a cookies
Věra Pohlová 25. 11. 2008 14:42
 
└ 
Re: AJAX a cookies
Jan Pejša 25. 11. 2008 16:34
 
 
└ 
Re: AJAX a cookies
Věra Pohlová 25. 11. 2008 16:58
 
 
 
└ 
Re: AJAX a cookies
Jan Pejša 25. 11. 2008 20:47
RE: Co je Cross-Site Request Forgery a jak se mu bránit
anonymní uživatel 24. 11. 2008 14:54
├ 
RE: Co je Cross-Site Request Forgery a jak se mu bránit
pht 24. 11. 2008 14:55
└ 
RE: Co je Cross-Site Request Forgery a jak se mu bránit
Jan Pejša 24. 11. 2008 15:25
 
└ 
RE: Co je Cross-Site Request Forgery a jak se mu bránit
pht 25. 11. 2008 10:04
 
 
├ 
RE: Co je Cross-Site Request Forgery a jak se mu bránit
Martin Hassman 25. 11. 2008 10:20
 
 
└ 
RE: Co je Cross-Site Request Forgery a jak se mu bránit
Jan Pejša 25. 11. 2008 10:33
Google
Lukáš Havrlant 24. 11. 2008 15:19
├ 
Re: Google
Jakub Vrána 24. 11. 2008 15:22
│
└ 
Re: Google
Lukáš Havrlant 24. 11. 2008 15:28
│
 
└ 
Re: Google
Jakub Vrána 24. 11. 2008 15:34
└ 
Re: Google
Jan Pejša 24. 11. 2008 16:00
drobna korektura + dalsi poznamky
anonymní uživatel 24. 11. 2008 17:05
└ 
Re: drobna korektura + dalsi poznamky
Martin Hassman 24. 11. 2008 17:13
 
└ 
Re: drobna korektura + dalsi poznamky
Jan Pejša 24. 11. 2008 21:09
TYPO (= překlep)
Miloss 24. 11. 2008 17:30
└ 
Re: TYPO (= překlep)
Martin Hassman 24. 11. 2008 17:35
Tajna hodnota v cookie
anonymní uživatel 24. 11. 2008 18:11
├ 
Re: Tajna hodnota v cookie
Martin Hassman 24. 11. 2008 18:18
├ 
Re: Tajna hodnota v cookie
Jan Pejša 24. 11. 2008 21:22
│
└ 
Re: Tajna hodnota v cookie
Věra Pohlová 26. 11. 2008 02:50
│
 
└ 
Re: Tajna hodnota v cookie
Jan Pejša 26. 11. 2008 07:26
│
 
 
└ 
Re: Tajna hodnota v cookie
Věra Pohlová 26. 11. 2008 20:51
├ 
Re: Tajna hodnota v cookie
Jan Pejša 24. 11. 2008 21:27
└ 
Re: Tajna hodnota v cookie
Věra Pohlová 26. 11. 2008 02:38
 
└ 
Re: Tajna hodnota v cookie
Mima 5. 12. 2008 09:43
Podvrzeni refereru?
Leoš Ondra 24. 11. 2008 22:23
├ 
Re: Podvrzeni refereru?
Martin Hassman 24. 11. 2008 22:52
│
└ 
Re: Podvrzeni refereru?
Leoš Ondra 24. 11. 2008 23:26
├ 
Re: Podvrzeni refereru?
Jakub Vrána 25. 11. 2008 01:49
│
├ 
Re: Podvrzeni refereru?
Martin Straka 25. 11. 2008 02:09
│
│
└ 
Re: Podvrzeni refereru?
Věra Pohlová 26. 11. 2008 02:52
│
└ 
Re: Podvrzeni refereru?Re: Podvrzeni refereru?Re: Podvrzeni refereru?
anonymní uživatel 12. 12. 2008 15:52
│
 
└ 
Re: Podvrzeni refereru?Re: Podvrzeni refereru?Re: Podvrzeni refereru?
Jakub Vrána 12. 12. 2008 16:20
└ 
Re: Podvrzeni refereru?
Věra Pohlová 26. 11. 2008 03:12
 
└ 
Re: Podvrzeni refereru?
Jakub Vrána 26. 11. 2008 11:04
 
 
└ 
Re: Podvrzeni refereru?
Věra Pohlová 26. 11. 2008 14:48
 
 
 
└ 
Re: Podvrzeni refereru?
Leoš Ondra 26. 11. 2008 22:40
 
 
 
 
└ 
Re: Podvrzeni refereru?
Věra Pohlová 28. 11. 2008 12:44
 
 
 
 
 
└ 
Re: Podvrzeni refereru?
Jakub Vrána 29. 11. 2008 04:26
 
 
 
 
 
 
└ 
Re: Podvrzeni refereru?
Věra Pohlová 1. 12. 2008 10:58
 
 
 
 
 
 
 
└ 
Re: Podvrzeni refereru?
Jakub Vrána 5. 12. 2008 12:54
 
 
 
 
 
 
 
 
└ 
Re: Podvrzeni refereru?
Věra Pohlová 5. 12. 2008 13:24
 
 
 
 
 
 
 
 
 
└ 
Re: Podvrzeni refereru?
Jakub Vrána 5. 12. 2008 13:58
A co continuation-based frameworky, např. Seaside?
nigol 26. 11. 2008 06:41
└ 
Re: A co continuation-based frameworky, např. Seaside?
Jan Pejša 26. 11. 2008 07:33
 
├ 
Re: A co continuation-based frameworky, např. Seaside?
Filip Jirsák 26. 11. 2008 09:51
 
└ 
Re: A co continuation-based frameworky, např. Seaside?
nigol 26. 11. 2008 14:57
Díky za precizní článek s výbornými příklady
karmi 3. 12. 2008 16:52
└ 
Re: Díky za precizní článek s výbornými příklady
Martin Hassman 3. 12. 2008 16:54
Ochrana v Nette
David Grudl 12. 12. 2008 16:05
       
Zasílat nově přidané příspěvky e-mailem