opencode-api-security-testing 2.0.0 → 2.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.
Files changed (63) hide show
  1. package/README.md +30 -24
  2. package/SKILL.md +1797 -0
  3. package/core/advanced_recon.py +788 -0
  4. package/core/agentic_analyzer.py +445 -0
  5. package/core/analyzers/api_parser.py +210 -0
  6. package/core/analyzers/response_analyzer.py +212 -0
  7. package/core/analyzers/sensitive_finder.py +184 -0
  8. package/core/api_fuzzer.py +422 -0
  9. package/core/api_interceptor.py +525 -0
  10. package/core/api_parser.py +955 -0
  11. package/core/browser_tester.py +479 -0
  12. package/core/cloud_storage_tester.py +1330 -0
  13. package/core/collectors/__init__.py +23 -0
  14. package/core/collectors/api_path_finder.py +300 -0
  15. package/core/collectors/browser_collect.py +645 -0
  16. package/core/collectors/browser_collector.py +411 -0
  17. package/core/collectors/http_client.py +111 -0
  18. package/core/collectors/js_collector.py +490 -0
  19. package/core/collectors/js_parser.py +780 -0
  20. package/core/collectors/url_collector.py +319 -0
  21. package/core/context_manager.py +682 -0
  22. package/core/deep_api_tester_v35.py +844 -0
  23. package/core/deep_api_tester_v55.py +366 -0
  24. package/core/dynamic_api_analyzer.py +532 -0
  25. package/core/http_client.py +179 -0
  26. package/core/models.py +296 -0
  27. package/core/orchestrator.py +890 -0
  28. package/core/prerequisite.py +227 -0
  29. package/core/reasoning_engine.py +1042 -0
  30. package/core/response_classifier.py +606 -0
  31. package/core/runner.py +938 -0
  32. package/core/scan_engine.py +599 -0
  33. package/core/skill_executor.py +435 -0
  34. package/core/skill_executor_v2.py +670 -0
  35. package/core/skill_executor_v3.py +704 -0
  36. package/core/smart_analyzer.py +687 -0
  37. package/core/strategy_pool.py +707 -0
  38. package/core/testers/auth_tester.py +264 -0
  39. package/core/testers/idor_tester.py +200 -0
  40. package/core/testers/sqli_tester.py +211 -0
  41. package/core/testing_loop.py +655 -0
  42. package/core/utils/base_path_dict.py +255 -0
  43. package/core/utils/payload_lib.py +167 -0
  44. package/core/utils/ssrf_detector.py +220 -0
  45. package/core/verifiers/vuln_verifier.py +536 -0
  46. package/package.json +17 -13
  47. package/references/asset-discovery.md +119 -612
  48. package/references/graphql-guidance.md +65 -641
  49. package/references/intake.md +84 -0
  50. package/references/report-template.md +131 -38
  51. package/references/rest-guidance.md +55 -526
  52. package/references/severity-model.md +52 -264
  53. package/references/test-matrix.md +65 -263
  54. package/references/validation.md +53 -400
  55. package/scripts/postinstall.js +46 -0
  56. package/src/index.ts +259 -275
  57. package/agents/cyber-supervisor.md +0 -55
  58. package/agents/probing-miner.md +0 -42
  59. package/agents/resource-specialist.md +0 -31
  60. package/commands/api-security-testing-scan.md +0 -59
  61. package/commands/api-security-testing-test.md +0 -49
  62. package/commands/api-security-testing.md +0 -72
  63. package/tsconfig.json +0 -17
@@ -1,612 +1,119 @@
1
- # 资产发现方法论
2
-
3
- ## 目录
4
-
5
- 1. [被动收集](#1-被动收集)
6
- 2. [主动探测](#2-主动探测)
7
- 3. [JavaScript 分析](#3-javascript-分析)
8
- 4. [Swagger/OpenAPI 发现](#4-swaggeropenapi-发现)
9
- 5. [云存储发现](#5-云存储发现)
10
- 6. [关联系统发现](#6-关联系统发现)
11
- 7. [指纹识别](#7-指纹识别)
12
-
13
- ---
14
-
15
- ## 1. 被动收集
16
-
17
- ### 1.1 DNS 记录收集
18
-
19
- ```python
20
- # 被动 DNS 收集
21
- DNS_RECORD_TYPES = ["A", "AAAA", "MX", "NS", "TXT", "CNAME", "SOA"]
22
-
23
- def passive_dns_enum(domain):
24
- # 使用 SecurityTrails, VirusTotal, CRTSH 等被动源
25
- passive_sources = [
26
- f"https://securitytrails.com/api/v1/domain/{domain}/dns",
27
- f"https://crt.sh/?q=%.{domain}",
28
- ]
29
-
30
- for source in passive_sources:
31
- try:
32
- resp = requests.get(source, timeout=10)
33
- # 解析并收集子域名
34
- except:
35
- pass
36
- ```
37
-
38
- ### 1.2 SSL 证书收集
39
-
40
- ```python
41
- # 从 SSL 证书中发现子域名
42
- def cert_enumeration(domain):
43
- import socket
44
- import ssl
45
-
46
- ctx = ssl.create_default_context()
47
- with socket.create_connection((domain, 443)) as sock:
48
- with ctx.wrap_socket(sock, server_hostname=domain) as ssock:
49
- cert = ssock.getpeercert()
50
- # 提取证书中的所有域名
51
- return cert.get('subjectAltName', [])
52
- ```
53
-
54
- ### 1.3 网页内容收集
55
-
56
- ```python
57
- # HTML 中提取链接和路径
58
- def extract_from_html(html_content):
59
- patterns = {
60
- 'links': r'href=["\']([^"\']+)["\']',
61
- 'scripts': r'src=["\']([^"\']+\.js[^"\']*)["\']',
62
- 'forms': r'action=["\']([^"\']+)["\']',
63
- 'iframes': r'src=["\']([^"\']+)["\']',
64
- 'comments': r'<!--([^-]|-[^-])*-->',
65
- 'meta': r'<meta[^>]+content=["\']([^"\']+)["\']',
66
- }
67
-
68
- assets = {}
69
- for name, pattern in patterns.items():
70
- assets[name] = re.findall(pattern, html_content)
71
-
72
- return assets
73
- ```
74
-
75
- ---
76
-
77
- ## 2. 主动探测
78
-
79
- ### 2.1 子域名爆破
80
-
81
- ```python
82
- # 子域名字典
83
- SUBDOMAIN_WORDLIST = [
84
- # 通用
85
- "www", "mail", "ftp", "admin", "blog", "dev",
86
- "test", "staging", "demo", "api", "mobile",
87
- "vpn", "git", "gitlab", "jenkins", "ci",
88
- # 业务
89
- "oms", "cms", "erp", "crm", "scm", "wms",
90
- "ums", "rms", "pms", "bms", "fms",
91
- # 部门
92
- "hr", "finance", "it", "ops", "security",
93
- # 常用数字
94
- "test1", "test2", "dev1", "dev2",
95
- "staging1", "staging2",
96
- ]
97
-
98
- def bruteforce_subdomains(domain, wordlist=SUBDOMAIN_WORDLIST):
99
- found = []
100
- for subdomain in wordlist:
101
- target = f"{subdomain}.{domain}"
102
- try:
103
- ip = socket.gethostbyname(target)
104
- found.append((target, ip))
105
- print(f"[+] Found: {target} -> {ip}")
106
- except socket.gaierror:
107
- pass
108
- return found
109
- ```
110
-
111
- ### 2.2 端口扫描
112
-
113
- ```python
114
- # 常见 Web 端口
115
- WEB_PORTS = [
116
- 80, 443, # HTTP/HTTPS
117
- 8080, 8443, # Alt HTTP
118
- 3000, 3001, # Dev servers
119
- 5000, 5001, # Python/Flask
120
- 8000, 8001, # Python
121
- 8888, # Jupyter
122
- 9000, # PHP-FPM
123
- 9200, # Elasticsearch
124
- 27017, # MongoDB
125
- 6379, # Redis
126
- 3306, # MySQL
127
- 5432, # PostgreSQL
128
- 11211, # Memcached
129
- ]
130
-
131
- # 快速端口扫描
132
- def quick_port_scan(host, ports=WEB_PORTS):
133
- open_ports = []
134
- for port in ports:
135
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
136
- sock.settimeout(1)
137
- result = sock.connect_ex((host, port))
138
- if result == 0:
139
- open_ports.append(port)
140
- print(f"[+] Port {port} open")
141
- sock.close()
142
- return open_ports
143
- ```
144
-
145
- ### 2.3 路径爆破
146
-
147
- ```python
148
- # 常见路径字典
149
- PATH_WORDLIST = [
150
- # 管理后台
151
- "/admin", "/manage", "/management", "/administrator",
152
- "/login", "/signin", "/auth", "/oauth",
153
- "/dashboard", "/console", "/backend",
154
- # API
155
- "/api", "/api/v1", "/api/v2", "/rest",
156
- "/swagger", "/swagger-ui", "/api-docs",
157
- "/graphql", "/graphiql",
158
- # 文件
159
- "/robots.txt", "/sitemap.xml", "/crossdomain.xml",
160
- "/.git/config", "/.env", "/config.php",
161
- "/backup", "/bak", "/old", "/debug",
162
- # 探测
163
- "/server-status", "/server-info",
164
- "/actuator", "/actuator/health",
165
- ]
166
-
167
- def bruteforce_paths(base_url, wordlist=PATH_WORDLIST):
168
- found = []
169
- for path in wordlist:
170
- url = base_url.rstrip('/') + path
171
- try:
172
- resp = requests.get(url, timeout=5, allow_redirects=False)
173
- if resp.status_code in [200, 301, 302, 403]:
174
- found.append((path, resp.status_code))
175
- print(f"[+] {path} ({resp.status_code})")
176
- except:
177
- pass
178
- return found
179
- ```
180
-
181
- ---
182
-
183
- ## 3. JavaScript 分析
184
-
185
- ### 3.1 JS 文件收集
186
-
187
- ```python
188
- # 从 HTML 中提取所有 JS 文件
189
- def collect_js_files(html_content):
190
- js_files = []
191
-
192
- # script src
193
- patterns = [
194
- r'<script[^>]+src=["\']([^"\']+\.js[^"\']*)["\']',
195
- r'"(/_next/static/[^"]+\.js)"',
196
- r'"(/static/js/[^"]+\.js)"',
197
- r'"(https://[^"]+\.js)"',
198
- ]
199
-
200
- for pattern in patterns:
201
- matches = re.findall(pattern, html_content)
202
- js_files.extend(matches)
203
-
204
- # 去重
205
- return list(set(js_files))
206
- ```
207
-
208
- ### 3.2 API 端点提取
209
-
210
- ```python
211
- # 从 JS 中提取 API 端点
212
- API_PATTERNS = [
213
- # axios/fetch
214
- r'["\'](/(?:api|auth|admin|user|login|logout)[^"\']*)["\']',
215
- r'\.(?:get|post|put|delete|patch)\\(["\']([^"\']+)["\']\\)',
216
- # URL patterns
217
- r'["\']https?://[^"\']+(?:api|auth|admin)[^"\']*["\']',
218
- # baseURL
219
- r'baseURL\s*[:=]\s*["\']([^"\']+)["\']',
220
- # webpack chunk
221
- r'"(?:chunk-|js/)([a-f0-9]+)"',
222
- ]
223
-
224
- def extract_api_from_js(js_content):
225
- endpoints = set()
226
-
227
- for pattern in API_PATTERNS:
228
- matches = re.findall(pattern, js_content, re.IGNORECASE)
229
- for match in matches:
230
- if isinstance(match, tuple):
231
- endpoints.update(match)
232
- else:
233
- endpoints.add(match)
234
-
235
- return list(endpoints)
236
- ```
237
-
238
- ### 3.3 敏感信息提取
239
-
240
- ```python
241
- # 敏感信息正则
242
- SENSITIVE_PATTERNS = {
243
- 'api_key': [
244
- r'(?:api[_-]?key|apikey)\s*[:=]\s*["\']([a-zA-Z0-9_-]{20,})["\']',
245
- r'["\'](?:sk|pk|api)[_-][a-zA-Z0-9]{20,}["\']',
246
- ],
247
- 'aws_key': [
248
- r'AKIA[0-9A-Z]{16}',
249
- r'(?:aws[_-]?)?(?:access[_-]?key[_-]?id|secret[_-]?key)',
250
- ],
251
- 'jwt': [
252
- r'eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+',
253
- ],
254
- 'private_key': [
255
- r'-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----',
256
- ],
257
- 'ip_address': [
258
- r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b',
259
- ],
260
- 'internal_host': [
261
- r'(?:https?://)?(?:[a-z0-9-]+\.)+(?:local|internal|lan|intranet)(?::\d+)?',
262
- r'http://192\.168\.\d{1,3}\.\d{1,3}(?::\d+)?',
263
- r'http://10\.\d{1,3}\.\d{1,3}\.\d{1,3}(?::\d+)?',
264
- ],
265
- }
266
-
267
- def extract_sensitive_info(js_content):
268
- findings = {}
269
- for info_type, patterns in SENSITIVE_PATTERNS.items():
270
- for pattern in patterns:
271
- matches = re.findall(pattern, js_content, re.IGNORECASE)
272
- if matches:
273
- findings[info_type] = list(set(matches))
274
- return findings
275
- ```
276
-
277
- ---
278
-
279
- ## 4. Swagger/OpenAPI 发现
280
-
281
- ### 4.1 常见 Swagger 路径
282
-
283
- ```python
284
- # Swagger 路径字典
285
- SWAGGER_PATHS = [
286
- # Swagger UI
287
- "/swagger-ui.html",
288
- "/swagger-ui/index.html",
289
- "/swagger-ui/swagger-ui-bundle.js",
290
- "/swagger-ui-standalone-preset.js",
291
- # OpenAPI
292
- "/v2/api-docs",
293
- "/v3/api-docs",
294
- "/api-docs",
295
- "/api-docs.json",
296
- "/openapi.json",
297
- "/openapi.yaml",
298
- # Swagger 2.0
299
- "/swagger.json",
300
- "/swagger.yaml",
301
- # 其他
302
- "/doc.html",
303
- "/swagger/index.html",
304
- "/api/swagger.json",
305
- "/api/swagger.yaml",
306
- "/api-docs/swagger.json",
307
- ]
308
-
309
- def probe_swagger(base_url):
310
- for path in SWAGGER_PATHS:
311
- url = base_url + path
312
- try:
313
- resp = requests.get(url, timeout=10)
314
- if resp.status_code == 200:
315
- if 'swagger' in resp.text.lower() or 'openapi' in resp.text.lower():
316
- print(f"[+] Found: {url}")
317
- return url
318
- except:
319
- pass
320
- return None
321
- ```
322
-
323
- ### 4.2 解析 OpenAPI Schema
324
-
325
- ```python
326
- # 解析 OpenAPI JSON
327
- def parse_openapi_schema(schema_url):
328
- resp = requests.get(schema_url)
329
- schema = resp.json()
330
-
331
- api_info = {
332
- 'title': schema.get('info', {}).get('title'),
333
- 'version': schema.get('info', {}).get('version'),
334
- 'basePath': schema.get('basePath'),
335
- 'servers': [s.get('url') for s in schema.get('servers', [])],
336
- 'endpoints': []
337
- }
338
-
339
- # 提取所有端点
340
- for path, methods in schema.get('paths', {}).items():
341
- for method, details in methods.items():
342
- if method.upper() in ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']:
343
- api_info['endpoints'].append({
344
- 'path': path,
345
- 'method': method.upper(),
346
- 'summary': details.get('summary'),
347
- 'parameters': details.get('parameters', []),
348
- 'requestBody': details.get('requestBody'),
349
- 'responses': details.get('responses'),
350
- })
351
-
352
- return api_info
353
- ```
354
-
355
- ---
356
-
357
- ## 5. 云存储发现
358
-
359
- ### 5.1 云存储 URL 模式
360
-
361
- ```python
362
- # 云存储 URL 正则
363
- CLOUD_STORAGE_PATTERNS = {
364
- 'aliyun_oss': [
365
- r'[a-z0-9-]+\.oss-(?:cn-[a-z0-9-]+)\.aliyuncs\.com',
366
- r'https?://(?:[a-z0-9-]+\.)?oss-[a-z0-9-]+\.aliyuncs\.com',
367
- ],
368
- 'aws_s3': [
369
- r'[a-z0-9-]+\.s3(?:(?:\.|\-)[a-z0-9-]+)?\.amazonaws\.com',
370
- r's3(?:(?:\.|\-)[a-z0-9-]+)?\.amazonaws\.com/[a-z0-9-]+',
371
- ],
372
- 'tencent_cos': [
373
- r'[a-z0-9-]+\.cos\.[a-z0-9-]+\.myqcloud\.com',
374
- r'https?://(?:[a-z0-9-]+\.)?cos\.myqcloud\.com',
375
- ],
376
- 'huawei_obs': [
377
- r'[a-z0-9-]+\.obs\.[a-z0-9-]+\.hwclouds\.com',
378
- r'https?://(?:[a-z0-9-]+\.)?obs\.hwclouds\.com',
379
- ],
380
- 'minio': [
381
- r'[a-z0-9-]+\.minio\.[a-z0-9.-]+',
382
- r'http://minio(?:[a-z0-9.-]+)?:\d+',
383
- ],
384
- }
385
-
386
- def detect_cloud_storage(content):
387
- findings = []
388
- for provider, patterns in CLOUD_STORAGE_PATTERNS.items():
389
- for pattern in patterns:
390
- matches = re.findall(pattern, content, re.IGNORECASE)
391
- for match in matches:
392
- findings.append({
393
- 'provider': provider,
394
- 'url': match if '://' in match else f'http://{match}'
395
- })
396
- return findings
397
- ```
398
-
399
- ### 5.2 云存储探测
400
-
401
- ```python
402
- # 云存储探测函数
403
- def probe_cloud_storage(bucket_url):
404
- tests = [
405
- # 列出目录
406
- ("GET", "", None, [200], "list_bucket"),
407
- # 上传测试
408
- ("PUT", "test.txt", b"test", [200, 201], "put_object"),
409
- # 获取上传的文件
410
- ("GET", "test.txt", None, [200], "get_object"),
411
- ]
412
-
413
- results = []
414
- for method, path, data, expected_codes, test_name in tests:
415
- url = bucket_url.rstrip('/') + '/' + path
416
- try:
417
- if method == "GET":
418
- resp = requests.get(url, timeout=10)
419
- elif method == "PUT":
420
- resp = requests.put(url, data=data, timeout=10)
421
-
422
- if resp.status_code in expected_codes:
423
- results.append({
424
- 'test': test_name,
425
- 'status': 'success',
426
- 'details': resp.status_code
427
- })
428
- except Exception as e:
429
- results.append({
430
- 'test': test_name,
431
- 'status': 'failed',
432
- 'error': str(e)
433
- })
434
-
435
- return results
436
- ```
437
-
438
- ---
439
-
440
- ## 6. 关联系统发现
441
-
442
- ### 6.1 内网地址发现
443
-
444
- ```python
445
- # 从响应中提取内网地址
446
- INTERNAL_IP_PATTERNS = [
447
- # 私有IP
448
- r'http://192\.168\.\d{1,3}\.\d{1,3}(?::\d+)?(?:/[^\s]*)?',
449
- r'http://10\.\d{1,3}\.\d{1,3}\.\d{1,3}(?::\d+)?(?:/[^\s]*)?',
450
- r'http://172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}(?::\d+)?(?:/[^\s]*)?',
451
- # localhost
452
- r'http://localhost(?::\d+)?(?:/[^\s]*)?',
453
- r'http://127\.0\.0\.1(?::\d+)?(?:/[^\s]*)?',
454
- # Docker/K8s
455
- r'http://172\.(?:1[7-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}(?::\d+)?',
456
- ]
457
-
458
- def extract_internal_ips(content):
459
- findings = []
460
- for pattern in INTERNAL_IP_PATTERNS:
461
- matches = re.findall(pattern, content, re.IGNORECASE)
462
- findings.extend(matches)
463
- return list(set(findings))
464
- ```
465
-
466
- ### 6.2 系统关联发现
467
-
468
- ```python
469
- # 从响应头提取 Server 信息
470
- def extract_server_info(response_headers):
471
- info = {
472
- 'server': response_headers.get('Server', ''),
473
- 'xPoweredBy': response_headers.get('X-Powered-By', ''),
474
- 'via': response_headers.get('Via', ''),
475
- }
476
-
477
- # 提取版本信息
478
- for header_value in info.values():
479
- version_match = re.findall(r'(\d+\.\d+\.\d+)', header_value)
480
- if version_match:
481
- info['versions'] = version_match
482
-
483
- return info
484
-
485
- # 常见系统 URL 模式
486
- SYSTEM_PATTERNS = {
487
- 'admin': '/admin', '/administrator', '/manage',
488
- 'monitoring': '/monitor', '/health', '/status',
489
- 'database': '/phpmyadmin', '/adminer', '/pgadmin',
490
- 'devops': '/jenkins', '/gitlab', '/jira', '/confluence',
491
- 'storage': '/oss', '/files', '/upload',
492
- }
493
- ```
494
-
495
- ---
496
-
497
- ## 7. 指纹识别
498
-
499
- ### 7.1 技术栈识别
500
-
501
- ```python
502
- # 技术栈指纹
503
- TECH_FINGERPRINTS = {
504
- 'frontend': {
505
- 'vue': ['vue.js', 'vue.min.js', '__vue__', 'Vue'],
506
- 'react': ['react.js', 'react.min.js', '_react', 'React'],
507
- 'angular': ['angular.js', 'angular.min.js', 'ng-app', 'Angular'],
508
- 'jquery': ['jquery.js', 'jquery.min.js', 'jQuery'],
509
- },
510
- 'backend': {
511
- 'express': ['Express', 'x-powered-by', 'express-session'],
512
- 'django': ['csrftoken', 'csrfmiddlewaretoken', 'django'],
513
- 'flask': ['flask', 'session', ' werkzeug'],
514
- 'spring': ['JSESSIONID', 'spring', 'GRAILS_'],
515
- 'rails': ['_session_id', 'Ruby on Rails'],
516
- 'laravel': ['laravel_session', 'XSRF-TOKEN'],
517
- },
518
- 'server': {
519
- 'nginx': ['nginx', 'Server: nginx'],
520
- 'apache': ['apache', 'Server: apache'],
521
- 'iis': ['IIS', 'X-AspNet-Version'],
522
- 'tomcat': ['Apache-Coyote', 'tomcat'],
523
- },
524
- }
525
-
526
- def identify_tech_stack(html_content, headers):
527
- identified = {'frontend': [], 'backend': [], 'server': []}
528
-
529
- content = html_content + str(headers)
530
-
531
- for category, fingerprints in TECH_FINGERPRINTS.items():
532
- for tech, keywords in fingerprints.items():
533
- for keyword in keywords:
534
- if keyword.lower() in content.lower():
535
- identified[category].append(tech)
536
- break
537
-
538
- return identified
539
- ```
540
-
541
- ### 7.2 CMS 识别
542
-
543
- ```python
544
- # CMS 指纹
545
- CMS_PATTERNS = {
546
- 'wordpress': [
547
- '/wp-content/',
548
- '/wp-includes/',
549
- 'wp-json',
550
- 'WordPress',
551
- ],
552
- 'drupal': [
553
- '/sites/default/',
554
- 'drupal.js',
555
- 'Drupal.settings',
556
- ],
557
- 'joomla': [
558
- '/media/jui/',
559
- 'Joomla!',
560
- 'option=com_',
561
- ],
562
- 'dedecms': [
563
- '/templets/default/',
564
- 'DedeCms',
565
- 'dede_',
566
- ],
567
- 'discuz': [
568
- '/static/image/common/',
569
- 'Discuz!',
570
- 'forum.php',
571
- ],
572
- }
573
- ```
574
-
575
- ---
576
-
577
- ## 附录:资产发现检查清单
578
-
579
- ```
580
- □ 被动收集
581
- □ SSL 证书分析
582
- □ DNS 记录收集
583
- □ 网页内容提取
584
-
585
- □ 主动探测
586
- □ 子域名爆破
587
- □ 端口扫描
588
- □ 路径爆破
589
-
590
- □ JS 分析
591
- □ JS 文件收集
592
- □ API 端点提取
593
- □ 敏感信息发现
594
-
595
- □ API 文档
596
- □ Swagger 发现
597
- □ OpenAPI 解析
598
- □ API 端点整理
599
-
600
- □ 云存储
601
- □ 云存储 URL 发现
602
- □ Bucket 权限测试
603
-
604
- □ 关联系统
605
- □ 内网地址发现
606
- □ 系统关联分析
607
-
608
- □ 指纹识别
609
- □ 技术栈识别
610
- □ CMS 识别
611
- □ 版本信息收集
612
- ```
1
+ # Asset Discovery Guidance
2
+
3
+ 将原始 API 材料转换为紧凑的安全相关清单。
4
+
5
+ ## 目标
6
+
7
+ 识别对安全测试最重要的 API 部分。
8
+
9
+ ## 核心表面
10
+
11
+ - base URL(s)
12
+ - versioning scheme
13
+ - routes 或 operations
14
+ - methods
15
+ - content types
16
+ - auth schemes
17
+
18
+ ## 信任边界
19
+
20
+ - public vs authenticated endpoints
21
+ - user vs admin operations
22
+ - internal vs external APIs
23
+ - service-to-service 或 callback flows
24
+ - tenant organization 边界
25
+
26
+ ## 敏感对象
27
+
28
+ 关注以下对象:
29
+ - users
30
+ - roles
31
+ - teams
32
+ - organizations
33
+ - invoices
34
+ - payments
35
+ - orders
36
+ - files
37
+ - secrets
38
+ - API keys
39
+ - tokens
40
+ - audit logs
41
+ - exports
42
+ - configuration objects
43
+
44
+ ## 高风险操作模式
45
+
46
+ 标记与以下相关的 endpoints 或 mutations:
47
+ - create/update/delete user
48
+ - role assignment
49
+ - permission change
50
+ - password reset
51
+ - token issue 或 refresh
52
+ - export 或 bulk download
53
+ - import 或 bulk update
54
+ - file upload
55
+ - webhook registration
56
+ - callback URL configuration
57
+ - search filter on sensitive entities
58
+ - internal admin dashboards 或 debug endpoints
59
+
60
+ ## REST 提示
61
+
62
+ 优先包含模式的 endpoints:
63
+ - `/admin`
64
+ - `/internal`
65
+ - `/users`
66
+ - `/roles`
67
+ - `/permissions`
68
+ - `/export`
69
+ - `/import`
70
+ - `/search`
71
+ - `/upload`
72
+ - `/files`
73
+ - `/billing`
74
+ - `/settings`
75
+ - `/token`
76
+ - `/auth`
77
+ - `/debug`
78
+
79
+ 同时注意:
80
+ - bulk 操作
81
+ - object IDs in path 或 query
82
+ - 同一资源上隐藏的替代方法
83
+ - 不一致的版本化 endpoints
84
+
85
+ ## GraphQL 提示
86
+
87
+ 优先:
88
+ - 变更 roles、permissions 或 state 的 mutations
89
+ - 暴露嵌套对象遍历的 fields
90
+ - admin-only resolvers
91
+ - schema introspection 暴露
92
+ - 带敏感链接数据的宽对象图
93
+ - 可能意外扩展访问的 connection 或 pagination 模式
94
+
95
+ ## 资产摘要格式
96
+
97
+ 优先简洁输出:
98
+
99
+ ```
100
+ - Base URLs:
101
+ - API type:
102
+ - Auth schemes:
103
+ - Roles observed or assumed:
104
+ - Sensitive objects:
105
+ - High-risk operations:
106
+ - Trust boundaries:
107
+ - Unknown areas:
108
+ ```
109
+
110
+ ## 优先级规则
111
+
112
+ 当表面较大时,优先深度在:
113
+ 1. auth 和 role 变更
114
+ 2. user tenant 数据
115
+ 3. export/import 和 bulk 操作
116
+ 4. file 和 callback 流程
117
+ 5. 金融或行政操作
118
+
119
+ 不要在低风险的只读 metadata endpoints 上浪费空间,除非它们支持更广泛的滥用路径。