[TabNews – Postmortem] Open Redirect descoberto na página de login
Na última sexta-feira, fomos informados pelo Renan sobre uma vulnerabilidade do tipo Open Redirect em nossa página de login. 😱 O problema já foi corrigido ontem. 🙌
Embora a falha pudesse ser explorada em determinados cenários, não encontramos nenhum indício de abuso.
O que aconteceu
A página de login do TabNews aceita um parâmetro redirect
para redirecionar o usuário de volta para a página que estava antes do login. A ideia é que, ao tentar interagir com uma publicação sem estar autenticado, ele seja levado para a página de login e, após autenticar, volte para a rota original.
O problema é que estávamos validando o redirect
apenas verificando se ele começava com /
sem começar com //
, que poderia indicar um domínio externo (por exemplo, //curso.dev
).
No entanto, como o Renan alertou, ainda era possível burlar essa verificação com uma URL como esta:
https://tabnews.com.br/login?redirect=/%09/curso.dev
O %09
é só um exemplo, e representa uma tabulação. O que acontecia:
- O Next.js automaticamente convertia
%09
em uma tabulação real (\t
) ao preencherrouter.query.redirect
. - O caminho era recebido como
"/\t/curso.dev"
e considerado como interno. - Ao usar
router.replace(redirect)
, o caractere de tabulação era descartado silenciosamente, transformando o caminho em//curso.dev
. - Isso resultava em um redirecionamento para
https://curso.dev
, o que nunca deveria ser possível, já que o redirecionamento deve ocorrer apenas para rotas internas do TabNews.
Como corrigimos
A correção foi feita garantindo que o valor passado no redirect
seja interpretado de forma segura:
- Em vez de confiar na string bruta, agora construímos um
new URL(redirect, location.origin)
e validamos seurl.origin
continua sendo igual alocation.origin
. - Só redirecionamos se essa condição for verdadeira. Isso impede que qualquer caminho externo (mesmo malformado ou disfarçado) seja aceito.
Com essa abordagem, mesmo que o redirect
contenha espaços, quebras de linha ou tabulações, o redirecionamento só ocorre se o destino final continuar dentro do domínio do TabNews.
O que aprendemos
Esse incidente reforça que:
- Verificações simples, como "começa com
/
e não com//
", não são suficientes quando múltiplos componentes (navegador, framework, bibliotecas) participam do parsing da URL. - A decodificação automática feita pelo Next.js nos parâmetros da URL pode introduzir riscos se não forem considerados os efeitos colaterais, como a remoção silenciosa de certos caracteres.
- A validação robusta de origem com
new URL(..., base)
é uma abordagem muito mais segura do que tentar manipular strings manualmente.
O que ainda podemos melhorar
Seria ótimo adicionar testes automatizados específicos para validar esse tipo de redirecionamento e garantir que o comportamento continue seguro no futuro.
Como reportar vulnerabilidades
Se você encontrar qualquer problema de segurança no TabNews, pedimos que utilize uma das opções abaixo para fazer o reporte:
- Via GitHub: Security advisories
- Por e-mail: [email protected]
Todos os relatos são analisados com prioridade, e agradecemos desde já qualquer colaboração nesse sentido.
Agradecimentos
Nosso agradecimento ao Renan, que identificou e compartilhou a vulnerabilidade de forma ética. 💪 Esse tipo de contribuição ajuda a tornar o TabNews mais seguro para todo mundo. 🚀