Segurança de APIs: protegendo seus endpoints
Autenticação, autorização, rate limiting, validação de entrada e os erros mais comuns que expõem APIs a ataques — um guia prático para blindar os endpoints da sua aplicação.

APIs são a espinha dorsal de praticamente todo app moderno construído com IA: o front-end conversa com o back-end por elas, integrações dependem delas e dados sensíveis trafegam por elas. Justamente por serem a porta de entrada, são também o alvo preferido de atacantes. Neste guia você vai conhecer as camadas essenciais para proteger seus endpoints — da autenticação à observabilidade — e os erros mais comuns que abrem brechas.
Por que APIs são um alvo tão visado
Diferente de uma interface web pensada para humanos, uma API é projetada para ser consumida por máquinas, de forma programática e em grande volume. Isso significa que um atacante pode automatizar tentativas, varrer endpoints e explorar falhas em escala. Se você ainda está construindo sua base conceitual, vale começar por O que é uma API? Definição clara para iniciantes e depois voltar a este guia com o vocabulário firme.
A segurança de API não é um único recurso, e sim um conjunto de camadas que se reforçam. Confiar em apenas uma — só autenticação, por exemplo — deixa flancos abertos. Esse princípio é conhecido como defesa em profundidade: cada camada assume que as outras podem falhar e ainda assim oferece proteção. Vamos percorrer as principais.
O modelo de superfície de ataque de uma API
Antes das camadas, vale visualizar onde estão os riscos. Cada endpoint que recebe entrada do usuário é uma porta. Cada parâmetro é uma fechadura que pode estar mal feita. A superfície inclui não só as rotas documentadas, mas também:
- Endpoints legados de versões antigas que continuam ativos.
- Rotas internas que vazaram para a internet por engano.
- Documentação automática (/swagger, /openapi.json) exposta publicamente.
- Webhooks e callbacks que aceitam dados de terceiros.
Pensar a API como superfície, e não como rotas isoladas, é o que evita aquela falha esquecida que derruba todo o resto. Atacantes mapeiam essa superfície exatamente como descrito em Reconhecimento (recon): a fase mais importante do pentest — então pense como eles para defender melhor.
Camada 1: Autenticação forte
Autenticação responde "quem está chamando esta API?". Os mecanismos mais usados hoje:
- Tokens JWT: o cliente envia um token assinado em cada requisição. Para entender a fundo seu funcionamento e armadilhas, veja O que é JWT (JSON Web Token)?.
- OAuth 2.0: ideal quando terceiros precisam acessar recursos em nome do usuário, conforme explicado em O que é OAuth 2.0? Delegação de acesso explicada.
- API keys: chaves estáticas para identificar aplicações; simples, mas exigem cuidado redobrado no armazenamento.
A RFC 7519 (Jones, Bradley, Sakimura, 2015) padroniza os tokens JWT que sustentam boa parte dessas estratégias. Independente do método, a regra é: autentique no servidor, valide a assinatura e os claims do token, e nunca confie em identidade vinda do cliente sem verificação.
GET /api/v1/pedidos HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiI...Armadilhas comuns de JWT
JWT é poderoso, mas tem pegadinhas que aparecem em auditorias com frequência:
- Algoritmo none: bibliotecas antigas aceitavam tokens sem assinatura quando o cabeçalho dizia "alg": "none". Sempre fixe os algoritmos aceitos no servidor.
- Confusão de algoritmo: um atacante troca RS256 (assimétrico) por HS256 (simétrico) e usa a chave pública como segredo. Valide o algoritmo esperado, não o que o token declara.
- Falta de expiração: tokens sem exp vivem para sempre. Use prazos curtos e refresh tokens.
- Não validar aud e iss: um token emitido para outro serviço não deveria ser aceito pelo seu.
Para sessões longas, prefira access tokens de vida curta combinados com refresh tokens revogáveis, em vez de um único token eterno.
Camada 2: Autorização correta em cada endpoint
Autenticar não basta: depois de saber quem é o usuário, você precisa decidir o que ele pode fazer. Um dos erros mais graves e comuns em APIs é a autorização quebrada em nível de objeto — quando o usuário A consegue acessar o recurso do usuário B só trocando um ID na URL.
GET /api/v1/faturas/1042 <- minha fatura
GET /api/v1/faturas/1043 <- fatura de OUTRO usuário (deveria ser 403!)A defesa é checar, no servidor e em cada requisição, se o usuário autenticado realmente é dono do recurso solicitado. Nunca dependa de o front-end "não mostrar" o botão. O OWASP ASVS (OWASP Foundation, 2021) trata esse controle como requisito central de verificação de segurança.
IDOR, BOLA e o problema dos IDs sequenciais
Essa classe de falha aparece nas referências de segurança como IDOR (Insecure Direct Object Reference) ou, no vocabulário específico de APIs, BOLA (Broken Object Level Authorization) — consistentemente o risco número um do OWASP API Security Top 10. A causa raiz é sempre a mesma: o servidor confia no ID enviado pelo cliente sem confirmar a propriedade do objeto.
Algumas defesas práticas:
- Verificação de propriedade no servidor: filtre as consultas pelo usuário autenticado (WHERE user_id = :usuario_atual), não apenas pelo ID do recurso.
- IDs não sequenciais: usar UUIDs em vez de inteiros incrementais não substitui a checagem, mas dificulta a enumeração cega.
- Autorização em nível de função e de objeto: separe "pode acessar este tipo de recurso" de "pode acessar este recurso específico".
# Ruim: confia no ID e não checa propriedade
fatura = db.get_fatura(id=request_id)
return fatura
# Bom: vincula a consulta ao usuário autenticado
fatura = db.get_fatura(id=request_id, user_id=usuario_autenticado.id)
if fatura is None:
return resposta(404) # não revela se o recurso existe
return faturaRepare no 404 em vez de 403: revelar que o recurso existe (mas é de outro) já entrega informação ao atacante.
Camada 3: Validação e sanitização de entrada
Toda entrada vinda do cliente é não confiável até prova em contrário. Falhas de validação levam a injeções (SQL, comandos, NoSQL) e a comportamentos inesperados. As práticas essenciais:
- Valide tipo, formato e tamanho de cada campo (use schemas).
- Prefira allowlists (o que é permitido) a denylists (o que é proibido).
- Use consultas parametrizadas para falar com o banco — nunca concatene strings de SQL.
- Imponha limites de tamanho ao corpo da requisição para evitar abuso de memória.
# Ruim: vulnerável a SQL injection
db.execute(f"SELECT * FROM users WHERE email = '{email}'")
# Bom: consulta parametrizada
db.execute("SELECT * FROM users WHERE email = %s", (email,))Validação por schema na borda
A forma mais robusta de validar é definir um schema explícito para cada endpoint e rejeitar qualquer requisição que não o satisfaça, antes de qualquer lógica de negócio. Isso centraliza a validação na borda da API e garante que o restante do código trabalhe apenas com dados já confiáveis:
# Exemplo com Pydantic (Python)
from pydantic import BaseModel, EmailStr, conint
class CriarPedido(BaseModel):
email: EmailStr
quantidade: conint(gt=0, le=100)
cupom: str | None = NoneSe o corpo da requisição não bater com o schema, a requisição falha com 422 antes de tocar o banco. O mesmo vale para validar tipos numéricos, comprimentos máximos de string e formatos de data. Tratar a entrada com rigor na borda elimina classes inteiras de bug de uma vez.
Camada 4: Rate limiting e proteção contra abuso
Rate limiting restringe quantas requisições um cliente pode fazer em um intervalo de tempo. Sem ele, sua API fica exposta a:
- Força bruta contra endpoints de login.
- Negação de serviço (DoS) por excesso de chamadas.
- Scraping abusivo de dados.
Estratégias comuns incluem limitar por IP, por API key ou por usuário autenticado, usando algoritmos como token bucket ou janela deslizante. Quando o limite é excedido, responda com o status apropriado:
HTTP/1.1 429 Too Many Requests
Retry-After: 60Combine rate limiting com bloqueio temporário após várias falhas de autenticação para frustrar ataques automatizados.
Escolhendo a chave e o algoritmo
A escolha da chave de limitação importa tanto quanto o limite em si. Limitar só por IP pune usuários atrás de um mesmo NAT corporativo e é facilmente burlado por quem rotaciona IPs. O ideal é combinar dimensões: por usuário autenticado para endpoints sensíveis, por IP para rotas públicas, e por API key para integrações.
Quanto aos algoritmos:
- Token bucket: permite rajadas curtas até esgotar os "tokens", que se recarregam a uma taxa fixa. Bom para tráfego naturalmente irregular.
- Janela deslizante (sliding window): conta requisições em uma janela móvel, evitando o pico de borda que a janela fixa permite.
- Janela fixa: simples, mas vulnerável a dobrar o limite na virada da janela.
Exponha cabeçalhos como X-RateLimit-Remaining para que clientes bem-comportados se autorregulem, reduzindo o tráfego de erro.
Camada 5: Transporte seguro e cabeçalhos
Toda comunicação com a API deve trafegar exclusivamente sobre HTTPS. Dados em texto puro na rede podem ser interceptados, incluindo tokens de autenticação. Além disso:
- Desabilite métodos HTTP não usados e feche endpoints de debug.
- Configure CORS de forma restritiva, liberando apenas as origens necessárias.
- Use cabeçalhos de segurança apropriados nas respostas.
- Não exponha detalhes internos em mensagens de erro — um stack trace vazado entrega informação valiosa ao atacante.
CORS sem furos
CORS (Cross-Origin Resource Sharing) é fonte recorrente de configuração perigosa. Os erros clássicos:
- *Access-Control-Allow-Origin: combinado com credenciais**: liberar qualquer origem e ainda aceitar cookies é uma porta escancarada.
- Refletir a origem sem validar: ecoar o cabeçalho Origin recebido equivale, na prática, a permitir tudo.
- Allowlist frouxa: validar apenas o final do domínio permite que meusite.com.atacante.com passe.
Mantenha uma allowlist explícita de origens confiáveis e valide a correspondência exata. CORS é um controle do navegador, não substitui autorização no servidor — mas mal configurado abre vetores reais.
Os erros mais comuns que expõem APIs
Vale conhecer os padrões de falha mais frequentes, muitos deles catalogados no OWASP Top 10 explicado: as 10 maiores falhas de segurança web:
- Exposição excessiva de dados: o endpoint retorna o objeto inteiro do banco, incluindo campos sensíveis que o cliente deveria filtrar. Retorne só o necessário.
- Falta de autorização em nível de função: endpoints administrativos acessíveis a usuários comuns.
- Mass assignment: aceitar no corpo da requisição campos que o usuário não deveria poder definir (como role: admin). Valide quais campos são editáveis.
- Segredos vazados: chaves e credenciais em código-fonte, repositórios ou logs. Esse problema é tão central que tem guia próprio em Gestão de segredos e chaves de API sem vazar dados.
- Versionamento e endpoints esquecidos: versões antigas da API que continuam ativas e vulneráveis.
- Consumo irrestrito de recursos: requisições que pedem paginação gigante ou disparam processamento caro sem limites, abrindo espaço para DoS na camada de aplicação.
Mass assignment na prática
O mass assignment merece destaque porque é traiçoeiro. Muitos frameworks mapeiam automaticamente o JSON recebido para os campos de um modelo. Se o cliente enviar um campo extra que existe no modelo mas não deveria ser editável, ele é gravado:
{ "nome": "Ana", "email": "ana@exemplo.com", "role": "admin" }Se o servidor faz usuario.update(**dados) sem filtrar, o usuário acabou de se promover a admin. A defesa é validar quais campos são editáveis por meio de um schema explícito (como o da Camada 3), nunca aceitando o corpo bruto direto no modelo.
Observabilidade: enxergar o ataque acontecendo
Defender é também detectar. Registre eventos de segurança relevantes — falhas de autenticação, acessos negados, picos de tráfego — sem nunca logar dados sensíveis como senhas ou tokens completos. Logs estruturados e alertas permitem que você perceba um ataque em andamento em vez de descobri-lo semanas depois pelo vazamento.
Monitore métricas como taxa de respostas 401/403, latência anormal e volume de 429. Um aumento súbito nessas taxas costuma ser o primeiro sinal de uma campanha automatizada contra seus endpoints.
Boas práticas de log seguro:
- Redija segredos: nunca registre senhas, tokens completos, números de cartão ou PII desnecessária.
- Correlacione com IDs de requisição: um request_id por chamada permite reconstruir o caminho de um ataque.
- Alerte em padrões, não em eventos isolados: uma falha de login é normal; mil falhas em um minuto, vindas do mesmo intervalo de IPs, é um ataque.
- Cuidado com mensagens de erro 5xx: detalhes internos do banco ou do driver vazados ao cliente são informação de bandeja para o atacante. Redija antes de responder.
Segurança no ciclo de vida da API
As camadas que vimos protegem a API em execução, mas a segurança começa muito antes do primeiro deploy e continua depois dele. Pensar no ciclo de vida completo evita que falhas entrem silenciosamente:
- Design: defina o contrato da API (por exemplo, com OpenAPI) antes de codar. Um contrato explícito é a base para validação automática de entrada e saída e documenta quais campos cada endpoint aceita.
- Desenvolvimento: use análise estática para pegar SQL concatenado, segredos no código e dependências vulneráveis antes de qualquer commit chegar à branch principal.
- Testes: além de testes funcionais, escreva testes de segurança que confirmem que um usuário não acessa o recurso de outro (anti-IDOR), que campos sensíveis não são editáveis (anti-mass-assignment) e que rotas protegidas rejeitam requisições sem token.
- Deploy: rotacione segredos, feche endpoints de debug e confirme que a configuração de produção difere da de desenvolvimento (sem CORS aberto, sem stack traces).
- Operação: monitore, alerte e tenha um plano de resposta para quando — não se — um incidente acontecer.
Tratar segurança como um portão de qualidade contínuo, e não como uma auditoria pontual antes do lançamento, é o que mantém a postura defensiva ao longo da evolução do produto.
Versionamento e depreciação seguros
APIs evoluem, e versões antigas tendem a virar dívida de segurança esquecida. Adote uma política explícita: documente quais versões estão suportadas, comunique prazos de depreciação aos consumidores e desative de fato as versões antigas no servidor, não apenas na documentação. Uma rota /api/v1 que continua respondendo dois anos depois do lançamento da v2, sem receber correções, é exatamente o tipo de endpoint esquecido que atacantes procuram.
Um checklist prático
Antes de colocar uma API em produção, confirme:
- [ ] Toda rota protegida exige autenticação válida no servidor.
- [ ] Cada acesso a recurso verifica a propriedade (sem IDOR/BOLA).
- [ ] Toda entrada é validada por schema e consultas são parametrizadas.
- [ ] Campos sensíveis (como role) não podem ser definidos via mass assignment.
- [ ] Rate limiting está ativo, especialmente no login.
- [ ] Comunicação é só HTTPS e CORS está restrito a origens conhecidas.
- [ ] Respostas não vazam stack traces nem campos sensíveis.
- [ ] Segredos estão fora do código, em um gerenciador apropriado.
- [ ] Endpoints legados e de debug foram desativados.
- [ ] Eventos de segurança são registrados e monitorados.
Perguntas frequentes
JWT ou sessão no servidor? Depende. JWT brilha em arquiteturas distribuídas e sem estado, mas dificulta revogação imediata. Sessões no servidor são triviais de revogar, ao custo de armazenamento compartilhado. Muitos sistemas combinam os dois: JWT de vida curta + refresh token revogável.
Rate limiting resolve DoS? Reduz DoS na camada de aplicação e ataques de força bruta, mas não substitui proteção de infraestrutura (CDN, WAF) contra DDoS volumétrico.
API key é suficiente para autenticar? Para identificar uma aplicação, sim; para autenticar um usuário com permissões granulares, não. API keys são estáticas e, se vazadas, dão acesso pleno até a rotação. Trate-as como segredos e combine com escopos.
Preciso validar entrada se uso um ORM? Sim. O ORM protege contra SQL injection em consultas parametrizadas, mas não valida regras de negócio, tipos, tamanhos nem impede mass assignment. Validação por schema continua necessária.
Conclusão
Segurança de API não é um produto que você compra, e sim um conjunto de camadas que se reforçam: autenticação forte, autorização verificada em cada requisição, validação rigorosa de entrada, rate limiting, transporte seguro e observabilidade. Os ataques mais comuns exploram justamente a ausência de uma dessas camadas — uma autorização esquecida, uma entrada não validada, um campo de mass assignment aberto, um segredo vazado. Trate cada endpoint como uma porta que precisa de fechadura, vigia e registro, adote defesa em profundidade para que a falha de uma camada não derrube as outras, e suas APIs estarão à frente da maioria das aplicações por aí.
Referências
- OWASP Foundation (2021). OWASP Application Security Verification Standard 4.0. OWASP.
- Jones, M., Bradley, J., Sakimura, N. (2015). RFC 7519: JSON Web Token (JWT). IETF.
- OWASP Foundation (2023). OWASP API Security Top 10. OWASP.
- Hardt, D. (2012). RFC 6749: The OAuth 2.0 Authorization Framework. IETF.


