Operator On The Wire
← Back to Knowledge Base
OOTW / Chapter III - Web / Fuzzing / Techniques

API

API fuzzing discovers routes, versions, methods, resources, actions, and schemas. We use it after basic directory fuzzing because /api, /graphql, /swagger, /openapi.json, and versioned prefixes often expose the real application logic behind a thin frontend.

Common API entry points:

/api
/api/v1
/api/v2
/graphql
/graphiql
/swagger
/swagger.json
/swagger-ui
/openapi.json
/docs
/redoc
/actuator

Find API roots:

ffuf -u http://127.0.0.1:5000/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
  -mc 200,204,301,302,307,401,403

If that list is unavailable, start with a small custom list:

printf "api\napi/v1\napi/v2\ngraphql\nswagger\nswagger.json\nopenapi.json\ndocs\nredoc\nactuator\n" > api-roots.txt

ffuf -u http://127.0.0.1:5000/FUZZ \
  -w api-roots.txt \
  -mc 200,204,301,302,307,401,403

Fuzz resources under an API prefix:

ffuf -u http://127.0.0.1:5000/api/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/api/objects.txt \
  -mc 200,204,301,302,307,401,403 \
  -fs 1234

Fuzz version prefixes:

printf "v1\nv2\nv3\nbeta\ninternal\nprivate\nadmin\n" > api-versions.txt

ffuf -u http://127.0.0.1:5000/api/FUZZ/users \
  -w api-versions.txt \
  -mc 200,204,301,302,307,401,403

Fuzz nested API actions:

ffuf -u http://127.0.0.1:5000/api/users/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt \
  -mc 200,204,301,302,307,401,403

Test HTTP methods:

for m in GET POST PUT PATCH DELETE OPTIONS; do
  echo "== $m =="
  curl -i -X "$m" http://127.0.0.1:5000/api/users
done

Use ffuf with JSON bodies:

ffuf -u http://127.0.0.1:5000/api/users \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"FUZZ"}' \
  -w /usr/share/seclists/Fuzzing/special-chars.txt \
  -mc all \
  -fs 1234

Use wfuzz for regex-based API success:

wfuzz -w api-objects.txt \
  --ss '"id"|"name"|"role"|"status"' \
  http://127.0.0.1:5000/api/FUZZ

Spider first, fuzz second:

katana -u http://127.0.0.1:5000/ -silent -jc -kf all -o urls.txt
grep -Ei '/api/|graphql|swagger|openapi' urls.txt | sort -u

API findings to test next:

IDOR on numeric IDs
mass assignment on JSON fields
SQLi in filters and sort keys
XSS in JSON rendered by frontend
SSTI where API data becomes templates
command injection in admin/operator actions
auth bypass on method changes
excessive data exposure

Notes

An API 401 or 403 can still be a valid finding. It confirms the route exists and gives us something to retest after authentication or role changes.

Always compare GET, POST, PUT, PATCH, DELETE, and OPTIONS where the application exposes API resources.