Next.js e falhas de middleware: mecanismo de autorização ineficaz

TechubNews
REACT-0,85%

Escrito por: Rachid.A

Yewlne

01 Texto da tradução

Recentemente, decidi colaborar com Yasser Allam, que usa o nome de inzo_. Após discutirmos vários objetivos potenciais, decidimos focar no Next.js (que tem 130 mil estrelas no GitHub e mais de 9,4 milhões de downloads por semana). É um framework com o qual estou muito familiarizado e que tive uma boa experiência criativa, como comprovam os meus resultados de pesquisa anteriores. Portanto, nesta artigo, o “nós” refere-se naturalmente a nós dois.

Next.js é um framework JavaScript completo baseado em React, com recursos ricos - é o lugar ideal para uma exploração detalhada. Com fé, curiosidade e resiliência, embarcamos numa jornada para explorar os cantos pouco conhecidos, em busca dos tesouros que ali se escondem.

Pouco depois, encontramos um problema significativo no middleware. Seu impacto é amplo, todas as versões são afetadas e não são necessárias condições prévias para explorar essa vulnerabilidade - iremos demonstrar isso em detalhes em breve.

Índice

Middleware do Next.js

Ferramenta de autorização: código antigo de nível tesouro

A ordem de execução e middlewareInfo.name

Ferramenta de autorização: O que ontem se tornou poesia, hoje vale ainda mais.

/src diretório

Máxima profundidade de recursão

Exploração de vulnerabilidades

Contornar autorização/reescrever

Contornar CSP

Realizar DoS através de envenenamento de cache (O quê?)

Esclarecer

Aviso de Segurança - CVE-2025-29927

Isenção de responsabilidade

Conclusão

Middleware do Next.js

O middleware permite que você execute código antes que a solicitação seja concluída. Em seguida, você pode modificar o conteúdo da resposta com base na solicitação recebida, reescrevendo, redirecionando, modificando os cabeçalhos da solicitação ou da resposta, ou retornando diretamente a resposta (extraído da documentação do Next.js).

Como um framework completo, o Next.js possui seu próprio middleware — uma característica importante e amplamente utilizada. Seus casos de uso são diversos, sendo os mais importantes os seguintes:

Reescrita de caminho (Path rewriting)

Redirecionamentos do lado do servidor

Adicionar cabeçalhos de informação à resposta (como CSP, etc.)

O mais importante é: autenticação (Authentication) e autorização (Authorization)

Um uso comum de middleware é a autorização, que envolve proteger caminhos específicos com base em condições específicas.

Verificação de identidade e autorização: antes de conceder acesso a páginas específicas ou rotas de API, certifique-se da identidade do usuário e verifique o cookie de sessão (documentação do Next.js).

Exemplo: Quando o usuário tenta acessar /dashboard/admin, o pedido passa primeiro pelo middleware, que verifica se o cookie de sessão do usuário é válido e se ele tem as permissões necessárias. Se a validação for bem-sucedida, o middleware encaminha o pedido; caso contrário, o middleware redireciona o usuário para a página de login:

Ferramenta de autorização: código antigo de nível tesouro

Como um grande homem disse uma vez, “talk is cheap, show me the bug”, vamos evitar muitas narrativas e ir direto ao ponto; ao revisar a versão antiga do framework (v12.0.7), encontramos este trecho de código:

Quando um aplicativo Next.js usa middleware, a função runMiddleware é chamada. Além de sua função principal, a função usa o valor do cabeçalho x-middleware-subrequest e o usa para determinar se o middleware deve ser aplicado. O valor do cabeçalho é dividido em uma lista usando dois pontos (:) como separador e a lista é verificada para ver se contém um valor middlewareInfo.name. Isso significa que, se adicionarmos um cabeçalho x-middleware-subrequest com o valor correto à solicitação, o middleware – independentemente de sua finalidade – será completamente ignorado e a solicitação será encaminhada via NextResponse.next() e o caminho para o destino original será concluído sem qualquer influência do middleware. Esta cabeça e o seu valor são como uma “chave mestra” que ignora todas as regras. Neste ponto, percebemos que encontramos um problema incrível, e as últimas peças do quebra-cabeça precisam ser concluídas em seguida.

Para que a nossa “chave mestra” funcione, o seu valor deve conter middlewareInfo.name, mas qual é esse valor?

A ordem de execução e middlewareInfo.name

O valor de middlewareInfo.name é muito fácil de adivinhar, é apenas o caminho onde o middleware está localizado. Para entender isso, precisamos ter uma breve compreensão de como o middleware era configurado nas versões antigas.

Primeiro, antes da versão 12.2 — nesta versão houve uma alteração na convenção de middleware — os arquivos devem ser nomeados como _middleware.ts. Além disso, o router da app foi introduzido apenas na versão 13 do Next.js. O único router existente na época era o router de pages, portanto, esse arquivo deve ser colocado dentro da pasta pages (específico para o router).

Com essas informações, podemos inferir o caminho exato do middleware e, assim, adivinhar o valor do cabeçalho x-middleware-subrequest. Esse valor é composto apenas pelo nome do diretório (ou seja, o nome do roteador único que existia na época) e pelo nome do arquivo, seguindo a convenção de nomenclatura que começa com um sublinhado na época:

x-middleware-subrequest: pages/_middleware

Quando tentamos contornar aqueles que estão configurados para redirecionar sistematicamente as tentativas de acesso de /dashboard/team/admin para /dashboard.

Conseguimos, invadimos ⚔️

Agora podemos contornar completamente o middleware, evitando assim qualquer sistema de proteção baseado nele, sendo o mais típico a autorização, como no exemplo acima. Esta descoberta é bastante impressionante, mas há outros pontos a considerar.

A versão anterior a 12.2 permitia que as rotas aninhadas colocassem um ou mais arquivos _middleware em qualquer lugar da árvore de diretórios (começando pela pasta pages), e eles tinham uma ordem de execução, como podemos ver na captura de tela de documentos antigos recuperados do Web Archive:

Isto significa o que para a nossa exploração de vulnerabilidades?

Probabilidade = Número de níveis no caminho

Portanto, para acessar /dashboard/panel/admin (protegido por middleware), o valor de middlewareInfo.name pode ter três possibilidades, e, consequentemente, o valor de x-middleware-subrequest também pode ter três possibilidades:

páginas/_middleware

ou

páginas/dashboard/_middleware

ou

pages/dashboard/panel/_middleware

Ferramenta de autorização: O que ontem se tornou poesia, hoje vale ainda mais.

Até agora, acreditamos que apenas as versões anteriores à 13 são vulneráveis a ataques, pois o middleware foi movido no código-fonte e ainda não cobrimos todos os seus aspectos. Suspeitamos que os mantenedores já tenham notado essa vulnerabilidade e a corrigido antes das mudanças significativas na versão 13, então reportamos essa vulnerabilidade aos mantenedores do framework e continuamos nossa pesquisa.

O que nos surpreendeu foi que, dois dias após a descoberta inicial, descobrimos que todas as versões do Next.js — desde a versão 11.1.4 — apresentavam vulnerabilidades! O código não está mais na mesma localização e a lógica de exploração também mudou ligeiramente.

Como mencionado anteriormente, a partir da versão 12.2, o arquivo não contém mais sublinhados e deve ser nomeado simplesmente como middleware.ts. Além disso, ele não está mais na pasta pages (o que é conveniente para nós, uma vez que a partir da versão 13 foi introduzido o roteador de aplicativos, o que dobraria as possibilidades).

Tendo isso em mente, a carga útil para as primeiras versões a partir da versão 12.2 é muito simples:

Tendo isso em conta, o primeiro payload da versão a partir da 12.2 é muito simples:

x-middleware-subrequest: middleware

/src diretório

Ainda é necessário considerar que o Next.js oferece a possibilidade de criar o diretório /src:

(Documentação do Next.js) Como uma alternativa para ter um diretório especial app ou pages no diretório raiz do projeto, o Next.js também suporta o padrão comum de colocar o código do aplicativo no diretório src. (Documentação do Next.js)

Neste caso, o payload será:

x-middleware-subrequest: src/middleware

Assim, independentemente de quantos níveis haja no caminho, existem apenas duas possibilidades. Isso simplifica a dificuldade de exploração de vulnerabilidades nas versões relevantes.

Na versão mais recente, houve uma pequena mudança (garantimos que é a última).

Máxima profundidade de recursão

Na versão atualizada, a lógica mudou ligeiramente, veja este trecho de código:

v15.1.7

Como antes, o sistema irá recuperar o valor do cabeçalho x-middleware-subrequest e formar uma lista usando o caractere de dois-pontos como separador. Mas desta vez, a condição para o encaminhamento direto da solicitação - ou seja, ignorar as regras do middleware - é diferente:

O valor da constante depth deve ser maior ou igual ao valor da constante MAX_RECURSION_DEPTH (ou seja, 5). Durante o processo de atribuição, sempre que um valor na lista subrequests (ou seja, o valor do cabeçalho separado por :) for igual a params.name (ou seja, o caminho do middleware), a constante depth aumentará em 1. Como mencionado, aqui só existem duas possibilidades: middleware ou src/middleware.

Assim, para contornar o middleware, só precisamos adicionar os seguintes cabeçalhos/valores na solicitação:

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

ou

x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

Para que foi originalmente este código?

Este código parece ser para evitar que pedidos recursivos entrem em um loop infinito.

Exploração de vulnerabilidades

Uma vez que sabemos que você gosta desse tipo de conteúdo, aqui estão alguns casos reais do Programa de Recompensa por Bugs.

Contornar autorização/reescrever

Neste exemplo, ao tentarmos acessar /admin/login, recebemos uma resposta 404. A partir do cabeçalho da resposta, pode-se ver que o middleware executou a reescrita do caminho para evitar o acesso de usuários não autorizados ou inadequados:

mas usando nossa ferramenta de autorização:

Podemos aceder a este ponto final sem obstáculos, o middleware é completamente ignorado. Versão alvo do Next.js: 15.1.7

Contornar CSP

Desta vez, o site utiliza middleware para configurar - além de outras funcionalidades - CSP e cookies:

Vamos contorná-lo:

Target next.js versão: 15.0.3Target next.js version: 15.0.3

Nota: Preste atenção às diferenças de payload dos dois alvos, um dos quais utiliza o diretório src/ enquanto o outro não.

Realizar DoS através de envenenamento de cache (O quê?)

Sim, este exploit também pode permitir ataques DoS de envenenamento de cache. Isso claramente não é o que devemos procurar primeiro, mas se não houver caminhos sensíveis protegidos e não houver pontos de exploração mais interessantes, então certas situações podem levar a um DoS por envenenamento de cache (CPDoS):

Suponha que um site reescreva o caminho do usuário com base na localização geográfica do usuário, adicionando (/en, /fr, etc.), e não forneça páginas ou recursos no caminho raiz (/). Se contornarmos o middleware, evitaremos a reescrita e chegaremos à página raiz. Como os desenvolvedores não pretendiam que os usuários acessassem a página raiz, não forneceram a página correspondente, resultando em um 404 (ou, dependendo da configuração/tipo de reescrita, pode ser um 500).

Se o site utilizar um sistema de cache/CDN, poderá forçar o cache da resposta 404, tornando a página indisponível e afetando gravemente a disponibilidade do site.

Esclarecer

Desde a publicação do aviso de segurança, recebemos consultas de algumas pessoas que estão preocupadas com a segurança de suas aplicações e não entendem muito bem a extensão do ataque. É importante esclarecer que os elementos vulneráveis são o middleware. Se você não está usando middleware (ou pelo menos não para fins sensíveis), não há motivo para se preocupar (mas, por favor, verifique os aspectos de DoS mencionados acima), pois contornar o middleware não contorna nenhum mecanismo de segurança real.

Caso contrário, as consequências podem ser catastróficas, recomendamos que implemente rapidamente as medidas orientativas do aviso de segurança.

Aviso de Segurança - CVE-2025-29927

patch

Para o Next.js 15.x, este problema foi corrigido na 15.2.3.

Para o Next.js 14.x, este problema foi corrigido na versão 14.2.25.

Para as versões 11.1.4 a 13.5.6 do Next.js, recomendamos consultar as seguintes soluções.

Solução

Se não conseguir atualizar para uma versão segura, recomendamos que bloqueie os pedidos de utilizadores externos que contenham o cabeçalho de pedido x-middleware-subrequest de aceder à sua aplicação Next.js.

Severidade

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (Severidade: 9.1/10, Crítico)

Mais informações

No momento em que este artigo foi escrito, está claro que os aplicativos implantados no Vercel e no Netlify não são mais afetados por essa vulnerabilidade (atualização: devido ao alto número de falsos positivos, a Cloudflare ajustou a regra para entrar em vigor apenas quando o usuário a habilitar ativamente - esses falsos positivos não distinguem efetivamente entre solicitações de usuários legítimos e solicitações de invasores potenciais).

Isenção de responsabilidade

Este estudo é publicado apenas para fins educacionais, com o objetivo de ajudar os desenvolvedores a compreenderem as causas fundamentais do problema, ou para fornecer inspiração a pesquisadores / caçadores de vulnerabilidades em futuros trabalhos de pesquisa. Este artigo serve como material complementar ao aviso de segurança, oferecendo uma explicação e esclarecimento adicionais sobre a natureza da vulnerabilidade - uma vez que o aviso já divulgou o cabeçalho de solicitação que causou a vulnerabilidade (bem como as diferenças de submissão relacionadas).

Declaramos claramente que não apoiamos qualquer uso antiético deste artigo.

Conclusão

Como enfatizado neste artigo, esta vulnerabilidade já existe no código-fonte do Next.js há vários anos, mudando com a evolução dos middleware e suas versões. Qualquer software pode ter vulnerabilidades sérias, mas quando isso afeta um dos frameworks mais populares, torna-se especialmente perigoso e pode ter consequências graves para um ecossistema mais amplo. Como mencionado anteriormente, no momento da redação deste artigo, o Next.js tinha quase 10 milhões de downloads por semana. Ele é amplamente utilizado em áreas críticas, desde serviços bancários até blockchain. Quando uma vulnerabilidade afeta funcionalidades maduras nas quais os usuários confiam (como autorização e autenticação), o risco é ainda maior.

A equipe da Vercel levou alguns dias para resolver essa vulnerabilidade, mas é importante notar que, assim que perceberam o problema, a correção foi submetida e integrada em novas versões (incluindo backport) em poucas horas.

Linha do tempo :

27 de fevereiro de 2025: um relatório de vulnerabilidade foi enviado aos mantenedores (naquele momento, acreditávamos que apenas as versões 12.0.0 a 12.0.7 estavam afetadas, e isso foi anotado no relatório).

1 de março de 2025: Foi enviado o segundo e-mail, explicando que na realidade todas as versões têm vulnerabilidades, incluindo a versão estável mais recente.

5 de março de 2025: Recebida a resposta preliminar da equipe da Vercel, informando que a versão 12.x não está mais em manutenção (pode ser que ainda não tenham lido o modelo de aviso de segurança anexado no nosso segundo e-mail, não percebendo que todas as versões estão afetadas).

5 de março de 2025: Reenviar e-mail, por favor, que a equipe consulte o mais rápido possível o segundo e-mail e o modelo de aviso de segurança.

11 de março de 2025: reenviar o e-mail para confirmar se as novas informações foram adotadas.

17 de março de 2025: Recebida a resposta da equipe Vercel, confirmando que as informações relevantes foram adotadas.

18 de março de 2025: Recebido um e-mail da equipe Vercel, informando que o relatório foi aceito e o patch de correção foi concluído. Algumas horas depois, foi lançada a versão 15.2.3 que inclui a correção (e inclui a correção retroativa).

21 de março de 2025: Aviso de segurança oficialmente publicado.

No geral, o processo de busca por vulnerabilidades de dia zero é emocionante e faz o adrenalina disparar apenas no momento em que uma pista é descoberta; o restante do tempo é como uma jornada repleta de incertezas - para os curiosos, pode trazer ganhos de conhecimento; para aqueles que carecem de paciência, essa jornada parece especialmente longa. Não hesite, agir em equipe é sempre muito mais fácil do que atravessar o deserto sozinho.

Ver original
Aviso: As informações nesta página podem ser provenientes de terceiros e não representam as opiniões ou pontos de vista da Gate. O conteúdo exibido nesta página é apenas para referência e não constitui aconselhamento financeiro, de investimento ou jurídico. A Gate não garante a exatidão ou integridade das informações e não será responsável por quaisquer perdas decorrentes do uso dessas informações. Os investimentos em ativos virtuais apresentam altos riscos e estão sujeitos a uma volatilidade de preços significativa. Você pode perder todo o capital investido. Por favor, compreenda completamente os riscos envolvidos e tome decisões prudentes com base em sua própria situação financeira e tolerância ao risco. Para mais detalhes, consulte o Aviso Legal.
Comentário
0/400
Sem comentários