APIs Aren’t Standard HTTP

Modern applications expose attack surface that doesn’t look like a form with GET parameters. GraphQL endpoints accept JSON queries with arbitrary depth. gRPC services use binary framing over HTTP/2. WebSocket handshakes have their own CORS model. Cache poisoning depends on header handling at the CDN layer, not application logic.

Standard fuzzing tools built for form fields and query strings miss all of this. Eight tools cover the API surface specifically.


mg-graphql: Introspection and Schema Analysis

mg-graphql target-bounty

The tool starts by detecting GraphQL endpoints from the crawl corpus and common paths (/graphql, /api/graphql, /query). For each candidate, it sends an introspection query:

{ __schema { queryType { name } types { name fields { name } } } }

A successful introspection response means the schema is fully enumerable. The tool extracts all types and fields, then flags dangerous mutations by name pattern: deleteUser, resetPassword, createAdmin, updatePermissions. These are HIGH candidates for testing.

Two additional checks run against the schema: query batching (sending an array of query objects in a single request, which can bypass per-query rate limits) and depth limit absence (sending a deeply nested query like { user { friends { friends { friends { ... } } } } } to check whether the server enforces query depth limits, which mitigates DoS via complex queries).

If introspection is disabled, the tool falls back to field guessing from common type names.


mg-openapi: Spec-Driven Endpoint Testing

mg-openapi target-bounty --spec https://target.example.com/openapi.json

The tool parses JSON OpenAPI specs and builds minimal valid requests for each endpoint defined in the spec. For each operation, it constructs a request with placeholder values: numeric parameters get 1, string parameters get "test", booleans get true.

The --unauthenticated flag replays the same set of requests without auth headers. Endpoints that return 200 without authentication when they should require it are flagged as BROKEN_ACCESS_CONTROL findings.

Required parameters are included; optional parameters are omitted unless they suggest interesting behavior by name. The tool doesn’t attempt to find the spec automatically beyond common paths — provide the spec URL directly.


mg-grpc: Service Reflection and Unauthenticated Calls

mg-grpc target-bounty --host grpc.target.example.com:443

gRPC uses HTTP/2 with a specific framing format: a 1-byte compression flag followed by a 4-byte big-endian message length, then the protobuf message body. The tool constructs these frames manually using reqwest with http2_prior_knowledge for cleartext or standard TLS ALPN negotiation for encrypted transport.

Server reflection is attempted first. If the server implements the gRPC reflection service, the tool enumerates all services and methods. For each method discovered, it sends an empty request body (valid protobuf: no fields set) and records the response. Methods that return data instead of UNIMPLEMENTED or UNAUTHENTICATED are flagged as potentially accessible without credentials.

Without reflection support, method names must be provided manually with --service and --method.


mg-websocket: CSWSH and Payload Fuzzing

mg-websocket target-bounty

WebSocket connection handling has its own CORS model. Unlike XHR and fetch, browsers don’t enforce CORS preflight for WebSocket upgrade requests — the server is responsible for validating the Origin header.

mg-websocket attempts a WebSocket handshake with Origin: https://attacker.example.com using tokio-tungstenite. A 101 Switching Protocols response with that Origin means Cross-Site WebSocket Hijacking is possible — an attacker can read WebSocket messages from a victim’s session by loading a malicious page.

Optional fuzz mode sends common payloads after a successful handshake:

mg-websocket target-bounty --fuzz

Payloads include XSS strings, SQL injection, JSON with special characters, and oversized messages. Response content and any server-side errors are recorded.


mg-cors-exploit: Origin Reflection Testing

mg-cors-exploit target-bounty

Four Origin header values are tested against every HTTP endpoint: a random subdomain of the target domain, https://attacker.example.com, the null origin (sent by sandboxed iframes), and a pre-domain variant (https://attacker.target.example.com).

The exploitable condition requires both headers in the response: Access-Control-Allow-Origin reflecting the injected origin AND Access-Control-Allow-Credentials: true. Without credentials, CORS reflection is informational. With credentials, an attacker can make authenticated requests from a foreign origin and read the response — reading session data, user info, or any authenticated API response.

This shares logic with mg-probe’s CORS check but runs a broader origin test matrix against the full endpoint list rather than just the root path.


mg-cache-poison: Unkeyed Header Injection

mg-cache-poison target-bounty

Cache poisoning requires a cache to be present. The tool first confirms this by looking for cache indicator headers in responses: Age, X-Cache, CF-Cache-Status, Via. Endpoints without these headers are skipped.

The attack pattern is two requests. First: inject a value into an unkeyed header (X-Forwarded-Host, X-Forwarded-For, X-Original-URL) and request the page. Second: request the same page without the injected header. If the second response reflects the injected value, the response was served from cache with the poisoned content.

The most impactful finding is X-Forwarded-Host reflected in a Location redirect or in an absolute URL in the response body — this allows serving the cached response to other users with attacker-controlled URLs embedded.


mg-proto-pollute: Prototype Pollution

mg-proto-pollute target-bounty

Prototype pollution targets JavaScript applications that merge user-controlled objects into application state without sanitizing __proto__ or constructor keys.

For POST endpoints, the tool injects {"__proto__":{"polluted":true}} into the request body. For GET endpoints, it adds ?__proto__[polluted]=true to the URL.

Detection is behavioral: a 500 response where there was a 200, or a response body change, suggests the pollution caused an error in the application. Definitive confirmation requires controlled execution context, which the tool flags as requiring manual verification.


mg-deser: Deserialization Artifact Detection

mg-deser target-bounty

mg-deser scans the crawl corpus for serialized object artifacts, then tests injectable endpoints.

Java: magic bytes 0xaced 0x0005 in any crawled response indicate Java deserialization. This triggers manual review — Java deserialization gadget chains can achieve RCE when a vulnerable library is on the classpath.

PHP: patterns matching PHP’s serialization format (O:, a:, s:) in responses or parameters. The tool sends a harmless O:8:"stdClass":0:{} payload to relevant endpoints and checks for 500 responses that suggest the server is attempting to deserialize the input.

Python pickle: magic bytes \x80\x04\x95 or \x80\x03 in responses indicate pickled data. Pickle deserialization of attacker-controlled input is arbitrary code execution.

Findings from mg-deser are flagged as requiring manual exploitation confirmation, not as confirmed RCE. The detection is reliable; the impact verification is manual.


Combining API Tests

GraphQL and OpenAPI specs discovered during crawling feed directly into mg-graphql and mg-openapi. gRPC services appear in port scan output with TLS ALPN indicating h2. WebSocket endpoints are found in the crawl link graph. The API surface tools pick up where the standard HTTP testing tools leave off, covering the protocol and format variations that parameter fuzzing doesn’t reach.