Olá a todos, Pat Reeves aqui, de volta ao botsec.net. É 3 de abril de 2026 e eu tenho passado tempo demais recentemente investigando um tipo particular de problema relacionado a bots que está começando a me irritar. Falamos muito sobre botnets sofisticadas, ataque de preenchimento de credenciais e técnicas avançadas de evasão, e com razão. Mas, às vezes, é a negligência aparentemente pequena e quase trivial que deixa os maiores buracos.
Hoje, quero falar sobre algo que é menos sobre os bots em si e mais sobre as portas que deixamos escancaradas para eles. Especificamente, estou falando sobre a ameaça silenciosa de redirecionamentos e encaminhamentos inseguro do lado do servidor. Isso não se resume apenas a envenenamento de SEO ou experiência do usuário; quando feito errado, essas ações aparentemente inocentes se tornam um vetor primário para a tomada de conta impulsionada por bots, exfiltração de dados e até mapeamento interno da rede. 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. “Ele apenas envia o usuário para uma página diferente. Qual é o problema?” O grande problema, meus amigos, é quando essa “página diferente” é ditada pela entrada do usuário sem a validação adequada. Ou quando uma transferência confia internamente em parâmetros que se originaram externamente. É um problema clássico de confiança, e os bots prosperam em ambientes onde a confiança está mal colocada.
Pensem nisso. Você tem uma página de login. Após a autenticação bem-sucedida, você geralmente redireciona o usuário para o painel ou uma página previamente solicitada. Às vezes, essa URL de destino é passada como um parâmetro de consulta: /login?redirect_to=/dashboard. Parece bom, certo? Mas e se um bot mudar isso para /login?redirect_to=https://malicious-phishing-site.com/steal-creds? Ou, ainda pior, /login?redirect_to=//internal-admin-panel.yourdomain.com?
Recentemente, consultei uma empresa de e-commerce de médio porte que estava enfrentando um aumento no que pensavam ser “sequestro de sessão.” Usuários estavam relatando que eram desconectados e redirecionados para páginas estranhas, ou pior, encontrando seus carrinhos preenchidos com itens aleatórios e endereços de entrega 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, apressados, 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();
}
?>
Vê o problema? Nenhuma validação. Um bot poderia fazer login 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 vazado, e então apresentado a uma página de login falsa. Isso não era apenas hipotético; estava acontecendo. Bots estavam automatizando a descoberta e 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 existe há muito tempo, mas continua aparecendo. Bots adoram isso, pois conferem legitimidade aos ataques de phishing. Se a URL inicial é https://yourbank.com/login?redirect_to=https://evil.com, um usuário menos atento pode apenas ver “yourbank.com” e confiar nele.
Então, como solucionamos isso? Simples. Coloque em uma lista de permissão, não em uma lista de bloqueio. Nunca confie implicitamente em 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 próprio domínio. Caso contrário, redirecione para uma página segura.
Exemplo Prático 1: Protegendo Redirecionamentos em Python (Flask)
Digamos que você esteja usando Flask. Um padrão comum para redirecionamentos pode parecer assim (primeiro a versão vulnerável):
# REDIRECIONAMENTO VULNERÁVEL em Flask
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 login para continuar." # Placeholder para o formulário de login real
return f"Página 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) # PERIGO: 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 que next_url seja realmente um caminho interno ou um caminho no nosso domínio.
“`html
# REDIRECIONAMENTO SEGURO Flask
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 (redirecionará para o dashboard)
A função is_safe_url é fundamental aqui. Ela verifica se o esquema da URL de destino é HTTP/HTTPS e, crucialmente, se sua localização de rede (domínio) corresponde ao nosso. Isso previne redirecionamentos para sites externos.
Encaminhamentos do Lado do Servidor: O Primo Mais Astuto
Redirecionamentos são operações do lado do cliente; o navegador recebe um 302 e vai para outro lugar. Encaminhamentos do lado do servidor são diferentes. O servidor processa internamente a solicitação para um recurso diferente sem informar o cliente. A URL na barra de endereços do navegador não muda.
É aqui que as coisas ficam realmente interessantes para bots, especialmente se você estiver usando frameworks que lidam com isso internamente com base nos parâmetros da solicitação. Imagine um firewall de aplicativo web (WAF) ou um gateway de API que está inspecionando cuidadosamente as solicitações recebidas. Se um bot conseguir enganar sua aplicação para realizar um encaminhamento interno para um ponto final sensível com base em um parâmetro externo não validado, esse WAF ou gateway pode nunca ver a solicitação interna maliciosa.
Eu vi isso acontecer com uma instituição financeira. Eles tinham um ponto final de API interna, /admin/audit_logs, que só era acessível a partir de IPs internos específicos. O aplicativo web voltado para o público tinha um recurso de “visualizar detalhes da transação”, que, por razões 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 buscava os dados específicos.
Um bot descobriu que, se passasse um ID de transação especialmente elaborado que parecia ../../admin/audit_logs (uma tentativa de travessia de caminho), o mecanismo de encaminhamento interno, devido à má limpeza, resolveria isso como /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 não precisava nem estar em uma rede interna; apenas precisava manipular um parâmetro que foi usado posteriormente para um encaminhamento interno.
Exemplo Prático 2: Prevenindo Travessia de Caminho em Encaminhamentos (Java/JSP)
Em servlets Java, você pode usar RequestDispatcher.forward(). Um exemplo vulnerável pode parecer assim:
// ENCaminhamento VULNERÁVEL de Servlet Java
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"); // ex.: "transactionDetails.jsp"
if (resource != null && !resource.isEmpty()) {
RequestDispatcher dispatcher = request.getRequestDispatcher(resource); // PERIGO: 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 configuração interna)
Para garantir a segurança disso, você precisa garantir que o parâmetro resource não permita travessia de caminho e aponte apenas para recursos internos seguros e esperados. Novamente, a lista branca é sua amiga.
“““html
// SECURE Java Servlet forward
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()) {
// Normalize path to prevent traversal
String normalizedResource = new java.io.File(resource).getCanonicalPath();
String contextPath = request.getContextPath();
if (contextPath == null) contextPath = ""; // Handle root context
// Ensure the normalized path starts with context path or is absolute
if (normalizedResource.startsWith(contextPath)) {
normalizedResource = normalizedResource.substring(contextPath.length());
}
boolean isAllowed = false;
for (String allowed : ALLOWED_RESOURCES) {
if (allowed.equals(normalizedResource)) { // Strict equality to whitelist
isAllowed = true;
break;
}
}
if (isAllowed) {
RequestDispatcher dispatcher = request.getRequestDispatcher(normalizedResource);
dispatcher.forward(request, response);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "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 (embora getCanonicalPath() possa não ser totalmente confiável para caminhos da web sem verificações adicionais dependendo do contêiner de servlets). A parte crucial é verificar estritamente se o recurso solicitado corresponde a uma entrada em nossa lista de permissões. Qualquer desvio significa uma resposta proibida.
Por que os Bots Amam Essas Falhas
- Frutos ao Alcance: Esses não são sempre zero-days complexos. Muitas vezes, são falhas básicas de validação de entrada que escapam a revisões de código.
- Legitimidade & Confiança: Redirects abertos permitem que bots criem URLs de phishing que parecem originar de um domínio confiável.
- Contornando Controles de Segurança: Encaminhamentos do lado do servidor, quando explorados, podem contornar restrições de nível de rede e WAF que são projetadas para solicitações externas. A solicitação interna pode parecer perfeitamente legítima para o sistema interno.
- Descoberta Automatizada: Bots são excelentes em sondar parâmetros para esse tipo de vulnerabilidades. Eles tentarão vários payloads de travessia de caminho, URLs externas e caminhos internos até encontrarem algo.
- Exfiltração de Dados & ATO: Seja vazando IDs de sessão via redirects ou acessando dados internos via encaminhamentos, o objetivo final é frequentemente a tomada de conta ou roubo de dados.
Medidas Ação para a Segurança dos Bots
Certo, então o que você realmente faz sobre isso?
- Audite Seus Redirects & Encaminhamentos: Revise seu código. Pesquise por
header("Location:,response.sendRedirect,return redirect,RequestDispatcher.forward, e quaisquer construções similares em seu framework. - Implemente Whitelisting Estrito: Para qualquer destino de redirect ou encaminhamento que use entrada fornecida pelo usuário, garanta que a entrada esteja estritamente na lista de permissões.
- Para redirects: Verifique se o domínio de destino corresponde ao seu, ou se o caminho é um caminho interno e relativo.
- Para encaminhamentos: Garanta que o recurso de destino seja um dos recursos internos seguros predefinidos. Nunca permita caracteres de travessia de caminho (
../,..\) nos parâmetros de encaminhamento.
“““html
- 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 próprias 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 manipulação de strings em bruto. - Política de Segurança de Conteúdo (CSP): Embora não seja uma solução direta para problemas do lado do servidor, uma CSP robusta pode mitigar o impacto de redirecionamentos abertos, impedindo que scripts e recursos sejam carregados de domínios externos não confiáveis, mesmo que um usuário seja redirecionado.
- Verificações de Segurança Regulares & Testes de Penetração: Inclua verificações para vulnerabilidades de redirecionamentos abertos e encaminhamentos em suas verificações regulares. Bots estão constantemente à procura disso, e sua equipe de segurança também deveria.
Isso não é algo glamouroso. Não se trata da mais recente botnet alimentada por IA. Trata-se de higiene fundamental de segurança na web. Mas no mundo da defesa contra bots, garantir esses pontos de entrada básicos frequentemente traz as maiores vitórias. Não deixe que o redirecionamento útil ou o encaminhamento interno da sua aplicação se tornem o melhor amigo de um bot. Mantenha-se vigilante, mantenha-se seguro!
– Pat Reeves, botsec.net
“`
🕒 Published: