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,525 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- API 参数 Hook 模块
5
-
6
- 使用 Playwright 在浏览器中 Hook API 调用,获取真实参数:
7
- 1. Hook XMLHttpRequest / Fetch / axios
8
- 2. 记录每次 API 调用的 URL、方法、参数
9
- 3. 分析参数语义(如 password、username 等)
10
- 4. 识别潜在的安全测试点
11
-
12
- 使用方式:
13
- from core.api_interceptor import APIInterceptor
14
-
15
- interceptor = APIInterceptor('http://target.com')
16
- results = interceptor.hook_all_apis()
17
- """
18
-
19
- import re
20
- import sys
21
- from typing import Dict, List, Set, Optional, Any
22
- from dataclasses import dataclass, field
23
- from datetime import datetime
24
-
25
- sys.path.insert(0, '/workspace/skill-play/API-Security-Testing-Optimized')
26
-
27
-
28
- @dataclass
29
- class HookedAPI:
30
- """Hook 到的 API 调用"""
31
- url: str
32
- method: str
33
- params: Dict[str, Any] = field(default_factory=dict)
34
- body: Any = None
35
- function_name: str = ""
36
- stack_trace: str = ""
37
- timestamp: float = 0
38
-
39
- # 分析结果
40
- semantic_type: str = "" # login, reset_password, user_query, etc.
41
- is_sensitive: bool = False
42
- test_vectors: List[Dict] = field(default_factory=list)
43
-
44
-
45
- class APIInterceptor:
46
- """
47
- API 参数 Hook 器
48
-
49
- 在浏览器中注入 JavaScript 代码来 Hook 所有 API 调用
50
- """
51
-
52
- def __init__(self, target: str, headless: bool = True):
53
- self.target = target
54
- self.headless = headless
55
- self.hooked_apis: List[HookedAPI] = []
56
- self._page = None
57
-
58
- # 敏感操作模式
59
- self.sensitive_patterns = {
60
- 'password': ['password', 'passwd', 'pwd', 'secret'],
61
- 'auth': ['login', 'logout', 'auth', 'token', 'credential'],
62
- 'user': ['user', 'profile', 'account', 'avatar'],
63
- 'admin': ['admin', 'manage', 'system'],
64
- 'reset': ['reset', 'forgot', 'recovery'],
65
- 'delete': ['delete', 'remove', 'destroy'],
66
- 'payment': ['pay', 'order', 'transaction', 'money'],
67
- }
68
-
69
- # 可测试的操作模式
70
- self.testable_patterns = [
71
- ('reset_password', 'password reset'),
72
- ('forgot_password', 'password recovery'),
73
- ('change_password', 'password change'),
74
- ('delete_account', 'account deletion'),
75
- ('modify_user', 'user modification'),
76
- ('admin_user', 'admin user management'),
77
- ]
78
-
79
- def hook_all_apis(self, interactions: List[str] = None) -> Dict:
80
- """
81
- Hook 所有 API 调用
82
-
83
- Args:
84
- interactions: 要执行的交互列表
85
-
86
- Returns:
87
- {
88
- 'total': 100,
89
- 'apis': [...],
90
- 'sensitive': [...],
91
- 'testable': [...],
92
- 'test_vectors': [...]
93
- }
94
- """
95
- print(f" [API Hook] 启动 Hook 器")
96
- print(f" [API Hook] 目标: {self.target}")
97
-
98
- results = {'total': 0, 'apis': [], 'sensitive': [], 'testable': [], 'test_vectors': []}
99
-
100
- try:
101
- from playwright.sync_api import sync_playwright
102
-
103
- with sync_playwright() as p:
104
- browser = p.chromium.launch(headless=self.headless)
105
- context = browser.new_context(
106
- viewport={'width': 1920, 'height': 1080},
107
- ignore_https_errors=True
108
- )
109
-
110
- hook_script = """
111
- (function() {
112
- window.__API_CALLS__ = [];
113
- var origFetch = window.fetch;
114
- window.fetch = function() {
115
- var args = arguments;
116
- var url = args[0] || '';
117
- var options = args[1] || {};
118
- window.__API_CALLS__.push({
119
- type: 'fetch',
120
- method: (options.method || 'GET').toUpperCase(),
121
- url: url
122
- });
123
- return origFetch.apply(window, args);
124
- };
125
- var OrigXHR = window.XMLHttpRequest;
126
- window.XMLHttpRequest = function() {
127
- var xhr = new OrigXHR();
128
- xhr.open = function() {
129
- this.__method = arguments[0];
130
- this.__url = arguments[1];
131
- return OrigXHR.prototype.open.apply(this, arguments);
132
- };
133
- xhr.send = function() {
134
- this.__data = arguments[0];
135
- var self = this;
136
- this.addEventListener('load', function() {
137
- window.__API_CALLS__.push({
138
- type: 'xhr',
139
- method: self.__method || 'GET',
140
- url: self.__url || '',
141
- data: self.__data || ''
142
- });
143
- });
144
- return OrigXHR.prototype.send.apply(this, arguments);
145
- };
146
- return xhr;
147
- };
148
- console.log('[Hook] API Hook 已启动');
149
- })();
150
- """
151
-
152
- context.add_init_script(hook_script)
153
-
154
- page = context.new_page()
155
- self._page = page
156
-
157
- print(f" [API Hook] 访问目标...")
158
- page.goto(self.target, wait_until='networkidle', timeout=30000)
159
- page.wait_for_timeout(3000)
160
-
161
- self._execute_interactions()
162
-
163
- results = self._process_results()
164
-
165
- browser.close()
166
-
167
- except Exception as e:
168
- print(f" [API Hook] 失败: {e}")
169
-
170
- print(f" [API Hook] 捕获 {results['total']} 个 API 调用")
171
- print(f" [API Hook] 发现 {len(results.get('sensitive', []))} 个敏感操作")
172
-
173
- return results
174
-
175
- def _inject_hook_code(self):
176
- """注入 Hook 代码到页面"""
177
-
178
- # 简化的 Hook 代码
179
- hook_code = """
180
- (function() {
181
- if (window.__HOOKED__) return;
182
- window.__HOOKED__ = true;
183
- window.__API_CALLS__ = [];
184
-
185
- // Hook fetch
186
- var origFetch = window.fetch;
187
- window.fetch = function() {
188
- var args = arguments;
189
- var url = args[0] || '';
190
- var options = args[1] || {};
191
-
192
- window.__API_CALLS__.push({
193
- type: 'fetch',
194
- method: (options.method || 'GET').toUpperCase(),
195
- url: url,
196
- timestamp: Date.now()
197
- });
198
-
199
- return origFetch.apply(this, args);
200
- };
201
-
202
- // Hook XMLHttpRequest
203
- var origXHR = window.XMLHttpRequest;
204
- window.XMLHttpRequest = function() {
205
- var xhr = new origXHR();
206
- var origOpen = xhr.open;
207
- var origSend = xhr.send;
208
-
209
- xhr.open = function() {
210
- this.__method = arguments[0];
211
- this.__url = arguments[1];
212
- return origOpen.apply(this, arguments);
213
- };
214
-
215
- xhr.send = function() {
216
- this.__data = arguments[0];
217
- var self = this;
218
- this.addEventListener('load', function() {
219
- window.__API_CALLS__.push({
220
- type: 'xhr',
221
- method: self.__method || 'GET',
222
- url: self.__url || '',
223
- data: self.__data || '',
224
- timestamp: Date.now()
225
- });
226
- });
227
- return origSend.apply(this, arguments);
228
- };
229
-
230
- return xhr;
231
- };
232
-
233
- console.log('[Hook] API Hook 已启动');
234
- })();
235
- """
236
-
237
- self._page.evaluate(hook_code)
238
-
239
- def _execute_interactions(self):
240
- """执行交互操作触发 API 调用"""
241
- print(f" [API Hook] 执行交互...")
242
-
243
- # 1. 填写表单
244
- try:
245
- inputs = self._page.query_selector_all('input')
246
- for i, inp in enumerate(inputs[:10]):
247
- try:
248
- inp.fill(f'test_value_{i}')
249
- self._page.wait_for_timeout(300)
250
- except:
251
- pass
252
- except:
253
- pass
254
-
255
- # 2. 点击按钮
256
- try:
257
- buttons = self._page.query_selector_all('button')
258
- for btn in buttons[:10]:
259
- try:
260
- btn.click()
261
- self._page.wait_for_timeout(500)
262
- except:
263
- pass
264
- except:
265
- pass
266
-
267
- # 3. 导航
268
- routes = ['#/login', '#/home', '#/admin', '#/profile']
269
- for route in routes:
270
- try:
271
- self._page.goto(self.target + route, timeout=10000)
272
- self._page.wait_for_timeout(2000)
273
- except:
274
- pass
275
-
276
- def _process_results(self) -> Dict:
277
- """处理 Hook 结果"""
278
-
279
- # 获取 Hook 到的调用
280
- raw_calls = self._page.evaluate('window.__API_CALLS__ || []') if self._page else []
281
-
282
- apis = []
283
- sensitive = []
284
- testable = []
285
- test_vectors = []
286
-
287
- for call in raw_calls:
288
- url = call.get('url', '')
289
- method = call.get('method', 'GET').upper()
290
- data = call.get('data', {})
291
- params = call.get('params', {})
292
-
293
- # 只处理目标域名的 API
294
- target_host = self.target.replace('http://', '').replace('https://', '').split('/')[0]
295
- if target_host not in url:
296
- continue
297
-
298
- # 提取路径
299
- path = url.replace(f'http://{target_host}', '').split('?')[0]
300
-
301
- # 解析参数
302
- parsed_params = self._parse_params(data, params)
303
-
304
- # 创建 HookedAPI 对象
305
- api = HookedAPI(
306
- url=url,
307
- method=method,
308
- params=parsed_params,
309
- body=data,
310
- semantic_type=self._infer_semantic_type(path, method)
311
- )
312
-
313
- # 检测敏感操作
314
- if self._is_sensitive_operation(path, method):
315
- api.is_sensitive = True
316
- sensitive.append(api)
317
-
318
- # 生成测试向量
319
- vectors = self._generate_test_vectors(api)
320
- api.test_vectors = vectors
321
- test_vectors.extend(vectors)
322
-
323
- # 检测可测试操作
324
- if self._is_testable_operation(path):
325
- testable.append(api)
326
-
327
- apis.append(api)
328
-
329
- return {
330
- 'total': len(apis),
331
- 'apis': [a.url for a in apis],
332
- 'sensitive': [{'url': a.url, 'method': a.method, 'semantic': a.semantic_type} for a in sensitive],
333
- 'testable': [{'url': a.url, 'method': a.method, 'semantic': a.semantic_type} for a in testable],
334
- 'test_vectors': test_vectors,
335
- 'hooked_apis': apis,
336
- }
337
-
338
- def _parse_params(self, data: Any, params: Any) -> Dict:
339
- """解析参数"""
340
- result = {}
341
-
342
- if isinstance(data, dict):
343
- result.update(data)
344
- elif isinstance(data, str):
345
- try:
346
- result = json.loads(data) if data else {}
347
- except:
348
- # URL encoded
349
- for pair in data.split('&'):
350
- if '=' in pair:
351
- k, v = pair.split('=', 1)
352
- result[k] = v
353
-
354
- if isinstance(params, dict):
355
- result.update(params)
356
-
357
- return result
358
-
359
- def _infer_semantic_type(self, path: str, method: str) -> str:
360
- """推断语义类型"""
361
- path_lower = path.lower()
362
-
363
- if 'login' in path_lower or 'signin' in path_lower:
364
- return 'login'
365
- if 'reset' in path_lower and 'pass' in path_lower:
366
- return 'reset_password'
367
- if 'forgot' in path_lower or 'recovery' in path_lower:
368
- return 'forgot_password'
369
- if 'logout' in path_lower:
370
- return 'logout'
371
- if 'profile' in path_lower:
372
- return 'user_profile'
373
- if 'avatar' in path_lower:
374
- return 'avatar_upload'
375
- if 'user' in path_lower and ('add' in path_lower or 'create' in path_lower):
376
- return 'create_user'
377
- if 'user' in path_lower and ('delete' in path_lower or 'remove' in path_lower):
378
- return 'delete_user'
379
- if 'user' in path_lower and ('modify' in path_lower or 'update' in path_lower or 'edit' in path_lower):
380
- return 'modify_user'
381
- if 'password' in path_lower or 'passwd' in path_lower:
382
- return 'password_operation'
383
- if 'admin' in path_lower:
384
- return 'admin_operation'
385
-
386
- return 'general'
387
-
388
- def _is_sensitive_operation(self, path: str, method: str) -> bool:
389
- """判断是否为敏感操作"""
390
- path_lower = path.lower()
391
-
392
- sensitive_keywords = [
393
- 'password', 'passwd', 'pwd',
394
- 'login', 'logout', 'auth',
395
- 'reset', 'forgot', 'recovery',
396
- 'credit', 'card', 'payment', 'money',
397
- 'private', 'secret', 'key',
398
- ]
399
-
400
- for keyword in sensitive_keywords:
401
- if keyword in path_lower:
402
- return True
403
-
404
- # 危险方法
405
- if method in ['POST', 'PUT', 'DELETE'] and any(k in path_lower for k in ['user', 'admin', 'password', 'auth']):
406
- return True
407
-
408
- return False
409
-
410
- def _is_testable_operation(self, path: str) -> bool:
411
- """判断是否可测试"""
412
- path_lower = path.lower()
413
-
414
- testable_keywords = [
415
- 'reset', 'forgot', 'recovery',
416
- 'password', 'passwd',
417
- 'delete', 'remove',
418
- 'admin', 'manage',
419
- 'user', 'profile',
420
- 'modify', 'update', 'edit',
421
- 'upload', 'download',
422
- ]
423
-
424
- return any(keyword in path_lower for keyword in testable_keywords)
425
-
426
- def _generate_test_vectors(self, api: HookedAPI) -> List[Dict]:
427
- """生成测试向量"""
428
- vectors = []
429
- path = api.url.lower()
430
- method = api.method.upper()
431
- params = api.params
432
-
433
- # 1. 未授权访问测试
434
- if method in ['GET', 'POST', 'PUT', 'DELETE']:
435
- vectors.append({
436
- 'type': 'unauthorized_access',
437
- 'url': api.url,
438
- 'method': method,
439
- 'description': f'测试未授权访问 {path}',
440
- 'expected': '应该返回 401/403 或需要认证',
441
- })
442
-
443
- # 2. 参数篡改测试
444
- if params:
445
- for param_name in list(params.keys())[:3]:
446
- vectors.append({
447
- 'type': 'parameter_tampering',
448
- 'url': api.url,
449
- 'method': method,
450
- 'param': param_name,
451
- 'description': f'篡改参数 {param_name}',
452
- 'test_value': 'admin\' OR \'1\'=\'1',
453
- })
454
-
455
- # 3. 密码重置相关测试
456
- if 'reset' in path and 'password' in path:
457
- vectors.append({
458
- 'type': 'password_reset_bypass',
459
- 'url': api.url,
460
- 'method': method,
461
- 'description': '测试任意密码重置',
462
- 'test_vectors': [
463
- {'user_id': '1', 'new_password': 'hacked123'},
464
- {'username': 'admin', 'token': 'fake_token'},
465
- {'email': 'admin@test.com'},
466
- ]
467
- })
468
-
469
- # 4. 用户操作测试
470
- if 'user' in path or 'admin' in path:
471
- if method == 'DELETE':
472
- vectors.append({
473
- 'type': 'idor',
474
- 'url': api.url,
475
- 'method': method,
476
- 'description': '测试 IDOR - 任意用户删除',
477
- 'test_ids': [1, 2, 3, 'admin'],
478
- })
479
- elif method == 'PUT' or 'post' in method.lower():
480
- vectors.append({
481
- 'type': 'privilege_escalation',
482
- 'url': api.url,
483
- 'method': method,
484
- 'description': '测试权限提升',
485
- 'test_role': 'admin',
486
- })
487
-
488
- return vectors
489
-
490
-
491
- def run_api_hook(target: str) -> Dict:
492
- """运行 API Hook"""
493
- print("=" * 60)
494
- print("API Hook - 参数提取与安全测试")
495
- print("=" * 60)
496
-
497
- interceptor = APIInterceptor(target)
498
- results = interceptor.hook_all_apis()
499
-
500
- print("\n" + "=" * 60)
501
- print("Hook 结果")
502
- print("=" * 60)
503
- print(f"总 API 调用: {results['total']}")
504
- print(f"敏感操作: {len(results['sensitive'])}")
505
- print(f"可测试操作: {len(results['testable'])}")
506
- print(f"测试向量: {len(results['test_vectors'])}")
507
-
508
- if results['sensitive']:
509
- print("\n敏感操作:")
510
- for s in results['sensitive'][:10]:
511
- print(f" [{s['method']}] {s['url']} ({s['semantic']})")
512
-
513
- if results['test_vectors']:
514
- print("\n测试向量示例:")
515
- for tv in results['test_vectors'][:5]:
516
- print(f" [{tv['type']}] {tv['method']} {tv['url']}")
517
- print(f" {tv['description']}")
518
-
519
- return results
520
-
521
-
522
- if __name__ == "__main__":
523
- import sys
524
- target = sys.argv[1] if len(sys.argv) > 1 else "http://58.215.18.57:91"
525
- run_api_hook(target)