Proteção CSRF
Introdução
Cross-site request forgeries são um tipo de exploração maliciosa em que comandos não autorizados são executados em nome de um usuário autenticado. Felizmente, o Laravel facilita a proteção de sua aplicação contra ataques de falsificação de solicitação entre sites (CSRF).
Uma explicação da vulnerabilidade
Caso você não esteja familiarizado com as falsificações de solicitação entre sites, vamos discutir um exemplo de como essa vulnerabilidade pode ser explorada. Imagine que sua aplicação tenha uma rota /user/email
que aceita uma solicitação POST
para alterar o endereço de e-mail do usuário autenticado. Provavelmente, essa rota espera que um campo de entrada email
contenha o endereço de e-mail que o usuário gostaria de começar a usar.
Sem proteção CSRF, um site malicioso poderia criar um formulário HTML que aponta para a rota /user/email
de sua aplicação e envia o endereço de e-mail do usuário malicioso:
<form action="https://sua-aplicacao.com/user/email" method="POST">
<input type="email" value="[email protected]">
</form>
<script>
document.forms[0].submit();
</script>
Se o site malicioso enviar automaticamente o formulário quando a página for carregada, o usuário malicioso só precisa atrair um usuário desavisado de sua aplicação para visitar seu site e seu endereço de e-mail será alterado em sua aplicação.
Para prevenir essa vulnerabilidade, precisamos inspecionar cada request POST
, PUT
, PATCH
ou DELETE
recebida em busca de um valor de sessão secreto que a aplicação maliciosa não pode acessar.
Prevenindo solicitações CSRF
O Laravel gera automaticamente um "token" CSRF para cada sessão de usuário ativa. Esse token é utilizado para verificar se o usuário autenticado é a pessoa que realmente está fazendo as solicitações à aplicação. Como esse token é armazenado na sessão do usuário e muda toda vez que a sessão é renovada, uma aplicação maliciosa não pode acessá-lo.
O token CSRF da sessão atual pode ser acessado via sessão do objeto request
ou via função helper csrf_token
:
use Illuminate\Http\Request;
Route::get('/token', function (Request $request) {
$token = $request->session()->token();
$token = csrf_token();
// ...
});
Toda vez que você definir um formulário HTML "POST", "PUT", "PATCH" ou "DELETE" em sua aplicação, você deve incluir um input CSRF oculto _token
no formulário para que o middleware de proteção CSRF possa validar a solicitação. Para conveniência, você pode usar a diretiva Blade @csrf
para gerar o input de entrada de token oculto:
<form method="POST" action="/profile">
@csrf
<!-- Equivalente a... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>
O Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
middleware, que é incluído no grupo de middlewares web
por padrão, verificará automaticamente se o token na entrada da requisição corresponde ao token armazenado na sessão. Quando esses dois tokens correspondem, sabemos que o usuário autenticado é quem está iniciando a solicitação.
CSRF Tokens e SPAs
Se você está construindo uma SPA que está utilizando o Laravel como um backend de API, você deve consultar a documentação do Laravel Sanctum para obter informações sobre autenticação com sua API e proteção contra vulnerabilidades CSRF.
Excluindo URIs da proteção CSRF
Às vezes, você pode desejar excluir um conjunto de URIs da proteção CSRF. Por exemplo, se você estiver usando o Stripe para processar pagamentos e estiver utilizando seu sistema de webhook, você precisará excluir seu endpoint de webhook do Stripe da proteção CSRF, pois o Stripe não saberá qual token CSRF enviar para suas rotas.
Normalmente, você deve colocar esses tipos de rotas fora do grupo de middlewares web
que o Laravel aplica a todas as rotas no arquivo routes/web.php
. No entanto, você também pode excluir rotas específicas fornecendo suas URIs para o método validateCsrfTokens
no arquivo bootstrap/app.php
de sua aplicação:
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
]);
})
Dica
Para facilitar, o middleware CSRF é automaticamente desativado para todas as rotas ao executar testes.
X-CSRF-TOKEN
Além de verificar o token CSRF como um parâmetro POST, o middleware Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
, que é incluído no grupo de middlewares web
por padrão, também verificará o cabeçalho de solicitação X-CSRF-TOKEN
. Você poderia, por exemplo, armazenar o token em uma tag meta
HTML:
<meta name="csrf-token" content="{{ csrf_token() }}">
Em seguida, você pode instruir uma biblioteca como o jQuery a adicionar automaticamente o token a todos os cabeçalhos de solicitação. Isso fornece proteção CSRF simples e conveniente para suas aplicações baseadas em AJAX usando tecnologia JavaScript legada:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
X-XSRF-TOKEN
O Laravel armazena o token CSRF atual em um cookie criptografado XSRF-TOKEN
que é incluído em cada resposta gerada pelo framework. Você pode usar o valor do cookie para definir o cabeçalho de solicitação X-XSRF-TOKEN
.
Este cookie é enviado principalmente como uma conveniência para o desenvolvedor, pois alguns frameworks e bibliotecas JavaScript, como Angular e Axios, automaticamente colocam seu valor no cabeçalho X-XSRF-TOKEN
em solicitações de mesma origem.
Dica
Por padrão, o arquivo resources/js/bootstrap.js
inclui a biblioteca HTTP Axios, que enviará automaticamente o cabeçalho X-XSRF-TOKEN
para você.