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,687 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Smart API Analyzer - 智能 API 分析器
4
- 参考 ApiRed + 渗透测试工程师思维
5
-
6
- 核心功能:
7
- 1. 从 JS 中精确提取后端 API (过滤前端路由)
8
- 2. 识别参数定义和类型
9
- 3. 智能分类 API 端点
10
- 4. 敏感信息挖掘
11
- 5. 基于理解生成精准 fuzzing 目标
12
- """
13
-
14
- import re
15
- import hashlib
16
- from typing import Dict, List, Set, Tuple, Optional, Any
17
- from dataclasses import dataclass, field
18
- from urllib.parse import urljoin, urlparse, parse_qs
19
- from enum import Enum
20
- import requests
21
-
22
-
23
- class EndpointType(Enum):
24
- """端点类型"""
25
- BACKEND_API = "backend_api" # 后端 API (有价值)
26
- FRONTEND_ROUTE = "frontend_route" # 前端路由 (无价值)
27
- STATIC_RESOURCE = "static" # 静态资源
28
- UNKNOWN = "unknown"
29
-
30
-
31
- class Sensitivity(Enum):
32
- """敏感等级"""
33
- CRITICAL = "critical"
34
- HIGH = "high"
35
- MEDIUM = "medium"
36
- LOW = "low"
37
- INFO = "info"
38
-
39
-
40
- @dataclass
41
- class ParsedParameter:
42
- """解析出的参数"""
43
- name: str
44
- param_type: str # path, query, body, json
45
- data_type: str # int, string, bool, object
46
- required: bool = False
47
- is_sensitive: bool = False
48
- source: str = "" # from_response, from_js, from猜测
49
-
50
-
51
- @dataclass
52
- class SmartEndpoint:
53
- """智能端点"""
54
- path: str
55
- method: str
56
- endpoint_type: EndpointType = EndpointType.UNKNOWN
57
- sensitivity: Sensitivity = Sensitivity.INFO
58
-
59
- # 解析出的信息
60
- base_url: str = ""
61
- parameters: List[ParsedParameter] = field(default_factory=list)
62
- request_body: Dict = field(default_factory=dict)
63
- response_pattern: str = ""
64
-
65
- # 来源
66
- source_file: str = ""
67
- source_line: int = 0
68
- confidence: float = 0.0
69
-
70
- # 分析结果
71
- is_auth_endpoint: bool = False
72
- is_admin_endpoint: bool = False
73
- is_user_data_endpoint: bool = False
74
- has_sensitive_params: bool = False
75
-
76
- def to_dict(self) -> Dict:
77
- return {
78
- 'path': self.path,
79
- 'method': self.method,
80
- 'type': self.endpoint_type.value,
81
- 'sensitivity': self.sensitivity.value,
82
- 'base_url': self.base_url,
83
- 'parameters': [{'name': p.name, 'type': p.param_type, 'sensitive': p.is_sensitive} for p in self.parameters],
84
- 'is_auth': self.is_auth_endpoint,
85
- 'is_admin': self.is_admin_endpoint,
86
- 'confidence': self.confidence,
87
- }
88
-
89
-
90
- @dataclass
91
- class SensitiveMatch:
92
- """敏感信息匹配"""
93
- data_type: str
94
- value: str
95
- severity: Sensitivity
96
- context: str
97
- source: str
98
-
99
-
100
- class SmartAPIAnalyzer:
101
- """
102
- 智能 API 分析器
103
-
104
- 核心思维:像渗透测试工程师一样思考
105
- 1. 先理解目标 - 识别技术栈和 API 结构
106
- 2. 精确提取 - 区分后端 API 和前端路由
107
- 3. 发现参数 - 从响应和代码中提取参数定义
108
- 4. 智能分类 - 按功能和安全影响分类
109
- 5. 精准 Fuzz - 基于理解生成目标
110
- """
111
-
112
- # 后端 API 特征
113
- BACKEND_API_PATTERNS = [
114
- r'/api/', r'/v\d+/', r'/rest/', r'/graphql',
115
- r'/auth/', r'/login', r'/logout', r'/token',
116
- r'/admin/', r'/manage/',
117
- r'/user/', r'/profile/', r'/account/',
118
- r'/data/', r'/file/', r'/upload/', r'/download/',
119
- r'/config/', r'/setting/', r'/sys/',
120
- ]
121
-
122
- # 前端路由特征 (需过滤)
123
- FRONTEND_ROUTE_PATTERNS = [
124
- r'chunk-[a-f0-9]+\.js',
125
- r'\.css', r'\.svg', r'\.png', r'\.jpg',
126
- r'/js/', r'/css/', r'/img/', r'/assets/',
127
- r'/dist/', r'/build/',
128
- r'/node_modules/',
129
- ]
130
-
131
- # 敏感关键字
132
- SENSITIVE_KEYWORDS = {
133
- 'password': Sensitivity.HIGH,
134
- 'passwd': Sensitivity.HIGH,
135
- 'secret': Sensitivity.HIGH,
136
- 'token': Sensitivity.MEDIUM,
137
- 'jwt': Sensitivity.MEDIUM,
138
- 'bearer': Sensitivity.MEDIUM,
139
- 'api_key': Sensitivity.HIGH,
140
- 'apikey': Sensitivity.HIGH,
141
- 'access_key': Sensitivity.HIGH,
142
- 'private_key': Sensitivity.CRITICAL,
143
- 'credential': Sensitivity.HIGH,
144
- 'auth': Sensitivity.MEDIUM,
145
- 'session': Sensitivity.MEDIUM,
146
- 'cookie': Sensitivity.MEDIUM,
147
- 'userid': Sensitivity.LOW,
148
- 'user_id': Sensitivity.LOW,
149
- 'email': Sensitivity.MEDIUM,
150
- 'phone': Sensitivity.MEDIUM,
151
- 'mobile': Sensitivity.MEDIUM,
152
- 'idcard': Sensitivity.CRITICAL,
153
- 'ssn': Sensitivity.CRITICAL,
154
- 'credit': Sensitivity.CRITICAL,
155
- 'bank': Sensitivity.CRITICAL,
156
- }
157
-
158
- # 认证相关端点
159
- AUTH_PATTERNS = [
160
- r'/auth/', r'/login', r'/logout', r'/register', r'/signup',
161
- r'/token', r'/refresh', r'/verify', r'/oauth', r'/sso',
162
- r'/session', r'/cas/', r'/saml/',
163
- ]
164
-
165
- # 管理后台端点
166
- ADMIN_PATTERNS = [
167
- r'/admin/', r'/manage/', r'/control/', r'/dashboard',
168
- r'/system/', r'/config/', r'/setting/', r'/master',
169
- r'/root/', r'/super/', r'/privilege',
170
- ]
171
-
172
- # 用户数据端点
173
- USER_DATA_PATTERNS = [
174
- r'/user/', r'/profile/', r'/account/', r'/person/',
175
- r'/employee/', r'/member/', r'/customer/',
176
- r'/order/', r'/product/', r'/transaction/',
177
- ]
178
-
179
- # 参数名模式 (用于从响应中提取)
180
- PARAM_PATTERNS = [
181
- r'["\']?(\w+)["\']?\s*:\s*(?:null|undefined|"[^"]*"|\'[^\']*\'|\d+)',
182
- r'(?:id|userId|user_id|page|token|key|type|category|name|status)\s*[=:]\s*["\']?[^"\'\s,}]+',
183
- ]
184
-
185
- # 响应参数提取模式
186
- RESPONSE_PARAM_PATTERNS = [
187
- r'"(\w+)":\s*(?:\{|\[|"[^"]*"|\d+|true|false|null)',
188
- r'"(id|code|msg|data|list|count|total|pages?)"\s*:',
189
- ]
190
-
191
- def __init__(self, session: requests.Session = None):
192
- self.session = session or requests.Session()
193
- self.endpoints: List[SmartEndpoint] = []
194
- self.sensitive_data: List[SensitiveMatch] = []
195
- self.base_urls: Set[str] = set()
196
- self.js_content_cache: Dict[str, str] = {}
197
-
198
- def analyze_js_file(self, js_url: str, content: str) -> List[SmartEndpoint]:
199
- """
200
- 分析 JS 文件,提取智能端点
201
-
202
- 核心算法:
203
- 1. 提取所有字符串字面量
204
- 2. 识别 HTTP 调用模式 (fetch, axios, etc.)
205
- 3. 识别 Base URL 配置
206
- 4. 区分后端 API 和前端路由
207
- 5. 提取参数信息
208
- """
209
- endpoints = []
210
-
211
- base_url = self._extract_base_url(content, js_url)
212
- if base_url:
213
- self.base_urls.add(base_url)
214
-
215
- # 1. 提取 fetch 调用
216
- fetch_endpoints = self._extract_fetch_patterns(content, base_url)
217
- endpoints.extend(fetch_endpoints)
218
-
219
- # 2. 提取 axios 调用
220
- axios_endpoints = self._extract_axios_patterns(content, base_url)
221
- endpoints.extend(axios_endpoints)
222
-
223
- # 3. 提取 $.ajax 调用
224
- ajax_endpoints = self._extract_jquery_ajax_patterns(content, base_url)
225
- endpoints.extend(ajax_endpoints)
226
-
227
- # 4. 提取配置对象中的 URL
228
- config_endpoints = self._extract_config_urls(content, base_url)
229
- endpoints.extend(config_endpoints)
230
-
231
- # 5. 提取常量定义
232
- constant_endpoints = self._extract_constant_urls(content, base_url)
233
- endpoints.extend(constant_endpoints)
234
-
235
- # 去重
236
- seen = set()
237
- unique_endpoints = []
238
- for ep in endpoints:
239
- key = f"{ep.method}:{ep.path}"
240
- if key not in seen:
241
- seen.add(key)
242
- unique_endpoints.append(ep)
243
-
244
- return unique_endpoints
245
-
246
- def _extract_base_url(self, content: str, js_url: str) -> Optional[str]:
247
- """提取 Base URL"""
248
- patterns = [
249
- r'(?:baseURL|base_url|apiUrl|api_url|API_URL)\s*[:=]\s*["\']([^"\']+)["\']',
250
- r'(?:BASE_URL|API_URL)\s*[:=]\s*["\']([^"\']+)["\']',
251
- r'process\.env\.([A-Z_]+)\s*[:=]\s*["\']([^"\']+)["\']',
252
- ]
253
-
254
- for pattern in patterns:
255
- matches = re.findall(pattern, content)
256
- for match in matches:
257
- if isinstance(match, tuple):
258
- value = match[-1]
259
- else:
260
- value = match
261
-
262
- if value.startswith('http'):
263
- return value.rstrip('/')
264
-
265
- parsed = urlparse(js_url)
266
- return f"{parsed.scheme}://{parsed.netloc}"
267
-
268
- def _extract_fetch_patterns(self, content: str, base_url: str) -> List[SmartEndpoint]:
269
- """提取 fetch 调用"""
270
- endpoints = []
271
-
272
- patterns = [
273
- (r"fetch\s*\(\s*['\"]([^'\"]+)['\"]", "GET"),
274
- (r"fetch\s*\(\s*[`'\"]([^`'\"]+)[`'\"]", "GET"),
275
- (r"fetch\s*\(\s*['\"]([^'\"]+)['\"]\s*,\s*\{", None),
276
- ]
277
-
278
- for pattern, default_method in patterns:
279
- matches = re.finditer(pattern, content)
280
- for match in matches:
281
- path = match.group(1) if match.groups() else match.group(0)
282
-
283
- if not self._is_valid_api_path(path):
284
- continue
285
-
286
- method = default_method
287
- if method is None and match.group(0):
288
- method_match = re.search(r"method:\s*['\"](\w+)['\"]", match.group(0))
289
- method = method_match.group(1) if method_match else "GET"
290
-
291
- endpoint = self._create_smart_endpoint(path, method, base_url, "fetch", content)
292
- endpoints.append(endpoint)
293
-
294
- return endpoints
295
-
296
- def _extract_axios_patterns(self, content: str, base_url: str) -> List[SmartEndpoint]:
297
- """提取 axios 调用"""
298
- endpoints = []
299
-
300
- patterns = [
301
- r"axios\.(get|post|put|delete|patch|head|options)\s*\(\s*['\"]([^'\"]+)['\"]",
302
- r"axios\.(get|post|put|delete|patch)\s*\(\s*[`'\"]([^`'\"]+)[`'\"]",
303
- r"axios\s*.\s*(?:request|post|get)\s*\(\s*\{[^}]*url\s*:\s*['\"]([^'\"]+)['\"]",
304
- ]
305
-
306
- for pattern in patterns:
307
- matches = re.finditer(pattern, content)
308
- for match in matches:
309
- groups = match.groups()
310
- if len(groups) >= 2:
311
- method = groups[0].upper()
312
- path = groups[1]
313
-
314
- if not self._is_valid_api_path(path):
315
- continue
316
-
317
- endpoint = self._create_smart_endpoint(path, method, base_url, "axios", content)
318
- endpoints.append(endpoint)
319
-
320
- return endpoints
321
-
322
- def _extract_jquery_ajax_patterns(self, content: str, base_url: str) -> List[SmartEndpoint]:
323
- """提取 $.ajax 调用"""
324
- endpoints = []
325
-
326
- pattern = r"\$\.ajax\s*\(\s*\{([^}]+)\}"
327
- matches = re.finditer(pattern, content)
328
-
329
- for match in matches:
330
- config = match.group(0)
331
-
332
- url_match = re.search(r"url\s*:\s*['\"]([^'\"]+)['\"]", config)
333
- method_match = re.search(r"type\s*:\s*['\"](\w+)['\"]", config)
334
-
335
- if url_match:
336
- path = url_match.group(1)
337
- method = method_match.group(1).upper() if method_match else "GET"
338
-
339
- if not self._is_valid_api_path(path):
340
- continue
341
-
342
- endpoint = self._create_smart_endpoint(path, method, base_url, "jquery", content)
343
- endpoints.append(endpoint)
344
-
345
- return endpoints
346
-
347
- def _extract_config_urls(self, content: str, base_url: str) -> List[SmartEndpoint]:
348
- """提取配置对象中的 URL"""
349
- endpoints = []
350
-
351
- patterns = [
352
- r'(?:api|API|endpoint|ENDPOINT)\s*:\s*["\']([/a-zA-Z0-9_-]+)["\']',
353
- r'(?:url|URL|path|PATH)\s*:\s*["\']([/a-zA-Z0-9_-]+)["\']',
354
- ]
355
-
356
- for pattern in patterns:
357
- matches = re.findall(pattern, content)
358
- for path in matches:
359
- if not self._is_valid_api_path(path):
360
- continue
361
-
362
- endpoint = self._create_smart_endpoint(path, "GET", base_url, "config", content)
363
- endpoints.append(endpoint)
364
-
365
- return endpoints
366
-
367
- def _extract_constant_urls(self, content: str, base_url: str) -> List[SmartEndpoint]:
368
- """提取常量定义的 URL"""
369
- endpoints = []
370
-
371
- patterns = [
372
- r'const\s+\w*[Uu]rl\w*\s*=\s*["\']([^"\']+)["\']',
373
- r'(?:API|PATH|ROUTE)_(?:PATH|URL|ENDPOINT)\s*=\s*["\']([^"\']+)["\']',
374
- ]
375
-
376
- for pattern in patterns:
377
- matches = re.findall(pattern, content)
378
- for path in matches:
379
- if not self._is_valid_api_path(path):
380
- continue
381
-
382
- endpoint = self._create_smart_endpoint(path, "GET", base_url, "constant", content)
383
- endpoints.append(endpoint)
384
-
385
- return endpoints
386
-
387
- def _is_valid_api_path(self, path: str) -> bool:
388
- """验证是否为有效的 API 路径"""
389
- if not path or len(path) < 2:
390
- return False
391
-
392
- if path.startswith('//') or path.startswith('http'):
393
- return True
394
-
395
- if path.startswith('/'):
396
- path = path[1:]
397
-
398
- skip_patterns = [
399
- r'\.js$', r'\.css$', r'\.svg$', r'\.png$', r'\.jpg$',
400
- r'chunk-', r'module', r'dist', r'build',
401
- r'node_modules', r'assets', r'images', r'icons',
402
- ]
403
-
404
- for pattern in skip_patterns:
405
- if re.search(pattern, path, re.IGNORECASE):
406
- return False
407
-
408
- return True
409
-
410
- def _create_smart_endpoint(self, path: str, method: str, base_url: str, source: str, content: str) -> SmartEndpoint:
411
- """创建智能端点"""
412
- endpoint = SmartEndpoint(
413
- path=path,
414
- method=method.upper(),
415
- base_url=base_url,
416
- source_file=source,
417
- confidence=0.8 if source in ['fetch', 'axios', 'jquery'] else 0.5
418
- )
419
-
420
- path_lower = path.lower()
421
-
422
- if any(re.search(p, path_lower) for p in self.AUTH_PATTERNS):
423
- endpoint.is_auth_endpoint = True
424
- endpoint.sensitivity = Sensitivity.HIGH
425
- endpoint.endpoint_type = EndpointType.BACKEND_API
426
-
427
- if any(re.search(p, path_lower) for p in self.ADMIN_PATTERNS):
428
- endpoint.is_admin_endpoint = True
429
- endpoint.sensitivity = Sensitivity.HIGH
430
- endpoint.endpoint_type = EndpointType.BACKEND_API
431
-
432
- if any(re.search(p, path_lower) for p in self.USER_DATA_PATTERNS):
433
- endpoint.is_user_data_endpoint = True
434
- endpoint.sensitivity = Sensitivity.MEDIUM
435
- endpoint.endpoint_type = EndpointType.BACKEND_API
436
-
437
- if endpoint.endpoint_type == EndpointType.UNKNOWN:
438
- if any(re.search(p, path_lower) for p in self.BACKEND_API_PATTERNS):
439
- endpoint.endpoint_type = EndpointType.BACKEND_API
440
- endpoint.sensitivity = Sensitivity.INFO
441
-
442
- endpoint.parameters = self._extract_parameters_from_content(path, content)
443
-
444
- return endpoint
445
-
446
- def _extract_parameters_from_content(self, path: str, content: str) -> List[ParsedParameter]:
447
- """从 JS 内容中提取参数"""
448
- params = []
449
-
450
- path_parts = path.strip('/').split('/')
451
- for i, part in enumerate(path_parts):
452
- if re.match(r'^\{[\w_]+\}$', part):
453
- param_name = part[1:-1]
454
- params.append(ParsedParameter(
455
- name=param_name,
456
- param_type='path',
457
- data_type='string',
458
- source='from_path_template'
459
- ))
460
- elif re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', part) and part not in ['api', 'v1', 'v2', 'rest']:
461
- if i > 0:
462
- params.append(ParsedParameter(
463
- name=part,
464
- param_type='path',
465
- data_type='string',
466
- source='from_path_guess'
467
- ))
468
-
469
- param_names = re.findall(r'(?:param|params|parameter|query|data|body|payload)\s*[:=]\s*\{[^}]*\}', content)
470
- for param in param_names[:5]:
471
- name_match = re.search(r'["\']?(\w+)["\']?\s*:', param)
472
- if name_match:
473
- params.append(ParsedParameter(
474
- name=name_match.group(1),
475
- param_type='body',
476
- data_type='object',
477
- source='from_code'
478
- ))
479
-
480
- return params
481
-
482
- def analyze_response(self, endpoint: SmartEndpoint, response_text: str) -> List[ParsedParameter]:
483
- """从响应中提取参数"""
484
- params = []
485
-
486
- matches = re.findall(r'"(\w+)":\s*(?:\{|\[|"[^"]*"|\d+|true|false|null)', response_text)
487
- for match in matches:
488
- if match not in ['id', 'code', 'msg', 'data', 'list', 'total', 'page', 'pages', 'size']:
489
- params.append(ParsedParameter(
490
- name=match,
491
- param_type='response',
492
- data_type='mixed',
493
- source='from_response'
494
- ))
495
-
496
- return params
497
-
498
- def extract_sensitive_data(self, content: str, source: str = "") -> List[SensitiveMatch]:
499
- """提取敏感信息"""
500
- matches = []
501
-
502
- patterns = {
503
- 'AWS Access Key': (r'AKIA[0-9A-Z]{16}', Sensitivity.CRITICAL),
504
- 'AWS Secret Key': (r'[A-Za-z0-9/+=]{40}', Sensitivity.CRITICAL),
505
- 'JWT Token': (r'eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*', Sensitivity.HIGH),
506
- 'Bearer Token': (r'Bearer\s+[A-Za-z0-9_-]+', Sensitivity.HIGH),
507
- 'Basic Auth': (r'Basic\s+[A-Za-z0-9_-]+', Sensitivity.MEDIUM),
508
- 'API Key': (r'[a-zA-Z0-9]{32,}', Sensitivity.MEDIUM),
509
- 'Private Key': (r'-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----', Sensitivity.CRITICAL),
510
- 'Password': (r'(?:password|passwd|pwd)\s*[:=]\s*["\'][^"\']{4,}["\']', Sensitivity.HIGH),
511
- 'Email': (r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', Sensitivity.LOW),
512
- 'Phone': (r'1[3-9]\d{9}', Sensitivity.LOW),
513
- 'ID Card': (r'\d{17}[\dXx]', Sensitivity.CRITICAL),
514
- }
515
-
516
- for name, (pattern, severity) in patterns.items():
517
- regex_matches = re.finditer(pattern, content, re.IGNORECASE)
518
- for match in regex_matches:
519
- value = match.group(0)
520
- if len(value) > 5 and len(value) < 500:
521
- start = max(0, match.start() - 20)
522
- end = min(len(content), match.end() + 20)
523
- context = content[start:end]
524
-
525
- matches.append(SensitiveMatch(
526
- data_type=name,
527
- value=value[:50],
528
- severity=severity,
529
- context=context,
530
- source=source
531
- ))
532
-
533
- return matches
534
-
535
- def classify_endpoints(self) -> Dict[str, List[SmartEndpoint]]:
536
- """分类端点"""
537
- classified = {
538
- 'auth': [],
539
- 'admin': [],
540
- 'user_data': [],
541
- 'api': [],
542
- 'other': [],
543
- 'frontend': []
544
- }
545
-
546
- for ep in self.endpoints:
547
- if ep.is_auth_endpoint:
548
- classified['auth'].append(ep)
549
- elif ep.is_admin_endpoint:
550
- classified['admin'].append(ep)
551
- elif ep.is_user_data_endpoint:
552
- classified['user_data'].append(ep)
553
- elif ep.endpoint_type == EndpointType.BACKEND_API:
554
- classified['api'].append(ep)
555
- elif ep.endpoint_type == EndpointType.FRONTEND_ROUTE:
556
- classified['frontend'].append(ep)
557
- else:
558
- classified['other'].append(ep)
559
-
560
- return classified
561
-
562
- def generate_fuzz_targets(self) -> List[Tuple[str, str, Dict]]:
563
- """
564
- 生成精准 fuzzing 目标
565
-
566
- 返回: [(url, method, fuzz_params), ...]
567
- """
568
- targets = []
569
-
570
- classified = self.classify_endpoints()
571
-
572
- priority_order = ['auth', 'admin', 'user_data', 'api']
573
-
574
- for category in priority_order:
575
- for ep in classified[category]:
576
- full_url = ep.base_url + ep.path if ep.path.startswith('/') else ep.path
577
-
578
- params = {}
579
- for param in ep.parameters:
580
- if param.param_type == 'path':
581
- params[param.name] = self._get_fuzz_value(param.name)
582
- elif param.param_type == 'query':
583
- params[param.name] = self._get_fuzz_value(param.name)
584
-
585
- targets.append((full_url, ep.method, params))
586
-
587
- return targets
588
-
589
- def _get_fuzz_value(self, param_name: str) -> str:
590
- """根据参数名生成 fuzz 值"""
591
- fuzz_db = {
592
- 'id': ["1", "0", "999999", "1 OR 1=1", "${jndi}"],
593
- 'userId': ["1", "0", "admin", "1' OR '1'='1"],
594
- 'page': ["1", "0", "999"],
595
- 'pageSize': ["10", "100", "9999"],
596
- 'search': ["' OR '1'='1", "<script>alert(1)</script>", "${jndi:ldap://}"],
597
- 'q': ["' OR '1'='1", "<script>alert(1)</script>"],
598
- 'query': ["' OR '1'='1", "<script>alert(1)</script>"],
599
- 'type': ["1", "admin", "test"],
600
- 'name': ["admin", "test", "' OR '1'='1"],
601
- 'email': ["admin@test.com", "' OR '1'='1"],
602
- 'password': ["admin", "123456", "' OR '1'='1"],
603
- }
604
-
605
- return fuzz_db.get(param_name.lower(), ["test", "1", "admin"])
606
-
607
- def get_high_value_targets(self) -> List[SmartEndpoint]:
608
- """获取高价值目标"""
609
- return [ep for ep in self.endpoints
610
- if ep.sensitivity in [Sensitivity.CRITICAL, Sensitivity.HIGH]
611
- or ep.is_auth_endpoint or ep.is_admin_endpoint]
612
-
613
-
614
- def smart_analyze(target_url: str, session: requests.Session = None) -> Dict:
615
- """
616
- 智能分析主函数
617
-
618
- 像渗透测试工程师一样:
619
- 1. 收集 JS 文件
620
- 2. 智能提取 API 端点
621
- 3. 分类和评估
622
- 4. 提取敏感信息
623
- 5. 生成精准 fuzzing 目标
624
- """
625
- session = session or requests.Session()
626
- analyzer = SmartAPIAnalyzer(session)
627
-
628
- print("[*] Fetching target...")
629
- resp = session.get(target_url, timeout=10)
630
- html = resp.text
631
-
632
- js_url_pattern = r'<script[^>]+src=["\']([^"\']+\.js[^"\']*)["\']'
633
- js_urls = re.findall(js_url_pattern, html)
634
-
635
- print(f"[*] Found {len(js_urls)} JS files")
636
-
637
- all_endpoints = []
638
-
639
- for js_url in js_urls[:5]:
640
- if not js_url.startswith('http'):
641
- js_url = urljoin(target_url, js_url)
642
-
643
- print(f"[*] Analyzing: {js_url.split('/')[-1]}")
644
-
645
- try:
646
- js_resp = session.get(js_url, timeout=10)
647
- content = js_resp.text
648
-
649
- endpoints = analyzer.analyze_js_file(js_url, content)
650
- all_endpoints.extend(endpoints)
651
-
652
- sensitive = analyzer.extract_sensitive_data(content, js_url)
653
- analyzer.sensitive_data.extend(sensitive)
654
-
655
- except Exception as e:
656
- print(f"[!] Error analyzing {js_url}: {e}")
657
-
658
- analyzer.endpoints = all_endpoints
659
-
660
- classified = analyzer.classify_endpoints()
661
- high_value = analyzer.get_high_value_targets()
662
- fuzz_targets = analyzer.generate_fuzz_targets()
663
-
664
- print(f"\n[*] Analysis Results:")
665
- print(f" Total endpoints: {len(all_endpoints)}")
666
- print(f" Auth endpoints: {len(classified['auth'])}")
667
- print(f" Admin endpoints: {len(classified['admin'])}")
668
- print(f" User data endpoints: {len(classified['user_data'])}")
669
- print(f" API endpoints: {len(classified['api'])}")
670
- print(f" High value targets: {len(high_value)}")
671
- print(f" Fuzz targets: {len(fuzz_targets)}")
672
- print(f" Sensitive data found: {len(analyzer.sensitive_data)}")
673
-
674
- return {
675
- 'endpoints': all_endpoints,
676
- 'classified': classified,
677
- 'high_value': high_value,
678
- 'fuzz_targets': fuzz_targets,
679
- 'sensitive_data': analyzer.sensitive_data,
680
- 'base_urls': list(analyzer.base_urls),
681
- }
682
-
683
-
684
- if __name__ == "__main__":
685
- import sys
686
- target = sys.argv[1] if len(sys.argv) > 1 else "http://49.65.100.160:6004"
687
- result = smart_analyze(target)