opencode-api-security-testing 1.0.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 (35) hide show
  1. package/README.md +98 -0
  2. package/agents/cyber-supervisor.md +55 -0
  3. package/agents/probing-miner.md +42 -0
  4. package/agents/resource-specialist.md +31 -0
  5. package/commands/api-security-testing-scan.md +59 -0
  6. package/commands/api-security-testing-test.md +49 -0
  7. package/commands/api-security-testing.md +72 -0
  8. package/index.ts +9 -0
  9. package/package.json +37 -0
  10. package/references/README.md +72 -0
  11. package/references/asset-discovery.md +612 -0
  12. package/references/fuzzing-patterns.md +129 -0
  13. package/references/graphql-guidance.md +684 -0
  14. package/references/pua-agent.md +192 -0
  15. package/references/report-template.md +63 -0
  16. package/references/rest-guidance.md +547 -0
  17. package/references/severity-model.md +288 -0
  18. package/references/test-matrix.md +284 -0
  19. package/references/validation.md +425 -0
  20. package/references/vulnerabilities/01-sqli-tests.md +1128 -0
  21. package/references/vulnerabilities/02-user-enum-tests.md +423 -0
  22. package/references/vulnerabilities/03-jwt-tests.md +499 -0
  23. package/references/vulnerabilities/04-idor-tests.md +362 -0
  24. package/references/vulnerabilities/05-sensitive-data-tests.md +466 -0
  25. package/references/vulnerabilities/06-biz-logic-tests.md +501 -0
  26. package/references/vulnerabilities/07-security-config-tests.md +511 -0
  27. package/references/vulnerabilities/08-brute-force-tests.md +457 -0
  28. package/references/vulnerabilities/09-vulnerability-chains.md +465 -0
  29. package/references/vulnerabilities/10-auth-tests.md +537 -0
  30. package/references/vulnerabilities/11-graphql-tests.md +355 -0
  31. package/references/vulnerabilities/12-ssrf-tests.md +396 -0
  32. package/references/vulnerabilities/README.md +148 -0
  33. package/references/workflows.md +192 -0
  34. package/src/index.ts +108 -0
  35. package/tsconfig.json +17 -0
@@ -0,0 +1,425 @@
1
+ # 漏洞验证标准
2
+
3
+ ## 漏洞验证流程
4
+
5
+ ```
6
+ 发现 → 分析 → 验证 → 定级 → 报告
7
+
8
+ ┌─────────────────────────────────┐
9
+ │ 发现 (Discover) │
10
+ │ - 可疑响应差异 │
11
+ │ - 异常状态码 │
12
+ │ - 敏感信息暴露 │
13
+ └─────────────┬───────────────────┘
14
+
15
+ ┌─────────────────────────────────┐
16
+ │ 分析 (Analyze) │
17
+ │ - 多次请求确认差异稳定 │
18
+ │ - 对比正常/异常请求 │
19
+ │ - 排除 WAF/路由/认证 │
20
+ └─────────────┬───────────────────┘
21
+
22
+ ┌─────────────────────────────────┐
23
+ │ 验证 (Verify) │
24
+ │ - 10 维度检查 │
25
+ │ - 证据收集 │
26
+ │ - 确认或排除 │
27
+ └─────────────┬───────────────────┘
28
+
29
+ ┌─────────────────────────────────┐
30
+ │ 定级 (Severity) │
31
+ │ - CVSS 评分 │
32
+ │ - 业务影响评估 │
33
+ │ - 修复优先级 │
34
+ └─────────────┬───────────────────┘
35
+
36
+ ┌─────────────────────────────────┐
37
+ │ 报告 (Report) │
38
+ │ - 漏洞详情 │
39
+ │ - 复现步骤 │
40
+ │ - 修复建议 │
41
+ └─────────────────────────────────┘
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 10 维度验证检查表
47
+
48
+ | 维度 | 检查项 | 通过条件 | 典型误报 |
49
+ |------|--------|----------|----------|
50
+ | **D1 响应类型** | 是 JSON 还是 HTML? | JSON 响应包含业务数据 | HTML 页面 (WAF/SPA) |
51
+ | **D2 状态码** | 状态码是否合理? | 与漏洞场景匹配 | 302 重定向 |
52
+ | **D3 响应长度** | 响应长度是否正常? | 长度 > 100 字节 | 过短响应 (拦截) |
53
+ | **D4 WAF 识别** | 是否为 WAF 拦截? | 无 WAF 特征 | HTML 拦截页 |
54
+ | **D5 敏感信息** | 是否包含敏感字段? | 字段不属于测试数据 | 测试假数据 |
55
+ | **D6 一致性** | 多次请求是否一致? | 多次响应相同 | 不稳定响应 |
56
+ | **D7 SQL 注入** | 是否包含 SQL 错误? | 无 SQL 错误特征 | 通用错误信息 |
57
+ | **D8 IDOR** | 是否返回他人数据? | 返回数据属于他人 | 返回自己的数据 |
58
+ | **D9 认证绕过** | 是否返回 token/session? | Token 有效且可用 | 无效/过期 Token |
59
+ | **D10 信息泄露** | 是否泄露非公开信息? | 信息非公开 | 公开信息 |
60
+
61
+ ---
62
+
63
+ ## 各类型漏洞验证标准
64
+
65
+ ### SQL 注入
66
+
67
+ ```python
68
+ # 验证标准
69
+ SQLI_VERIFICATION = {
70
+ # 必须满足
71
+ 'required': [
72
+ '响应包含数据库错误信息',
73
+ 'UNION 查询有回显',
74
+ '时间盲注有延迟',
75
+ ],
76
+ # 参考指标
77
+ 'indicators': [
78
+ '错误信息包含 SQL 关键词',
79
+ '响应时间 > 5秒 (盲注)',
80
+ '页面结构与正常响应不同 (UNION)',
81
+ ],
82
+ # 排除条件
83
+ 'exclude': [
84
+ '通用错误信息 (无 SQL 关键词)',
85
+ 'WAF 拦截页面',
86
+ '响应时间正常但无其他特征',
87
+ ]
88
+ }
89
+
90
+ # 验证步骤
91
+ def verify_sqli(url, param, payload):
92
+ # 1. 原始请求 (基线)
93
+ baseline = requests.get(url, params={param: "1"})
94
+
95
+ # 2. 注入测试
96
+ inject = requests.get(url, params={param: payload})
97
+
98
+ # 3. 对比分析
99
+ indicators = {
100
+ 'sql_error': contains_sql_error(inject.text),
101
+ 'response_diff': baseline.text != inject.text,
102
+ 'data_leak': extract_data(inject.text), # UNION 注入时
103
+ 'time_delay': measure_time(inject), # 盲注时
104
+ }
105
+
106
+ # 4. 综合判断
107
+ if indicators['sql_error'] or indicators['data_leak'] or indicators['time_delay'] > 5:
108
+ return True, indicators
109
+ return False, indicators
110
+ ```
111
+
112
+ ### XSS
113
+
114
+ ```python
115
+ # 验证标准
116
+ XSS_VERIFICATION = {
117
+ 'required': [
118
+ 'Payload 未经处理回显',
119
+ '可执行 JavaScript',
120
+ ],
121
+ 'indicators': [
122
+ 'Payload 在响应中完整回显',
123
+ '<script> 标签未转义',
124
+ '事件处理器未被过滤',
125
+ ],
126
+ 'exclude': [
127
+ 'HTML 实体转义',
128
+ '<script> 被删除/过滤',
129
+ 'CSP 阻止执行',
130
+ ]
131
+ }
132
+
133
+ # 验证步骤
134
+ def verify_xss(url, param, payload):
135
+ # 1. 发送 XSS Payload
136
+ resp = requests.get(url, params={param: payload})
137
+
138
+ # 2. 检查回显
139
+ if payload in resp.text:
140
+ # 3. 检查是否是存储型
141
+ # 用另一请求检查是否持久化
142
+ resp2 = requests.get(url) # 再次访问
143
+
144
+ if payload in resp2.text:
145
+ return True, {'type': 'stored', 'persisted': True}
146
+ return True, {'type': 'reflected', 'persisted': False}
147
+
148
+ return False, {'type': None}
149
+ ```
150
+
151
+ ### IDOR
152
+
153
+ ```python
154
+ # 验证标准
155
+ IDOR_VERIFICATION = {
156
+ 'required': [
157
+ '用自己的 Token 访问他人资源',
158
+ '返回他人敏感数据',
159
+ ],
160
+ 'indicators': [
161
+ '资源 ID 可枚举',
162
+ '响应包含不同用户数据',
163
+ '无权限检查错误',
164
+ ],
165
+ 'exclude': [
166
+ '返回 401/403',
167
+ '返回空数据',
168
+ '返回自己的数据',
169
+ ]
170
+ }
171
+
172
+ # 验证步骤
173
+ def verify_idor(base_url, token, victim_resource_id):
174
+ # 1. 自己的资源 (基线)
175
+ headers = {'Authorization': f'Bearer {token}'}
176
+ my_resource = requests.get(
177
+ f'{base_url}/resource/1',
178
+ headers=headers
179
+ )
180
+
181
+ # 2. 他人的资源 (测试)
182
+ victim_resource = requests.get(
183
+ f'{base_url}/resource/{victim_resource_id}',
184
+ headers=headers
185
+ )
186
+
187
+ # 3. 对比分析
188
+ if victim_resource.status_code == 200:
189
+ my_data = my_resource.json()
190
+ victim_data = victim_resource.json()
191
+
192
+ # 检查是否是不同用户的数据
193
+ if my_data.get('userId') != victim_data.get('userId'):
194
+ return True, {
195
+ 'my_user': my_data.get('userId'),
196
+ 'victim_user': victim_data.get('userId'),
197
+ 'leaked_fields': list(victim_data.keys())
198
+ }
199
+
200
+ return False, {'status': victim_resource.status_code}
201
+ ```
202
+
203
+ ### JWT 漏洞
204
+
205
+ ```python
206
+ # 验证标准
207
+ JWT_VERIFICATION = {
208
+ 'alg_none': {
209
+ 'required': ['使用 alg:none 的 Token 可正常使用'],
210
+ 'test': '去除签名的 Token 可通过验证',
211
+ },
212
+ 'key_confusion': {
213
+ 'required': ['使用公钥作为对称密钥可伪造 Token'],
214
+ 'test': 'RS256 算法可被转换为 HS256',
215
+ },
216
+ 'weak_secret': {
217
+ 'required': ['弱密钥可被暴力破解'],
218
+ 'test': '常见密钥可成功签名',
219
+ },
220
+ 'kid_injection': {
221
+ 'required': ['kid 参数存在 SQL/NoSQL 注入'],
222
+ 'test': '利用 kid 注入读取任意密钥',
223
+ },
224
+ }
225
+
226
+ def verify_jwt_alg_none(token):
227
+ header = decode_header(token)
228
+ if header.get('alg') == 'none':
229
+ # 尝试去除签名
230
+ unsigned_token = create_unsigned_token(header, payload)
231
+ if is_valid(unsigned_token):
232
+ return True, {'alg': 'none', 'exploitable': True}
233
+ return False, {}
234
+ ```
235
+
236
+ ### 敏感信息泄露
237
+
238
+ ```python
239
+ # 验证标准
240
+ SENSITIVE_DATA_VERIFICATION = {
241
+ 'password': {
242
+ 'required': ['响应包含明文密码'],
243
+ 'severity': 'Critical',
244
+ 'exclude': ['密码已加密/哈希', '测试数据密码'],
245
+ },
246
+ 'token': {
247
+ 'required': ['响应包含有效 Token'],
248
+ 'severity': 'High',
249
+ 'exclude': ['过期 Token', '测试 Token'],
250
+ },
251
+ 'api_key': {
252
+ 'required': ['响应包含有效 API 密钥'],
253
+ 'severity': 'High',
254
+ 'exclude': ['测试环境密钥'],
255
+ },
256
+ 'internal_ip': {
257
+ 'required': ['响应包含内网 IP 地址'],
258
+ 'severity': 'Medium',
259
+ },
260
+ 'internal_url': {
261
+ 'required': ['响应包含内部系统 URL'],
262
+ 'severity': 'Medium',
263
+ },
264
+ }
265
+
266
+ def verify_sensitive_data(resp, field_name):
267
+ sensitive_fields = {
268
+ 'password', 'passwd', 'pwd', 'secret',
269
+ 'token', 'api_key', 'apikey', 'private_key',
270
+ 'ssn', 'id_card', 'phone', 'email',
271
+ }
272
+
273
+ if field_name.lower() in sensitive_fields:
274
+ # 检查值是否存在
275
+ value = resp.json().get(field_name)
276
+ if value and value not in ['', 'null', 'undefined']:
277
+ return True, {'field': field_name, 'severity': get_severity(field_name)}
278
+
279
+ return False, {}
280
+ ```
281
+
282
+ ---
283
+
284
+ ## 误报排除规则
285
+
286
+ ### 规则 1: WAF 识别
287
+
288
+ ```python
289
+ WAF_PATTERNS = [
290
+ # 通用 WAF
291
+ r'(?i)(waf|firewall|attack|blocked|intercepted)',
292
+ r'(?i)(forbidden|access.*denied|security)',
293
+ # 特定 WAF
294
+ r'Aliyun',
295
+ r'Tencet',
296
+ r'AWS.*WAF',
297
+ r'Cloudflare',
298
+ r'Incapsula',
299
+ ]
300
+
301
+ def is_waf_response(resp):
302
+ content = resp.text
303
+ for pattern in WAF_PATTERNS:
304
+ if re.search(pattern, content):
305
+ return True
306
+ return False
307
+ ```
308
+
309
+ ### 规则 2: SPA 路由识别
310
+
311
+ ```python
312
+ SPA_PATTERNS = [
313
+ r'<div id="app">',
314
+ r'<div id="root">',
315
+ r'__VUE__',
316
+ r'__NUXT__',
317
+ r'ReactDOM',
318
+ r'webpack',
319
+ ]
320
+
321
+ def is_spa_response(resp):
322
+ content = resp.text
323
+ for pattern in SPA_PATTERNS:
324
+ if re.search(pattern, content):
325
+ return True
326
+ return False
327
+ ```
328
+
329
+ ### 规则 3: 统一错误页识别
330
+
331
+ ```python
332
+ ERROR_PAGE_PATTERNS = [
333
+ r'页面不存在|404 Not Found',
334
+ r'服务器错误|500 Internal Server Error',
335
+ r'请求超时|Timeout',
336
+ ]
337
+
338
+ def is_error_page(resp):
339
+ for pattern in ERROR_PAGE_PATTERNS:
340
+ if re.search(pattern, resp.text):
341
+ return True
342
+ return False
343
+ ```
344
+
345
+ ---
346
+
347
+ ## 验证结果记录
348
+
349
+ ### 漏洞验证报告模板
350
+
351
+ ```markdown
352
+ ## 漏洞验证记录
353
+
354
+ ### 基本信息
355
+ - **漏洞类型**: SQL 注入
356
+ - **测试目标**: GET /api/user?id=1
357
+ - **测试时间**: 2026-04-03 10:30:00
358
+ - **验证人员**: Agent
359
+
360
+ ### 验证过程
361
+ 1. **原始请求**
362
+ - 请求: GET /api/user?id=1
363
+ - 响应: 200 OK, {"userId": 1, "name": "张三"}
364
+
365
+ 2. **Payload 测试**
366
+ - Payload: 1' OR '1'='1
367
+ - 请求: GET /api/user?id=1' OR '1'='1
368
+ - 响应: 200 OK, {"userId": 1, "name": "张三"}
369
+ - 响应: [{"userId": 1}, {"userId": 2}, {"userId": 3}]
370
+
371
+ 3. **对比分析**
372
+ - 原始响应: 1 条记录
373
+ - 注入响应: 3 条记录
374
+ - **差异确认**: 存在 SQL 注入
375
+
376
+ ### 维度评分
377
+ | 维度 | 得分 | 说明 |
378
+ |------|------|------|
379
+ | D1 响应类型 | 15/15 | JSON 响应正常 |
380
+ | D2 状态码 | 15/15 | 200 OK |
381
+ | D3 响应长度 | 18/20 | 长度增加 |
382
+ | D4 WAF | 20/20 | 无 WAF 特征 |
383
+ | D5 敏感信息 | 15/20 | 数据泄露 |
384
+ | D6 一致性 | 15/15 | 多次一致 |
385
+ | D7 SQL注入 | 25/25 | 确认注入 |
386
+ | D8 IDOR | 15/15 | N/A |
387
+ | D9 认证绕过 | 15/15 | N/A |
388
+ | D10 信息泄露 | 10/20 | 泄露用户列表 |
389
+
390
+ ### 最终结论
391
+ - **漏洞确认**: ✅ 是
392
+ - **CVSS**: 8.6 (High)
393
+ - **风险等级**: High
394
+ ```
395
+
396
+ ---
397
+
398
+ ## 验证检查清单
399
+
400
+ ```
401
+ □ 基础验证
402
+ □ 多次请求确认差异稳定
403
+ □ 对比正常/异常响应
404
+ □ 排除 WAF/安全设备
405
+ □ 排除 SPA 路由
406
+ □ 排除测试数据
407
+
408
+ □ 类型验证
409
+ □ SQL 注入: 数据库错误/数据泄露/时间延迟
410
+ □ XSS: Payload 回显/JavaScript 执行
411
+ □ IDOR: 跨用户数据访问
412
+ □ JWT: 算法攻击/密钥破解
413
+ □ SSRF: 内网访问/元数据获取
414
+
415
+ □ 证据收集
416
+ □ 请求/响应截图
417
+ □ Payload 记录
418
+ □ 时间戳记录
419
+ □ 关键响应内容
420
+
421
+ □ 定级评估
422
+ □ CVSS 计算
423
+ □ 业务影响评估
424
+ □ 修复优先级
425
+ ```