Olá a todos, Pat Reeves aqui, de volta ao botsec.net. É 3 de abril de 2026 e tenho passado muito tempo ultimamente explorando um tipo específico de problemas relacionados a bots que realmente estão começando a me incomodar. Falamos frequentemente sobre botnets sofisticados, credential stuffing e técnicas avançadas de evasão, e com razão. Mas às vezes, é o aparente pequeno, quase banal erro que deixa as maiores falhas.
Hoje quero falar sobre algo que diz respeito menos aos próprios bots e mais às portas que deixamos escancaradas para eles. Em particular, estou falando da ameaça silenciosa dos redirecionamentos e das encaminhamentos de servidor inseguros. Não se trata apenas de SEO poisoning ou da experiência do usuário; quando feito de forma inadequada, essas ações aparentemente inofensivas se tornam um vetor principal para takeover de contas guiados por bots, exfiltração de dados e até mesmo mapeamento da rede interna. E acreditem, os bots estão se tornando realmente bons em explorá-los.
“Mas Pat, é apenas um redirecionamento, certo?”
Essa é geralmente a primeira reação que recebo. “Simplesmente encaminhe o usuário para outra página. Qual é o problema?” O problema, meus amigos, é quando essa “página diferente” é determinada pela entrada do usuário sem uma validação adequada. Ou quando um redirecionamento confia internamente em parâmetros que foram originados externamente. É um clássico problema de confiança, e os bots prosperam em ambientes onde a confiança é mal colocada.
Pensem nisso. Vocês têm uma página de login. Após uma autenticação bem-sucedida, geralmente redirecionam o usuário para seu painel ou para uma página solicitada anteriormente. Às vezes, essa URL de destino é passada como um parâmetro de consulta: /login?redirect_to=/dashboard. Parece certo, certo? Mas e se um bot a alterar para /login?redirect_to=https://malicious-phishing-site.com/steal-creds? Ou, pior ainda, /login?redirect_to=//internal-admin-panel.yourdomain.com?
Recentemente, consultei uma empresa de e-commerce de médio porte que estava passando por um aumento do que pensavam ser “hijacking de sessões.” Os usuários relataram ter sido desconectados e redirecionados para páginas estranhas, ou pior, encontrando seus carrinhos preenchidos com itens aleatórios e endereços de envio alterados. Após muitas investigações, encontramos o culpado: um parâmetro de redirecionamento não validado em seu fluxo pós-login.
Seus desenvolvedores, apressadamente, implementaram um simples redirecionamento em PHP:
<?php
if (isset($_GET['redirect_to']) && !empty($_GET['redirect_to'])) {
header("Location: " . $_GET['redirect_to']);
exit();
} else {
header("Location: /dashboard");
exit();
}
?>
Viram o problema? Nenhuma validação. Um bot podia acessar e, então, criar uma URL como https://shop.example.com/post-login.php?redirect_to=//attacker.com/phish.html?stolen_session_id=ABCD123. O usuário, pensando que ainda estava no site legítimo, seria redirecionado, seu ID de sessão potencialmente exposto, e então apresentado com uma página de login falsa. Isso não era apenas hipotético; estava acontecendo. Os bots estavam automatizando a descoberta e a exploração dessa falha, transformando sessões de usuários legítimos em oportunidades de phishing.
Redirecionamentos Abertos: A Falha Óbvia, Mas Muitas Vezes Ignorada
O exemplo acima é um clássico “redirecionamento aberto.” Ele sempre esteve presente, e ainda assim continua a ressurgir. Os bots adoram isso porque conferem legitimidade aos ataques de phishing. Se a URL inicial é https://yourbank.com/login?redirect_to=https://evil.com, um usuário menos experiente pode simplesmente ver “yourbank.com” e confiar.
Então, como consertamos isso? Simples. Whitelist, não blacklist. Nunca confie implicitamente nas URLs de redirecionamento fornecidas pelo usuário. Em vez disso, verifique se a URL fornecida corresponde a um padrão esperado ou está dentro do seu domínio. Se não estiver, defina uma página segura como padrão.
Exemplo Prático 1: Segurança dos Redirecionamentos em Python (Flask)
Diga que você está usando Flask. Um padrão comum para os redirecionamentos pode parecer com isso (primeiro a versão vulnerável):
“`html
# VULNERABLE Flask redirect
from flask import Flask, request, redirect, url_for
app = Flask(__name__)
@app.route('/login')
def login():
if not request.args.get('next'):
return "Por favor, faça o login para continuar." # Placeholder para o formulário de login real
return f"Pagina de login para {request.args.get('next')}"
@app.route('/auth_success')
def auth_success():
next_url = request.args.get('next')
if next_url:
return redirect(next_url) # PERIGOSO: Redirecionamento aberto!
return redirect(url_for('dashboard'))
@app.route('/dashboard')
def dashboard():
return "Bem-vindo ao seu painel!"
# Para testar: http://127.0.0.1:5000/auth_success?next=https://malicious.com
Agora, vamos corrigir isso. Precisamos validar se next_url é de fato um caminho interno ou um caminho no nosso domínio.
# SECURE Flask redirect
from flask import Flask, request, redirect, url_for
from urllib.parse import urlparse, urljoin
app = Flask(__name__)
def is_safe_url(target):
ref_url = urlparse(request.host_url)
test_url = urlparse(urljoin(request.host_url, target))
return test_url.scheme in ('http', 'https') and \
ref_url.netloc == test_url.netloc
@app.route('/auth_success')
def auth_success():
next_url = request.args.get('next')
if next_url and is_safe_url(next_url):
return redirect(next_url)
return redirect(url_for('dashboard'))
# Para testar:
# http://127.0.0.1:5000/auth_success?next=/dashboard
# http://127.0.0.1:5000/auth_success?next=https://malicious.com (será redirecionado para o dashboard)
A função is_safe_url é fundamental aqui. Ela verifica se o esquema da URL de destino é HTTP/HTTPS e, o que é crucial, se sua localização de rede (domínio) corresponde ao nosso. Isso previne redirecionamentos para sites externos.
Encaminhamentos Lado Servidor: O Primo Mais Sutil
Redirecionamentos são operações do lado do cliente; o navegador recebe um 302 e vai para outro lugar. Os encaminhamentos do lado do servidor são diferentes. O servidor processa internamente a solicitação por um recurso diferente sem informar o cliente. A URL na barra de endereços do navegador não muda.
Aqui as coisas ficam realmente interessantes para bots, especialmente se você estiver usando frameworks que gerenciam essas operações internamente com base nos parâmetros da solicitação. Imagine um firewall para aplicativos web (WAF) ou um gateway API que inspecionam cuidadosamente as solicitações recebidas. Se um bot conseguir enganar seu aplicativo para executar um encaminhamento interno para um ponto final sensível com base em um parâmetro externo não validado, esse WAF ou gateway pode nem mesmo perceber a solicitação interna maliciosa.
Eu vi isso acontecer em um instituto financeiro. Eles tinham um ponto final API interno, /admin/audit_logs, acessível apenas de endereços IP internos específicos. O aplicativo web público tinha uma função de “visualizar detalhes da transação”, que, por motivos de desempenho, usava um encaminhamento interno para um servlet genérico de “visualizador de dados”, passando o ID da transação. O servlet então recuperava os dados específicos.
Um bot descobriu que se passasse um ID de transação especificamente projetado que se parecia com ../../admin/audit_logs (uma tentativa de traversal path), o mecanismo de encaminhamento interno, devido a uma sanitização inadequada, o resolvia em /admin/audit_logs. O servidor, pensando que era uma solicitação interna, ignorou a restrição de IP e forneceu os logs de auditoria. O bot nem precisou estar em uma rede interna; apenas precisava manipular um parâmetro que seria usado para um encaminhamento interno.
Exemplo Prático 2: Prevenir a Traversal Path em Encaminhamentos (Java/JSP)
Nos servlets Java, você poderia usar RequestDispatcher.forward(). Um exemplo vulnerável poderia se parecer com isso:
“`
// VULNERÁVEL encaminhamento Java Servlet
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/dataViewer")
public class DataViewerServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String resource = request.getParameter("resource"); // por exemplo, "transactionDetails.jsp"
if (resource != null && !resource.isEmpty()) {
RequestDispatcher dispatcher = request.getRequestDispatcher(resource); // PERIGOSO: Travessia de caminho
dispatcher.forward(request, response);
} else {
response.getWriter().println("Parâmetro de recurso ausente.");
}
}
}
// Para testar: /dataViewer?resource=../../WEB-INF/web.xml (pode expor a configuração interna)
Para tornar isso seguro, você deve se certificar de que o parâmetro resource não permita a travessia de caminho e aponte apenas para recursos internos seguros e previstos. Mais uma vez, a lista de permissões é sua amiga.
// AQUELE encaminhamento seguro Java Servlet
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/dataViewer")
public class DataViewerServlet extends HttpServlet {
private static final String[] ALLOWED_RESOURCES = {
"/WEB-INF/jsp/transactionDetails.jsp",
"/WEB-INF/jsp/userDetails.jsp",
"/WEB-INF/jsp/productInfo.jsp"
};
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String resource = request.getParameter("resource");
if (resource != null && !resource.isEmpty()) {
// Normalizar caminho para prevenir travessia
String normalizedResource = new java.io.File(resource).getCanonicalPath();
String contextPath = request.getContextPath();
if (contextPath == null) contextPath = ""; // Tratar contexto raiz
// Garantir que o caminho normalizado comece com o caminho de contexto ou seja absoluto
if (normalizedResource.startsWith(contextPath)) {
normalizedResource = normalizedResource.substring(contextPath.length());
}
boolean isAllowed = false;
for (String allowed : ALLOWED_RESOURCES) {
if (allowed.equals(normalizedResource)) { // Igualdade estrita para lista de permissões
isAllowed = true;
break;
}
}
if (isAllowed) {
RequestDispatcher dispatcher = request.getRequestDispatcher(normalizedResource);
dispatcher.forward(request, response);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "O acesso ao recurso solicitado é proibido.");
}
} else {
response.getWriter().println("Parâmetro de recurso ausente.");
}
}
}
Nesta versão segura, temos uma lista predefinida de ALLOWED_RESOURCES. Também tentamos normalizar o caminho (mesmo que getCanonicalPath() possa não ser completamente confiável para caminhos web sem verificações adicionais dependendo do contêiner servlet). A parte crucial é verificar rigorosamente se o recurso solicitado corresponde a uma entrada na nossa lista de permissões. Qualquer desvio significa uma resposta proibida.
Por que os Bots Amam Essas Vulnerabilidades
- Frutos de Baixo Custo: Eles não são sempre zero-days complexos. Muitas vezes são simples erros de validação de entrada que escapam das revisões de código.
- Legitimidade & Confiança: Os redirecionamentos abertos permitem que bots criem URLs de phishing que parecem vir de um domínio confiável.
- Superação dos Controles de Segurança: Os encaminhamentos do lado do servidor, quando explorados, podem contornar as restrições de rede e WAF projetadas para solicitações externas. A solicitação interna pode parecer perfeitamente legítima para o sistema interno.
- Descoberta Automática: Bots são excelentes em sondar parâmetros para esse tipo de vulnerabilidade. Eles tentarão vários payloads de travessia de caminho, URLs externos e caminhos internos até encontrarem algo.
- Exfiltração de Dados & Acesso Não Autorizado: Seja por meio de vazamentos de ID de sessão por meio de redirecionamentos ou acesso a dados internos por meio de encaminhamentos, o objetivo final é frequentemente a obtenção de contas ou o roubo de dados.
Considerações Práticas para a Segurança Contra Bots
Certo, então o que você realmente pode fazer sobre isso?
- Audite seus Redirecionamentos & Encaminhamentos: Verifique seu código-fonte. Procure por
header("Location:,response.sendRedirect,return redirect,RequestDispatcher.forwarde qualquer construção semelhante em seu framework. - Implemente Whitelisting Rigoroso: Para qualquer destino de redirecionamento ou encaminhamento que use input fornecido pelo usuário, certifique-se de que o input seja rigorosamente autorizado.
- Para redirecionamentos: Verifique se o domínio de destino corresponde ao seu, ou se o caminho é um caminho interno e relativo.
- Para encaminhamentos: Certifique-se de que o recurso de destino seja um dos conjuntos internos pré-definidos e seguros. Nunca permita caracteres de travessia de caminho (
../,..\) nos parâmetros de encaminhamento.
- Use Funções Seguras Fornecidas pelo Framework: A maioria dos frameworks web modernos possui funções integradas para redirecionamentos e encaminhamentos seguros. Use-as! Não crie as suas a menos que você entenda absolutamente as implicações de segurança. Por exemplo, as funções auxiliares
url_for()do Flask eredirect()do Django, quando usadas com nomes internos, são geralmente mais seguras do que a manipulação de strings brutas. - Content Security Policy (CSP): Embora não seja uma solução direta para problemas do lado do servidor, uma CSP sólida pode mitigar o impacto dos redirecionamentos abertos, impedindo o carregamento de scripts e recursos de domínios externos não confiáveis, mesmo que um usuário seja redirecionado.
- Escaneamentos de Segurança Regulares & Testes de Penetração: Inclua verificações para vulnerabilidades de redirecionamentos abertos e encaminhamentos em seus escaneamentos regulares. Bots estão constantemente procurando por essas vulnerabilidades, e sua equipe de segurança também deveria.
Não é glamour. Não se trata da última botnet alimentada por IA. Trata-se de uma higiene correta de segurança web fundamental. Mas no mundo da defesa contra bots, reforçar esses pontos de acesso básicos muitas vezes leva aos melhores resultados. Não deixe que o redirecionamento útil ou o encaminhamento interno de sua aplicação se tornem o melhor amigo de um bot. Mantenha-se vigilante, mantenha-se seguro!
– Pat Reeves, botsec.net
🕒 Published: