Docs / Web application pentesting / API Pentesting --- REST, GraphQL, OpenAPI and Cloud Web
GitHub

Web application pentesting

API Pentesting --- REST, GraphQL, OpenAPI and Cloud Web

Why APIs deserve a dedicated chapter

Modern applications expose business logic via JSON, GraphQL and microservices. The OWASP API Security Top 10 (2023) lists specific risks: broken object-level access control (BOLA), broken authentication, excessive resource consumption, injection at the business logic layer. Classic web scanners (HTML crawling) often miss these surfaces.

KittySploit addresses this gap through:

  • dedicated scanner/http/ modules (graphql_detect, swagger_detect);
  • a generic API fuzzer (auxiliary/scanner/http/api_fuzzer);
  • the api_import command to transform schemas or traffic into modules;
  • the agent with the api-review profile and HTTP intelligence (api_surface_detected).

Preparing the API workspace

workspace create api-review
workspace use api-review
scope add api.target.local
host add api.target.local

If the target is local with a self-signed certificate:

http https://api.target.local/health -k -I

The -k (--insecure) option disables TLS verification --- reserved for isolated test environment use.

Swagger and OpenAPI detection

Module scanner/http/swagger_detect

The module probes a list of common paths:

use scanner/http/swagger_detect
set rhost api.target.local
set rport 443
set ssl true
run

Paths tested (excerpt from source code modules/scanner/http/swagger_detect.py): /swagger, /swagger.json, /swagger-ui.html, /api-docs, /v2/api-docs, /v3/api-docs, /openapi.json, /openapi.yaml.

A low finding signals documentation disclosure: often critical in production (complete enumeration of operations) but expected in isolated test environment to accelerate testing.

Targeted mass scan for the API

scanner -u https://api.target.local --module swagger_detect -k
scanner -u https://api.target.local --tags api,swagger --threads 3
search swagger --type scanner --protocol http

Retrieving the schema

Once the path is found (e.g.\ /v3/api-docs):

http https://api.target.local/v3/api-docs -k -o /tmp/openapi.json
http https://api.target.local/swagger.json -k

Verify the JSON/YAML format before import.

GraphQL detection

Module scanner/http/graphql_detect

use scanner/http/graphql_detect
set rhost api.target.local
set rport 443
set ssl true
run

Probed paths: /graphql, /graphiql, /api/graphql, /query, /v1/graphql, /altair. The module attempts introspection:

POST {"query": "{ __schema { types { name } } }"}

Response 200 with data or __schema indicates active introspection.

Typical GraphQL risks

  • Open introspection --- complete map of the schema;
  • Depth / complexity --- DoS via nested queries;
  • BOLA --- access to another user's user(id:) via mutations;
  • Injection --- arguments passed to SQL or OS without sanitization.

Manual testing with http

http https://api.target.local/graphql -k -X POST \
  -H "Content-Type: application/json" \
  -j '{"query":"{ __typename }"}'

http https://api.target.local/graphql -k -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN_LAB" \
  -j '{"query":"{ users { id email } }"}'

API fuzzing with api_fuzzer

Loading the module

use auxiliary/scanner/http/api_fuzzer
set rhost api.target.local
set rport 443
set ssl true
show options
run

The module tests dozens of API paths (/api/v1, /rest, /oauth, /health…) and multiple HTTP methods (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD, TRACE). It applies fuzzing payloads to parameters and JSON bodies.

Prudent configuration

set threads 5
set timeout 10
run

Reduce threads on a fragile backend. Watch for 429 (rate limit) and 503 codes.

Interpreting results

  • 200/201 on /admin without auth indicates access control failure (OWASP API1).
  • 500 with stack trace indicates misconfiguration or information leakage.
  • 405 vs 401 --- distinguish forbidden method from protected resource.
  • Discovered endpoints --- feed api_import or manual tests.

The api_import command

Role and inputs

api_import generates KittySploit modules (scanner, fuzzer) from:
  • OpenAPI/Swagger specifications (JSON or YAML);
  • GraphQL introspection responses (JSON);
  • captured traffic: HAR, KittyProxy JSON, HTTP request list.

Implementation: interfaces/command_system/builtin/api_import_command.py, engine core/api_module_generator/generator.py.

Syntax

api_import <schema_or_traffic_file> [--type auto|openapi|graphql|traffic]
api_import openapi.json
api_import graphql-introspection.json --type graphql --name internal_graphql
api_import kittyproxy_traffic.har --type traffic --kind scanner --force

Important options:

  • --type auto --- automatic format detection;
  • --name --- pack name (e.g.\ internal_graphql);
  • --kind scanner,fuzzer --- generated module types;
  • --module-dir --- default modules/generated/api;
  • --artifact-dir --- default artifacts/api_module_packs;
  • --preview --- normalized inventory without writing files;
  • --force --- overwrite existing modules.

Preview then generation workflow

api_import /tmp/openapi.json --preview
api_import /tmp/openapi.json --name lab_rest_api --kind scanner,fuzzer

Expected output: files in modules/generated/api/, manifest in artifacts/api_module_packs/, unit tests under .../tests.

python -m unittest discover -s artifacts/api_module_packs/<pack>/tests

Import from KittyProxy traffic

  1. proxy start; browse the SPA application that consumes the API.
  2. Export the HAR or flow JSON.
  3. api_import capture.har --type traffic --name spa_traffic.
  4. Run the generated scanner against the isolated test target.

This workflow reconstructs an API surface that Swagger does not document (internal endpoints, deprecated versions).

REST testing with the http command

Overview

http (interfaces/command_system/builtin/http_command.py) sends HTTP requests from the CLI, curl-style. It respects the framework proxy (KittyProxy, Tor) if configured.

Essential options

-H / --headerHeader Key: Value (repeatable)
-d / --dataRaw body
-j / --jsonJSON body (automatic Content-Type)
-k / --insecureIgnore TLS certificate errors
-L / --locationFollow redirects
-I / --headHEAD request
-i / --includeDisplay response headers
-o / --outputWrite body to a file
--proxyOne-off proxy for this request
-A / --user-agentCustom User-Agent

Common REST cases

Bearer authentication:
http https://api.target.local/v1/users -k \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Resource creation:
http https://api.target.local/v1/items -k -X POST \
  -H "Authorization: Bearer TOKEN" \
  -j '{"name":"test-isolated test environment","qty":1}'
BOLA test (IDOR):
http https://api.target.local/v1/orders/1001 -k \
  -H "Authorization: Bearer TOKEN_USER_A"
http https://api.target.local/v1/orders/1002 -k \
  -H "Authorization: Bearer TOKEN_USER_A"

If a 200 response on 1002 reveals another user's data, document API1 (BOLA) with both requests as evidence.

Dangerous verbs (explicit engagement scope):
http https://api.target.local/v1/items/999 -k -X DELETE \
  -H "Authorization: Bearer TOKEN_LAB"

Chain with scanners

scanner -u https://api.target.local --module swagger_detect -k
http https://api.target.local/v3/api-docs -k -o /tmp/spec.json
api_import /tmp/spec.json --name lab_api
search lab_api
set rhost api.target.local
set ssl true
run

The generated module path is created under modules/generated/api/ and depends on the import name.

OWASP API Security and KittySploit modules

API#OWASP API riskKittySploit approach
API2Broken authhttp without token; invalid JWTs; api_fuzzer on /auth
API3Excessive data exposureGraphQL introspection; verbose JSON responses
API4Resource consumptionlimit threads; manual pagination tests
API5BFLAhttp -X POST on admin routes with standard user token
API6Business flowagent + manual review (beyond generic scan)
API7SSRFHTTP SSRF modules if API triggers URL fetch
API8Misconfigurationswagger_detect, exposed_env_detect
API9Inventoryapi_import + client documentation
API10Unsafe APIsinput validation via fuzzer and manual tests

Browser server and client-side API surfaces

browser_server command

The browser exploitation server (core/browser_server.py, browser_server start) records browser sessions and injects a control script (BeEF-like mode). For API pentesting, the main interest is capture of application traffic: an SPA loaded in the instrumented browser generates /api/... calls visible via browser_server sessions and exportable to api_import --type traffic.

browser_server start --host 127.0.0.1 --port 3000
browser_server status
browser_server inject
browser_server sessions

Hybrid web + API workflow

  1. Start browser_server and/or KittyProxy.
  2. Load the web application that consumes the API.
  3. Collect XHR/fetch requests.
  4. api_import on the traffic; complement with OpenAPI if available.
  5. Targeted http tests on undocumented endpoints.

KittySploit agent --- api-review profile

Profile definition

The api-review profile (interfaces/command_system/builtin/agent/mission_profiles.py) configures:

  • safety_profile: discreet;
  • approved_risks: [read, active];
  • request_budget: 30;
  • http_replay: safe;
  • description: ``API surface validation without destructive actions''.

Typical launch

agent https://api.target.local --profile api-review
agent https://api.target.local --profile api-review --goal "review REST and GraphQL"
agent https://api.target.local --profile api-review --plan-only
agent https://api.target.local --profile api-review --no-exploit

Combined with prior discovery:

scanner -u https://api.target.local --tags api --threads 3 -k
agent https://api.target.local --profile api-review --reuse-proxy-auth

Internal HTTP intelligence

The agent classifies requests with signals such as api_surface_detected, graphql_surface_detected or swagger_surface_detected. These signals, produced by http_intelligence.py, steer the plan toward graphql_detect, swagger_detect or generated modules.

Safeguards

  • --plan-only --- plan without execution;
  • --no-exploit --- no exploitation modules;
  • --request-budget N --- request ceiling;
  • custom TOML policy to forbid DELETE.

Cloud web integration (Firebase, actuators)

APIs are not always at /api/v1. KittySploit includes ``cloud web'' scanners:

use scanner/http/firebase_fingerprint_detect
set rhost api.target.local
set ssl true
run

use scanner/http/firebase_rtdb_public_access_detect
set rhost api.target.local
run

use scanner/http/spring_actuator_detect
set rhost api.target.local
set rport 443
set ssl true
run

An exposed Spring actuator (/actuator/env) equals an API configuration leak (secrets, internal URLs). Document as API8 (misconfiguration).

Complete methodology --- checklist

  1. Scope --- scope add, engagement letter, test accounts.
  2. Passive detection --- swagger_detect, graphql_detect.
  3. Schema collection --- http -o, client documentation.
  4. Import --- api_import --preview, then generation.
  5. Light fuzzing --- api_fuzzer with low threads.
  6. Manual tests --- BOLA, auth, validation with http.
  7. Agent --- --profile api-review --plan-only, human validation.
  8. Reporting --- vuln add, campaign --formats report.

Writing API findings

Each finding should contain:

  • endpoint and method (e.g.\ GET /v1/users/\{id\});
  • account used and proof of unauthorized access;
  • truncated JSON excerpt (no full dump);
  • OWASP API Top 10 reference;
  • remediation (object-level control, OAuth scopes, introspection disable).

Troubleshooting

  • api_import fails --- verify valid JSON; specify --type.
  • Generated modules not found --- sync now; path modules/generated/api.
  • 401 everywhere --- expired token; replay login via http.
  • GraphQL 400 --- Content-Type application/json; escape quotes in -j.
  • Agent exceeds budget --- increase --request-budget or split by subdomain.