O que são “testes de segurança básica” em APIs
Testes de segurança básica em APIs são validações objetivas que verificam se a API se comporta de forma segura diante de entradas maliciosas ou uso indevido comum, sem exigir técnicas avançadas de pentest. O foco é confirmar que a API: (1) restringe acesso por recurso (não apenas por “estar logado”), (2) não permite enumeração de identificadores (IDOR), (3) trata entradas de forma robusta (evitando injeções comuns), (4) limita abuso por volume (rate limiting), (5) aplica CORS corretamente quando exposta a browsers e (6) não vaza dados sensíveis em headers/respostas/logs.
Esses testes são majoritariamente “casos negativos”: você tenta fazer algo que não deveria ser permitido e observa se a API responde com bloqueio, mensagens genéricas e sem detalhes internos.
Pré-requisito conceitual: dados sensíveis em trânsito e em repouso
HTTPS como base
Antes de qualquer validação, trate HTTPS como pré-requisito: credenciais, tokens e dados pessoais não devem trafegar em HTTP. Em testes, valide que:
- O endpoint público usa
https://e não aceita downgrade parahttp://. - Requisições via HTTP (se existirem) são redirecionadas ou bloqueadas (conforme arquitetura), e nunca retornam dados sensíveis.
Checagem prática
- Tente chamar o mesmo endpoint via HTTP e observe: não deve haver resposta com payload sensível.
- Verifique se cookies (quando usados) têm
SecureeHttpOnly(quando aplicável a apps web).
Controle de acesso por recurso (Resource-Level Authorization)
Um erro comum é validar apenas se o usuário está autenticado, mas não se ele pode acessar aquele recurso específico. Controle de acesso por recurso significa que, para cada item (pedido, conta, documento), a API verifica se o usuário tem permissão para ler/alterar aquele item.
O que validar
- Leitura: usuário A não deve conseguir
GETrecursos do usuário B. - Alteração: usuário A não deve conseguir
PATCH/PUT/DELETErecursos do usuário B. - Ações: endpoints de “aprovar”, “cancelar”, “reembolsar” etc. devem validar permissão por recurso e por papel.
Passo a passo prático (casos negativos)
- Tenha dois usuários de teste:
userAeuserB, cada um com seus próprios recursos (ex.: pedidos). - Com credenciais de
userA, crie um recurso e capture o identificador (idA). - Com credenciais de
userB, tente acessar o recurso deuserAusandoidA. - Repita para operações de escrita (alterar/cancelar/excluir).
# Exemplo: userB tentando ler um recurso de userA (negativo) GET /orders/{idA} Authorization: Bearer <tokenUserB>Respostas esperadas (seguras)
403 Forbiddenquando o recurso existe, mas o usuário não tem permissão.404 Not Foundquando a estratégia é “não revelar existência” (depende do padrão do produto). O importante é consistência e não vazar detalhes.- Mensagem genérica, sem indicar “esse pedido pertence ao usuário X”.
Anti-padrões (sinais de falha)
- Retornar
200com dados de outro usuário. - Retornar erro detalhado indicando o dono do recurso, IDs internos, nomes de tabelas ou stack trace.
IDOR (Insecure Direct Object Reference) e enumeração de IDs
IDOR ocorre quando a API usa um identificador direto (por exemplo, /users/123, /files/abc) e não valida se o solicitante pode acessar aquele objeto. Mesmo com controle de acesso “geral”, falhas de IDOR aparecem quando a checagem por recurso é omitida em algum endpoint.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
Como testar enumeração de IDs
O objetivo é verificar se alterar o ID na URL, query ou corpo permite acesso indevido.
Passo a passo prático
- Identifique endpoints com IDs previsíveis (numéricos sequenciais, UUIDs expostos, códigos curtos).
- Faça uma requisição válida com seu próprio ID e confirme o sucesso.
- Altere o ID para um valor próximo (ex.:
+1,-1) ou um ID conhecido de outro usuário. - Repita em endpoints de leitura e escrita.
# Exemplo: tentativa de enumeração simples GET /accounts/1001 Authorization: Bearer <tokenUserA> GET /accounts/1002 Authorization: Bearer <tokenUserA>O que observar na resposta
- Não deve haver diferença “rica” de mensagens entre “não existe” e “existe mas não é seu” que facilite enumeração.
- Não deve retornar metadados que confirmem existência (ex.: nome, e-mail parcial, status do recurso).
Casos negativos adicionais
- IDs em campos do corpo:
{ "userId": 123 }— tente trocar para outro usuário. - IDs em parâmetros opcionais:
?ownerId=,?accountId=. - Endpoints de download: links diretos para arquivos devem exigir autorização, não apenas “URL secreta”.
Validação de input: injeções comuns em parâmetros e JSON
Validação de input em testes de API verifica se a aplicação trata entradas inesperadas sem executar comandos, sem quebrar parsing e sem retornar erros detalhados. Aqui o foco é cobrir injeções comuns e robustez de parsing, não explorar profundamente.
O que validar (visão prática)
- Campos string não devem aceitar payloads que alterem consultas/expressões.
- Campos numéricos devem rejeitar strings e formatos inválidos.
- JSON malformado deve ser rejeitado com erro controlado.
- Campos não esperados (extra fields) devem ser ignorados ou rejeitados conforme contrato, mas nunca causar comportamento inseguro.
Checklist de payloads negativos (exemplos)
Use em parâmetros de busca, filtros, ordenação e campos textuais:
- SQL injection básica:
' OR '1'='1 - Operadores comuns:
"; DROP TABLE x; --(apenas para validação de tratamento, não para dano) - NoSQL injection (quando há filtros JSON):
{"$ne": null} - Template injection/expressões:
{{7*7}} - Path traversal em nomes de arquivo:
../,..\ - JSON quebrado:
{"name": "abc"(faltando fechamento)
Passo a passo prático: montar casos negativos
- Escolha um endpoint que receba parâmetros e/ou JSON (ex.: criação de usuário, busca, atualização).
- Defina um “baseline” válido (requisição que funciona).
- Altere um campo por vez com um payload negativo (para isolar causa).
- Verifique status code e corpo do erro: deve ser controlado e sem detalhes internos.
- Confirme que não houve efeito colateral: nenhum registro indevido criado/alterado, nenhuma permissão elevada, nenhuma consulta “aberta”.
# Baseline (válido) POST /customers Content-Type: application/json { "name": "Ana", "email": "ana@example.com" } # Negativo: tentativa de injeção em campo string POST /customers Content-Type: application/json { "name": "Ana' OR '1'='1", "email": "ana@example.com" } # Negativo: JSON malformado POST /customers Content-Type: application/json { "name": "Ana", "email": "ana@example.com"Respostas esperadas (seguras)
400 Bad Requestpara formato inválido / JSON malformado / tipos errados.422 Unprocessable Entity- Mensagens genéricas e rastreáveis, sem stack trace, sem query, sem nomes de tabelas/coleções.
Anti-padrões
- Erro 500 com stack trace, detalhes de banco, nomes de classes, caminhos de arquivo.
- Resposta diferente que revela tecnologia interna (ex.: mensagem de driver SQL) e facilita exploração.
Rate limiting e proteção contra abuso (429)
Rate limiting reduz abuso por volume (força bruta, scraping, negação de serviço leve) limitando requisições por janela de tempo, por IP, por token, por usuário ou por rota. Em testes básicos, você valida que existe algum mecanismo e que a resposta ao exceder limite é adequada.
O que validar
- Endpoints sensíveis (login, reset de senha, envio de código, busca pesada) têm limites mais restritivos.
- Ao exceder o limite, a API retorna
429 Too Many Requests. - Se houver headers de rate limit, eles são consistentes (ex.:
Retry-Afterquando aplicável).
Passo a passo prático
- Escolha um endpoint alvo (ex.:
POST /auth/loginou uma rota de busca). - Dispare uma sequência de requisições em curto intervalo (mesmo token/IP).
- Registre em qual requisição começa a bloquear.
- Verifique se após aguardar o tempo indicado o acesso volta ao normal.
# Pseudofluxo de teste for i in 1..N: POST /auth/login (credenciais inválidas) esperar 100msRespostas esperadas (seguras)
429com mensagem genérica (ex.: “limite excedido”).- Opcional:
Retry-Afterindicando quando tentar novamente. - Sem revelar regras internas detalhadas (ex.: “seu limite é 37 req/min”).
CORS quando aplicável (APIs consumidas por browser)
CORS (Cross-Origin Resource Sharing) é relevante quando a API é chamada diretamente por aplicações web no navegador. O objetivo é permitir origens confiáveis e bloquear origens não autorizadas. Em testes, você valida se a política não é permissiva demais.
O que validar
- Não usar
Access-Control-Allow-Origin: *em endpoints que aceitam credenciais (cookies/authorization via browser), quando isso for aplicável ao cenário. - Restringir origens a uma lista conhecida (ex.: domínio do front-end).
- Preflight (
OPTIONS) responde de forma consistente, sem abrir métodos/headers desnecessários.
Passo a passo prático
- Faça uma requisição simulando origem confiável com header
Origin. - Repita com uma origem não confiável (ex.:
https://evil.example). - Para rotas que exigem preflight, envie
OPTIONScomAccess-Control-Request-MethodeAccess-Control-Request-Headers.
# Preflight (exemplo) OPTIONS /profile Origin: https://evil.example Access-Control-Request-Method: GET Access-Control-Request-Headers: AuthorizationRespostas esperadas (seguras)
- Para origem não permitida: ausência de
Access-Control-Allow-Origin(ou valor diferente do enviado), impedindo o browser de liberar a resposta para o script. - Não liberar métodos/headers além do necessário.
Política de headers sensíveis e vazamento de informações
Além do corpo da resposta, headers podem vazar informações ou permitir comportamentos inseguros. Em testes básicos, você checa se a API evita expor detalhes internos e aplica headers de segurança quando aplicável.
O que checar em respostas
- Não expor versão/tecnologia: evitar headers como
Serverdetalhado ouX-Powered-By(ou ao menos minimizar). - Não retornar tokens/segredos em headers por engano.
- Não refletir input do usuário em headers sem sanitização.
Headers de segurança (quando a API é acessada por browsers)
Strict-Transport-Security(HSTS) quando o domínio é exclusivamente HTTPS.Cache-Control: no-storepara respostas com dados sensíveis (ex.: perfil, tokens, extratos).Pragma: no-cacheeExpirescoerentes (legado, quando aplicável).
Passo a passo prático
- Escolha endpoints que retornam dados sensíveis (perfil, dados financeiros, tokens de sessão, reset de senha).
- Verifique headers de cache: dados sensíveis não devem ser cacheados por intermediários.
- Inspecione se há headers que revelam stack/infra.
| Verificação | Exemplo de risco | Resultado esperado |
|---|---|---|
| Cache de resposta | Resposta com PII cacheável | Cache-Control: no-store (quando aplicável) |
| Exposição de tecnologia | X-Powered-By: Express | Ausente ou genérico |
| Vazamento em erro | Stack trace no body | Erro controlado e genérico |
Como observar “respostas seguras” em casos negativos
Ao executar testes negativos (acesso indevido, payloads maliciosos, excesso de requisições), avalie não apenas o status code, mas a qualidade do erro e o que ele revela.
Checklist de resposta segura
- Status code coerente com o cenário (ex.:
403/404para acesso negado,400/422para input inválido,429para limite excedido). - Mensagem curta e genérica, sem detalhes de implementação.
- Sem dados sensíveis no body (IDs internos, e-mails de terceiros, tokens, segredos).
- Sem stack trace, sem SQL/NoSQL query, sem caminhos de arquivo.
- Consistência: o mesmo tipo de falha deve produzir o mesmo formato de erro.
Modelo de casos negativos (para você replicar)
- Acesso por recurso: “usuário B tenta alterar recurso do usuário A”.
- IDOR: “trocar o ID na URL e tentar ler/baixar”.
- Input: “inserir payload de injeção em um campo por vez”.
- Rate limit: “enviar N requisições em janela curta até obter 429”.
- CORS: “simular Origin não permitido e validar ausência de allow”.
- Headers: “validar no-store para dados sensíveis e ausência de headers reveladores”.