Já era para o NextJS... 13 NOVAS vulnerabilidades

BBetter Stack
컴퓨터/소프트웨어경제 뉴스AI/미래기술

Transcript

00:00:00Aconteceu de novo. Este é o meu terceiro vídeo sobre CVEs de Server Components este ano e eu nem
00:00:05acho que cobri todos eles. Desta vez são 13 CVEs, sim, 13 deles, entre React
00:00:11e Next.js, 6 dos quais são de alta gravidade e incluem negação de serviço, bypass de middleware,
00:00:15cross-site scripting e muito mais. Talvez os Server Components tenham sido um erro.
00:00:20Então, aqui está a nota de segurança do Next.js, sabe, apenas corrigindo alguns problemas casuais aqui
00:00:28que eles tiveram este mês e, lá no final, obviamente, a resolução é atualizar
00:00:32todas as suas versões do Next.js e estas são as versões impactadas. Vale notar que
00:00:36o TanStack não é impactado por isso, o que — posso ser tendencioso — mas é outro motivo para eu usar
00:00:41o TanStack. Agora, não passarei por todos estes, pois provavelmente ficaríamos aqui por um bom tempo
00:00:44e também não encontrei exploits funcionais para todos, mas quero mostrar um
00:00:48de cada categoria e começaremos com um bypass de middleware e proxy, e o que eu
00:00:52consegui recriar é este do Pages Router. Então temos um bypass de proxy de middleware no
00:00:56Pages Router se você estiver usando i18n, e você pode ver que este é um CVE com uma gravidade
00:01:02de 7.5 de 10. Este é um exemplo de uma aplicação vulnerável, então no Next.js config eu
00:01:06ativei o i18n e também configurei dois locais, inglês e francês, e também tenho um arquivo de middleware
00:01:12que foi renomeado para “proxy” em versões posteriores do Next.js para tentar evitar
00:01:16a confusão que estou prestes a mostrar, mas essencialmente o que o middleware deve nos permitir
00:01:19fazer é modificar uma requisição de entrada, seja redirecionando, reescrevendo ou adicionando
00:01:24alguns headers ou algo do tipo. No meu caso, estou usando para que, se tentarem visitar a
00:01:28página /secret, ele verifique se têm um cookie de sessão, ou seja, se estão logados, e se
00:01:32não estiverem, deve redirecioná-los para a página de login, para que apenas usuários autorizados vejam
00:01:37minha página secreta. Na parte inferior também temos um “matcher” para que qualquer middleware que
00:01:41estamos aplicando a essa página secreta também corresponda às variantes de local, porque tecnicamente
00:01:45agora, como temos dois locais, temos três versões desta URL. Na própria página secreta,
00:01:50eu também tenho algumas server-side props; estas devem ser buscadas no servidor em tempo de renderização
00:01:54e, novamente, como configuramos o middleware, teoricamente apenas um usuário logado deveria ser capaz de ver
00:01:58quais são esses valores, que eu uso mais tarde na própria página, como um e-mail, uma flag e
00:02:03também uma manchete. Repetindo, apenas um usuário autorizado deve poder ver isso. Vamos colocar isso
00:02:07à prova então, e a primeira coisa que tentarei fazer é acessar essa página secreta e você
00:02:11vê que sou redirecionado para o login, já que não estou logado, o que significa que nosso middleware está funcionando,
00:02:16mas e se nos tornássemos hackers mestres? Bem, poderíamos fazer isso primeiro inspecionando o elemento,
00:02:20coisa de hacker absolutamente louca, e então aqui embaixo, no script next data, precisamos procurar
00:02:24pelo nosso build ID; no meu caso é este aqui, e podemos ir em frente e copiá-lo,
00:02:28então precisamos digitar uma URL que é underscore next barra data barra o build ID que
00:02:32acabamos de copiar e então a página que estamos tentando acessar ponto JSON. Feito isso,
00:02:37você pode ver que recebemos de volta aquelas props que deveriam estar protegidas pelo middleware,
00:02:40que no meu caso eram uma flag, e-mail, manchete e também algo dizendo para você se inscrever para
00:02:44mais notícias de desenvolvedores, tutoriais, dicas e truques. Então faça isso. Espero ter
00:02:48impressionado você com minhas habilidades loucas de hacker, mas por que isso realmente acontece? Bem, este é
00:02:52tão fácil de explicar quanto foi de fazer: tínhamos nossa página secreta e algumas server side props,
00:02:56no Next.js as server side props são servidas de uma URL parecida com esta, mas nosso middleware
00:03:00deveria estar protegendo essa rota. O problema é que, como estávamos usando i18n, também
00:03:05tínhamos outras duas URLs, que eram as variantes em inglês e francês; você pode ver que as
00:03:09server side props também ganham variantes em inglês e francês, e o Next.js tinha um código
00:03:13defeituoso que significava que, se tivéssemos o i18n ativado, ele não protegia o caso base, então este
00:03:18não estava incluído no matcher, mas os outros dois estavam, as versões em inglês e francês estavam
00:03:22protegidas, mas não o caso base de barra secret. Podemos ver isso rapidinho se eu apenas mudar
00:03:26esta URL para a versão em inglês: eu sou redirecionado para a página de login. Uma vulnerabilidade incrivelmente simples,
00:03:31mas serei honesto com você: esses bypasses de middleware costumam parecer muito piores do que
00:03:35realmente são; não são ótimos, mas você não deveria proteger muita coisa apenas com middleware de qualquer forma,
00:03:40e o Next.js nem recomenda que você faça isso. Se você tivesse dados sensíveis
00:03:44nessas server side props e não tivesse nenhum tipo de lógica de autenticação no servidor, bem, sinto que parte
00:03:48do problema é sua também; então vamos passar para um mais prejudicial, que é negação de
00:03:53serviço. Houve três destes, mas só houve um que eu consegui recriar de forma confiável,
00:03:56que foi este aqui: negação de serviço com Server Components, e isso impacta o Next.js
00:04:01assim como qualquer coisa usando o pacote react-server-dom, que é basicamente apenas o Next.js
00:04:05e os outros frameworks que o copiaram como o Vinxt e alguns outros forks. O TanStack
00:04:10Start não usa isso, então não é vulnerável. Você pode ver que este também tem uma gravidade
00:04:14de 7.5 de 10. Com este, tudo o que você precisa é de uma aplicação Next.js muito simples e,
00:04:18nela, você precisa estar usando uma Server Action, mas, novamente, pode ser uma bem simples. Este é
00:04:22o site funcionando e você pode ver que, quando eu atualizo a página, o carregamento é
00:04:25quase instantâneo e, para colocar alguns números reais nisso, se eu enviar esta requisição,
00:04:29você vê que ela resolve em 0.02 segundos, mas se eu agora executar meu exploit e então
00:04:34enviar aquela requisição novamente, desta vez levou seis segundos, e isso foi eu executando o exploit
00:04:39uma vez, então imagine o que aconteceria se eu o encadeasse. Agora, para entender este exploit, precisamos
00:04:42saber um pouco sobre o protocolo React Flight, que é o formato que o React usa
00:04:46para serializar árvores de componentes e dados entre o servidor e o cliente. Você provavelmente
00:04:50já viu isso antes: nesta página tínhamos um formulário que tinha uma Server Action. Se eu for
00:04:54até a aba Network aqui e clicar em enviar, você verá que o payload é enviado como
00:04:58dados que parecem bobagem e o mesmo acontece com a resposta aqui. Se formos lá e copiarmos
00:05:02este payload, posso explicar o que acontece quando ele é enviado ao servidor. O primeiro
00:05:05passo é a desserialização e ela começará no chunk 0 onde temos este $k1. Este $k1
00:05:10é na verdade apenas um ponteiro dizendo que haverá alguns dados de formulário aqui
00:05:16que começam com um underscore, então ele pegará todas as outras chaves que enviamos
00:05:20como parte desse payload, passará por todas elas e procurará por uma string que comece com
00:05:24um underscore e saberá que esta será a chave e que este é o valor. Então, assim que
00:05:28terminar, ele pode dizer que temos name, email, message e simplesmente transformará esses dados
00:05:32neste objeto que temos aqui embaixo. Simples e prático. O problema com essa abordagem, porém,
00:05:36é o que acontece quando a escalamos. Digamos que eu adicione outro ponteiro, desta vez procurando por $k2,
00:05:41isso vai procurar por todas as chaves que começam com dois underscores. O problema
00:05:44é que agora, quando estivermos em $k1, ele passará por todas essas seis procurando pelas
00:05:48que começam com um underscore e, quando for para $k2, fará exatamente a mesma
00:05:52coisa, mas procurando as que começam com dois underscores. Então agora estamos passando por 12
00:05:56chaves no total. Bem, isso não é tão ruim, mas vamos levar ao extremo. Se adicionarmos 199.999
00:06:03chaves aleatórias ao payload que estamos enviando e então mudarmos nosso array no zero aqui
00:06:07para ir de $k1, $k2 até $k1000, isso significa que ele terá que procurar por um underscore,
00:06:12dois underscores, três underscores, até mil underscores em todas as nossas 200.000
00:06:17chaves que temos no payload, e isso significa que, no total, ele fará 200 milhões de comparações
00:06:21de strings. Como você pode imaginar, isso vai bloquear a thread por alguns bons segundos.
00:06:25Este é o commit que acredito ter corrigido o problema que estávamos tendo. Você pode ver que
00:06:28há muita coisa acontecendo neste commit e, para ser sincero, é um pouco complexo, mas tentarei
00:06:33explicar da melhor forma. Essencialmente, agora eles usam um sistema baseado em cursor para as chaves,
00:06:36então carregam todas essas 200.000 chaves que enviamos no payload em uma lista e então
00:06:41começamos no zero aqui, onde ele procura pela referência $k1 e começa a descer
00:06:45por essa lista com um cursor que não pode voltar atrás. Ele desce aqui até $j1 e vê que não
00:06:50corresponde ao underscore que precisamos, então vai para $j2, que também não corresponde a um underscore,
00:06:54e continua por toda a lista de chaves até $j199.999. Assim que chega
00:07:01aqui, percebe que não há correspondência para $k1, então passa para $k2. Agora o $k2 começa a procurar
00:07:06por dois underscores, mas o problema é que, como este é um sistema baseado em cursor e este cursor
00:07:09não pode voltar, ele termina imediatamente no fim da lista; então isso também será
00:07:14undefined, e isso continua até $k1000. Desta vez, só passamos por
00:07:18200.000 chaves. Essencialmente, esta correção reduziu o número de operações de
00:07:23$k*n, onde $k é o número de referências $k e $n é o número de chaves, para apenas
00:07:27$n+k. No nosso caso, passamos de 200.000.000 de operações para 201.000, já que
00:07:33ele ainda precisa percorrer todas as chaves e também as referências $k. Eu acho que
00:07:37este tweet do Prime realmente resume a situação em que estamos. Criar seu próprio protocolo com serialização
00:07:41é incrivelmente difícil, então não surpreende que estejamos vendo tantos problemas. Na minha opinião,
00:07:46eles precisam pedir para o Claude Mythos dar uma revisada na base de código do React e do Next.js. A seguir,
00:07:50temos o CV de maior gravidade de todos, que é Server-Side Request Forgery em
00:07:54aplicações Next.js. Você pode ver que este é classificado como 8.6 de 10, mas também vale
00:07:59notar que este não impactou implantações hospedadas na Vercel, apenas auto-hospedadas ou outros provedores.
00:08:04Este exploit também é super simples de aproveitar. Primeiro, precisamos lançar nosso servidor Next.js
00:08:09e, novamente, pode ser uma aplicação Next.js padrão. Você não precisa fazer modificações.
00:08:14Em seguida, também vamos querer um servidor interno. Digamos que este servidor só possa ser acessado pelo
00:08:18servidor Next.js e não pelo mundo exterior. Digamos que ele esteja em nossa nuvem.
00:08:23O que faremos é simplesmente enviar uma requisição curl muito simples para nossa
00:08:26aplicação Next.js. Ela estava na porta 3002 e dizemos que queremos que nosso
00:08:31alvo da requisição seja o servidor ao qual queremos acesso naquela URL de localhost. Se eu agora der
00:08:36enter, veja o que retorna. É na verdade a página HTML de um servidor Python,
00:08:40que tem apenas aquela listagem básica de diretórios, e se eu voltar ao próprio servidor Python,
00:08:45você pode ver que ele teve uma requisição de entrada que veio da aplicação Next.js.
00:08:49Para visualizar melhor o que fizemos, digamos que nesta linha pontilhada está nossa implantação do Next.js,
00:08:53então temos nosso servidor Next.js e também alguns serviços internos, seja Redis,
00:08:57um banco de dados ou qualquer outro serviço, e este aqui você não quer que tenha acesso ao público,
00:09:02para que ninguém possa enviar um curl para ele; ele simplesmente falhará, está protegido por firewall e isolado
00:09:06e só pode ser acessado pelo servidor Next.js. O que fizemos foi simplesmente enviar
00:09:10uma requisição curl para o servidor Next.js e dissemos: “Ei, você pode enviar uma requisição em nosso nome
00:09:15para o serviço interno?” e recebemos a informação de volta; então contornamos o firewall
00:09:19passando pelo Next.js, que tem acesso ao serviço interno. A causa raiz
00:09:23disso também é bem simples: basicamente, no nosso curl enviamos um header de upgrade websocket,
00:09:28e quando enviamos esses headers, o que acontece no Next.js é que chegamos a este trecho
00:09:32de código, e isso resolve as rotas em nossa URL, mas a URL processada que sai aqui é
00:09:37na verdade o alvo da requisição que enviamos em nosso curl, então este será o
00:09:40alvo que estamos tentando alcançar no servidor interno e não a aplicação Next.js.
00:09:45O que acontece com essa URL processada é que ela passa por uma verificação aqui embaixo para dizer: “A
00:09:49URL processada tem um protocolo?” Mas neste caso é sim, já que usamos HTTP e isso é um protocolo,
00:09:55então ele prossegue e faz o proxy dessa requisição para nós. A correção para isso apenas adiciona duas novas
00:09:58guardas em nossa função resolve routes; agora estamos recebendo um booleano de conclusão,
00:10:02bem como um código de status. O que essa função resolve routes realmente faz é
00:10:06pegar nossa URL e processar se é uma requisição de proxy legítima baseada em nossos Next.js
00:10:11rewrites, middleware e coisas do tipo; se não for, significa que o valor de “finished” será
00:10:15falso, então aqui embaixo temos uma verificação: se “finished” for verdadeiro, podemos seguir para o próximo passo; se
00:10:20não for, é definido como falso, então isso não rodará, o que significa que não faremos nossa requisição de proxy
00:10:24e, no caso da requisição curl que tínhamos anteriormente, é exatamente o que vai
00:10:27acontecer: “finished” será falso. Agora, se por algum motivo “finished” fosse verdadeiro, nossa
00:10:32próxima verificação é o código de status; quando resolve routes roda, recebemos um código de status de volta se a
00:10:36solicitação HTTP, então será 200, 404, algo assim; então, se houver um código de
00:10:41isso significa que não é uma requisição de proxy web socket válida, então ele simplesmente ignorará
00:10:45esta linha e não a executará. Tentei realmente mergulhar fundo nessas questões neste vídeo,
00:10:49então me deixe saber se você ainda está assistindo comentando algo aleatório, não sei, como
00:10:53“bar” ou algo assim, e também se inscreva se você gosta do conteúdo. Temos mais duas
00:10:58categorias para passar, mas estas devem ser um pouco mais rápidas, e começarei
00:11:01com envenenamento de cache, onde consegui recriar este problema moderado aqui e veja que este
00:11:04é envenenamento de cache em React Server Component e está classificado como 5.4 de 10. Para recriar
00:11:09este, tenho uma aplicação Next.js, mas também tenho uma CDN falsa para agir como se estivesse
00:11:14em um ambiente real de implantação. Isso significa que, se eu visitar meu site pela primeira vez na
00:11:18URL da CDN e clicar em navegar pelos produtos e voltar e clicar de novo, a primeira vez
00:11:23deve ser um cache miss e na próxima um cache hit. Podemos ver isso acontecendo nos logs
00:11:27aqui: primeiro tivemos um miss em /products com uma query string e depois foi um
00:11:31hit. O que fiz a seguir, porém, foi limpar o cache para simular que talvez o cache tenha expirado
00:11:35ou algo assim, e agora posso enviar esta requisição curl. Com isso de volta na minha aplicação,
00:11:39se eu clicar em navegar pelos produtos agora, verá que recebemos um monte de gíria tecnológica, então
00:11:44fizemos com sucesso um ataque de envenenamento de cache. O que acredito estar acontecendo aqui é que, quando enviamos nosso
00:11:47curl com um header de React Server Components sendo um, esta URL retornará seus dados de
00:11:52Server Component em vez de HTML. Então, quando isso precisa ser cacheado, o Next passará por
00:11:58uma função que verifica se são dados de Server Component ou não. Se forem dados de Server Component,
00:12:02serão armazenados no cache como tal, e se não forem, serão armazenados como HTML. Isso significa que,
00:12:07teoricamente, quando o usuário tenta buscar a versão HTML da página — apenas
00:12:11clicando no botão — ela nunca deveria retornar dados de Server Component. O problema é que, no
00:12:16nosso caso, como tínhamos essa query string no final do nosso curl de Server Component,
00:12:20ela não atendeu aos requisitos para verificar se era um Server Component ou não, já que
00:12:24isso simplesmente verifica se termina em .rsc, mas a nossa versão termina na query string; então
00:12:29agora ele acha que é HTML, armazena no cache como HTML, e da próxima vez que um usuário clicar
00:12:33no botão, ele recebe os dados do Server Component porque o sistema acreditou que
00:12:37aquilo era HTML. A correção para este foi incrivelmente simples: quando fazem a verificação se
00:12:41termina em .rsc, eles simplesmente ignoram as query strings agora. Passando agora para nossa
00:12:46última categoria de CVEs, temos alguns de cross site scripting; este é o que consegui uma recriação,
00:12:50você pode ver que é um 6.1 de 10 e tem cross site scripting em scripts “before interactive”
00:12:55com entrada não confiável. Basicamente, tudo o que isso significa é que no Next.js, se eu tiver uma tag de
00:12:59script que tenha a estratégia de “before interactive”, se eu tiver outro atributo nela que
00:13:03precise de algum tipo de conteúdo não confiável — por exemplo, este vem dos search params —
00:13:08eu posso fazer cross site scripting. Posso fazer isso fazendo o usuário clicar em um link como
00:13:12este, por exemplo, onde incorporei um monte de conteúdo naquele search param; se alguém
00:13:16clicasse naquele link, isso é o que veria: eles poderiam pensar que precisam
00:13:19logar no site novamente e, quando clicarem em entrar, veja aqui que era um formulário de login
00:13:22inteiramente falso injetado via aquele search param; essencialmente permite ao atacante
00:13:26executar JavaScript na máquina da vítima; acho que um exemplo mais realista
00:13:31seria roubar os cookies de sessão do Chrome para logar em tudo o que você tivesse acesso;
00:13:34este é um exemplo bem simples de escape incorreto e podemos ver isso mais fácil com
00:13:39esta versão simplificada, mas tudo o que estou fazendo naquele search param é primeiro fechar uma
00:13:43tag de script, depois abrir uma nova tag de script com o que eu quiser rodar nela; quando damos
00:13:47enter, veja que recebo aquele alerta que diz “pwned”. Como mostrei com meu app,
00:13:51a maneira como este funciona é: precisamos de uma tag script do Next.js com estratégia “before interactive”
00:13:55e também algum atributo nessa tag script que receba seus dados de alguma fonte
00:13:59não confiável; no meu caso, isso vem dos parâmetros de busca. O que isso faz no Next.js é que esta
00:14:04tag script é transformada em algo como isto, onde temos um “dangerouslySetInnerHTML” —
00:14:08já está no nome que vai ser perigoso — e também temos um JSON.stringify.
00:14:12O importante de saber sobre o JSON stringify é que ele não escapa caracteres HTML,
00:14:17como colchetes de fechamento; então o que está acontecendo aqui é que pegamos todas as tags script
00:14:21que configuramos no Next.js, ele procura pela fonte que será definida aqui e
00:14:24então o resto das props conterá o ID de rastreamento de dados, bem como o valor que
00:14:29definimos em nosso parâmetro de busca; isso é colocado no JSON stringify. Bem, o que isso
00:14:33realmente renderiza na página é algo assim: temos nosso ID de rastreamento de dados, que
00:14:37era o resto das props, mas também temos a string que inserimos via parâmetros de
00:14:41busca; então, se expandirmos como isso realmente fica na página, parece algo
00:14:45assim: temos nossa tag script, temos um ID de rastreamento de dados, mas logo depois
00:14:49temos uma tag de script de fechamento; então encerra o script que o Next.js estava tentando fazer e, depois
00:14:53disso, podemos rodar qualquer script que quisermos na página. Também temos este pedacinho
00:14:58no final aqui porque, se não tivéssemos, o analytics seria renderizado na
00:15:01página como texto, já que o HTML veria isso como texto; isso essencialmente apenas
00:15:05engole isso, para que não haja sinais claros de que algo ruim está acontecendo na página. E pronto,
00:15:09são 13 CVEs para o Next.js e React esta semana, vimos como alguns deles funcionam e, honestamente,
00:15:14não sei o que pensar sobre isso. Eu detesto isso, e digo isso como alguém que, há uns
00:15:18dois anos, fazia todo projeto em Next.js e achava que era o melhor e o
00:15:22futuro; mas parece ser um obstáculo atrás do outro. Sinto que eles se apressaram em
00:15:26algumas coisas e depois tiveram que consertar. Pessoalmente, agora estou totalmente focado em TanStack e também
00:15:31Astro quando preciso de um site baseado em conteúdo; eles me parecem muito mais simples e, para ser sincero,
00:15:35também tenho gostado muito do que a Cloudflare tem feito ultimamente, então estou migrando lentamente
00:15:39meus projetos para lá, mas ainda tenho cerca de 20 deles na Vercel e preciso ir
00:15:43atualizar. O que você acha? Os Server Components serão úteis algum dia ou tentamos e falhamos?
00:15:48Deixe-me saber nos comentários abaixo, inscreva-se e, como sempre, vejo você
00:15:51no próximo.

Key Takeaway

A complexidade da arquitetura de Server Components introduziu 13 vulnerabilidades graves no Next.js, exigindo atualização imediata para versões corrigidas e revisão de protocolos de serialização customizados.

Highlights

  • Treze novas vulnerabilidades de segurança atingiram o React e o Next.js, sendo seis classificadas como de alta gravidade.

  • Uma falha no roteamento de i18n permite ignorar middlewares de autenticação acessando diretamente a rota de dados JSON em /_next/data/.

  • O protocolo React Flight é vulnerável a ataques de negação de serviço (DoS) que aumentam o tempo de resposta de 0.02 para 6 segundos via sobrecarga de chaves.

  • A vulnerabilidade de Server-Side Request Forgery (SSRF) com nota 8.6 permite que atacantes acessem serviços internos protegidos por firewall através do servidor Next.js.

  • O envenenamento de cache em Server Components ocorre quando o sistema confunde dados RSC com HTML devido à manipulação de query strings na URL.

  • Scripts com a estratégia 'before-interactive' permitem a execução de Cross-Site Scripting (XSS) através de parâmetros de busca não sanitizados.

Timeline

Vulnerabilidades em larga escala no ecossistema React

  • O Next.js e o React enfrentam 13 novas CVEs simultâneas.
  • Seis dessas falhas possuem alta gravidade, incluindo bypass de middleware e SSRF.
  • A resolução definitiva para todos os problemas listados é a atualização imediata das versões do framework.

Este ciclo de atualizações marca a terceira grande leva de correções para Server Components em um curto período. As falhas impactam diversas funcionalidades principais, desde a negação de serviço até a execução de scripts maliciosos. Frameworks alternativos que não utilizam a mesma implementação de serialização do React permanecem imunes a estes problemas específicos.

Bypass de Middleware e Proxy no Pages Router

  • O uso de i18n no Pages Router cria rotas desprotegidas por falha no matcher do middleware.
  • Dados sensíveis em getServerSideProps ficam expostos através da URL de dados do Next.js.
  • A vulnerabilidade possui uma pontuação de gravidade de 7.5 em 10.

Ao ativar o suporte a múltiplos idiomas, o Next.js falha em proteger a rota base de dados JSON quando variantes de localidade estão configuradas. Atacantes utilizam o Build ID da aplicação para construir URLs em /_next/data/ e extrair props de páginas que deveriam exigir autenticação. A recomendação de segurança é nunca confiar exclusivamente em middlewares para a proteção de dados sensíveis no servidor.

Negação de Serviço via protocolo React Flight

  • A desserialização de payloads em Server Actions permite ataques de negação de serviço (DoS).
  • O envio de 200.000 chaves em um único payload bloqueia a thread do servidor por vários segundos.
  • A correção substitui a busca exaustiva por um sistema de cursor que reduz drasticamente o número de comparações de strings.

O problema reside na forma como o servidor processa referências de chaves dentro de objetos serializados, resultando em até 200 milhões de comparações custosas. Um único ataque bem estruturado pode elevar o tempo de processamento de milissegundos para segundos, escalando rapidamente para a indisponibilidade total. A nova implementação limita as operações a uma única passagem pelas chaves enviadas, impedindo a recursividade maliciosa.

Server-Side Request Forgery e acesso a redes internas

  • O cabeçalho de upgrade de WebSocket permite redirecionar requisições para serviços internos.
  • A falha 8.6 SSRF ignora firewalls e expõe bancos de dados ou instâncias Redis locais.
  • Implementações auto-hospedadas são as mais vulneráveis a este tipo de ataque via comando curl.

Atacantes enviam requisições manipuladas que forçam o servidor Next.js a atuar como um proxy para a rede interna. O código vulnerável processa a URL de destino antes de validar se a rota pertence à aplicação legítima. A correção introduz guardas na função de resolução de rotas que verificam o status da requisição e impedem o proxy de protocolos não autorizados.

Envenenamento de cache em Server Components

  • Manipulação de query strings engana CDNs para armazenar dados RSC como se fossem HTML.
  • Usuários comuns recebem payloads de texto técnico em vez da interface visual renderizada.
  • A vulnerabilidade é classificada com gravidade moderada de 5.4.

O sistema de cache verificava apenas se o final da URL continha a extensão .rsc para diferenciar conteúdos. Ao adicionar parâmetros de busca após a extensão, o atacante força o armazenamento de dados brutos do servidor no cache de páginas públicas. Isso resulta na exibição de dados de sistema para usuários finais que tentam acessar a página normalmente.

Cross-Site Scripting em scripts Before Interactive

  • A falha de escape em JSON.stringify permite a injeção de tags de fechamento de script.
  • Atacantes podem roubar cookies de sessão ou injetar formulários de login falsos.
  • O erro ocorre especificamente em tags de script que utilizam fontes de dados não confiáveis.

O componente de script do Next.js não escapa caracteres HTML adequadamente ao processar propriedades adicionais. Isso permite que um atacante insira uma tag de fechamento dentro de um parâmetro de URL, encerrando o script legítimo e iniciando um bloco de código malicioso. O resultado é a execução arbitrária de JavaScript no navegador da vítima, facilitando ataques de phishing e roubo de credenciais.

Community Posts

View all posts