Falšování požadavků napříč weby

This page is a translated version of the page Cross-site request forgery and the translation is 97% complete.

Cross-site request forgery (nebo CSRF) je typ útoku, který využívá chování mezipaměti webového prohlížeče ke zneužití zranitelnosti v zabezpečení webové aplikace.

Útoky CSRF využívají k autorizaci škodlivého požadavku HTTP ověřovací údaje uložené v mezipaměti prohlížeče oběti (jako je soubor cookie nebo uživatelské jméno a heslo uložené v mezipaměti). Škodlivý požadavek HTTP lze odeslat mnoha způsoby. Dokud jsou požadavky zpracovávány webovým prohlížečem, který má v mezipaměti ověřovací pověření, lze se pokusit o útok CSRF. Příklady:

  • Odkazy obsažené v e-mailových zprávách, které oběť otevře v prohlížeči
  • Obrázkové značky vložené do e-mailů ve formátu HTML (které jsou následně zobrazeny ve webovém e-mailovém klientovi)
  • Formuláře vložené do webové stránky
  • Požadavky ve stylu AJAX vytvořené prostřednictvím JavaScriptu

Když jsou úspěšné, mohou útoky umožnit útočníkovi provádět akce na webu se stejnou úrovní oprávnění jako oběť.

Širší přehled padělků žádostí napříč weby naleznete na Stránce o padělání žádostí mezi weby na Wikipedii.

Příklad

Následující fragment kódu pomáhá demonstrovat, jak by mohlo dojít k útoku CSRF. Předpokládejme, že neexistují žádné další kontroly nebo ochrany, které by zabránily útoku.

$user = $out->getUser();
$request = $out->getRequest();
if ( $user->isAllowed( 'delete' ) && $request->wasPosted() && $request->getCheck( 'delete' ) ) {
	$this->deleteItem( $request->getText( 'delete' ) );
}

Kód umožňuje uživateli smazat položku na wiki, pokud má dostatečná oprávnění a je ověřen.

Pokud je ověřený uživatel podveden k návštěvě externí webové stránky pod kontrolou útočníka, může útočník zfalšovat požadavek a odeslat jej na wiki. Wiki obdrží požadavek, zkontroluje autentizační pověření a poté spustí zfalšovaný požadavek, jako by jej skutečně podala oběť.

Obrana MediaWiki proti útokům CSRF

Snižujeme riziko CSRF útoků v MediaWiki pomocí pseudonáhodných tokenů výzvy. Tyto tokeny jsou generovány pro každou stránku, kterou ověřený uživatel navštíví.

Při odesílání formuláře pro danou stránku musí odeslání obsahovat token. Odeslání, které nezahrnuje token, se nezdaří. Pro útočníky je obtížné tyto tokeny uhodnout nebo ukrást, což ztěžuje útoky CSRF.

Díky same origin policy v JavaScriptu útočníci nemohou snadno použít JavaScript k načtení tokenu výzvy z formuláře.

Implementace tokenů výzvy

Tokeny výzvy by měly být přidány do všech formulářů a všech rozhraní API, která mohou provádět změny (upravovat, aktualizovat, mazat, blokovat atd.). Možná se budete chtít podívat na migraci kódu na HTMLForm, který podporuje ochranu CSRF.

Formuláře HTML

Chcete-li přidat tokeny, použijte metodu getEditToken() z instance uživatele aktuální požadavek . Kód bude vypadat takto:

function showForm( $out ) {
	...
	$user = $out->getUser();
	$out->addHTML( Html::hidden( 'token', $user->getEditToken() ) );
	...
}

function submitForm() {
	...
	if ( !$user->matchEditToken( $request->getVal( 'token' ) ) ) {
		... CSRF detected - stop the request right now ...
		return;
	}
	// OK, continue submit
	...
}

Každý formulář, který provádí operaci zápisu, by měl být chráněn tímto způsobem.

API

Pokud API provádí operace zápisu, mělo by přepsat isWriteMode, aby vrátilo true, a needsToken, aby vrátilo řetězec označující správný typ tokenu (obvykle 'csrf'). Obecně platí, že mustBePosted by měl v tomto případě také vrátit hodnotu true.

Související odkazy