CSRF em Server Actions do Next.js

🤩 CSRF em Server Actions do Next.js
Kapeka demonstrou um ataque CSRF contra Server Actions do Next.js. Comumente acredita-se que eles são protegidos por padrão. Não são.
Vamos examinar três fraquezas de segurança que permitem CSRF:
1⃣ Confusão de Vinculação — qualquer Server Action é acessível via um formulário
Next.js suporta dois modos para invocar funções do servidor:
Fetch Action — invocado via JavaScript com um cabeçalho personalizado next-action. Quando uma solicitação cross-domain inclui um cabeçalho personalizado, o navegador primeiro envia uma solicitação preflight para verificar permissões. CSRF é impossível neste caso.
MPA Action — invocado via um formulário HTML usando POST com multipart/form-data e sem cabeçalhos personalizados. O navegador trata isso como uma solicitação simples e a envia sem uma verificação preflight. Juntas, essas condições permitem CSRF.
A vulnerabilidade surge porque qualquer Server Action pode ser invocado de ambas as formas, incluindo o modo MPA menos seguro.
2️⃣ Contornando a verificação de Origin
Next.js compara o cabeçalho Origin da solicitação com o endereço do servidor. Se eles não corresponderem, a solicitação é bloqueada. No entanto, se o cabeçalho Origin estiver ausente ou igual a null, o framework permite a solicitação, assumindo que vem de um navegador mais antigo que não suporta o cabeçalho.
Um atacante pode obter Origin: null através de uma cadeia de redirecionamentos cross-domain. Para fazer isso, um formulário na página do atacante envia uma solicitação POST para o servidor do atacante, que então responde com um redirecionamento (especificamente com código de status 307, que preserva o método POST e o corpo da solicitação) para a aplicação da vítima.
Nesta situação, o navegador não pode determinar uma origem válida após o redirecionamento cross-domain e, portanto, define o cabeçalho Origin como null.
3️⃣ Atributo SameSite
Para que o ataque tenha sucesso, o cookie de sessão da vítima deve ser incluído em solicitações cross-site. Este comportamento depende do atributo SameSite:
  • Se SameSite=None, o cookie é sempre enviado com solicitações cross-site.
  • Se o atributo não estiver definido, o comportamento depende do navegador. Firefox e Safari enviam o cookie, enquanto o Chrome só o envia nos primeiros dois minutos após a criação do cookie.
💥 Cadeia de ataque
A vítima abre a página HTML do atacante → o formulário é enviado automaticamente → a solicitação é redirecionada através do servidor do atacante (o cabeçalho Origin torna-se null) → Next.js ignora a verificação de Origin → o framework desserializa argumentos do formulário → o Server Action é executado em nome da vítima quando os cookies de sessão estão configurados de forma insegura.
Um exemplo de um formulário CSRF é mostrado na imagem.
💬 Discutir
Produto
Chrome
Firefox
Next.Js
Safari
Server Actions
Publicado
2026-03-16, 12:03