opencode-api-security-testing 5.0.0 → 5.2.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 (28) hide show
  1. package/package.json +48 -48
  2. package/postinstall.mjs +40 -69
  3. package/references/references/README.md +0 -72
  4. package/references/references/asset-discovery.md +0 -119
  5. package/references/references/fuzzing-patterns.md +0 -129
  6. package/references/references/graphql-guidance.md +0 -108
  7. package/references/references/intake.md +0 -84
  8. package/references/references/pua-agent.md +0 -192
  9. package/references/references/report-template.md +0 -156
  10. package/references/references/rest-guidance.md +0 -76
  11. package/references/references/severity-model.md +0 -76
  12. package/references/references/test-matrix.md +0 -86
  13. package/references/references/validation.md +0 -78
  14. package/references/references/vulnerabilities/01-sqli-tests.md +0 -1128
  15. package/references/references/vulnerabilities/02-user-enum-tests.md +0 -423
  16. package/references/references/vulnerabilities/03-jwt-tests.md +0 -499
  17. package/references/references/vulnerabilities/04-idor-tests.md +0 -362
  18. package/references/references/vulnerabilities/05-sensitive-data-tests.md +0 -466
  19. package/references/references/vulnerabilities/06-biz-logic-tests.md +0 -501
  20. package/references/references/vulnerabilities/07-security-config-tests.md +0 -511
  21. package/references/references/vulnerabilities/08-brute-force-tests.md +0 -457
  22. package/references/references/vulnerabilities/09-vulnerability-chains.md +0 -465
  23. package/references/references/vulnerabilities/10-auth-tests.md +0 -537
  24. package/references/references/vulnerabilities/11-graphql-tests.md +0 -355
  25. package/references/references/vulnerabilities/12-ssrf-tests.md +0 -396
  26. package/references/references/vulnerabilities/README.md +0 -148
  27. package/references/references/workflows.md +0 -192
  28. package/src/src/index.ts +0 -535
@@ -1,423 +0,0 @@
1
- # 用户枚举测试
2
-
3
- ## 1. 概述
4
-
5
- 用户枚举(User Enumeration)是指通过某些接口可以判断用户名、手机号、邮箱等是否存在于系统中。
6
-
7
- **危险等级**: 中
8
-
9
- ## 2. 测试点识别
10
-
11
- ### 2.1 常见枚举接口
12
-
13
- | 接口模式 | 示例 |
14
- |----------|------|
15
- | 用户查重 | `/user/checkOnlyUser?username=X` |
16
- | 用户存在 | `/user/exist?phone=X` |
17
- | 用户验证 | `/user/validate?email=X` |
18
- | 注册接口 | `/user/register` |
19
- | 登录接口 | `/login` (响应差异) |
20
- | 密码重置 | `/user/resetPassword` |
21
-
22
- ### 2.2 响应差异点
23
-
24
- | 特征 | 说明 |
25
- |------|------|
26
- | 不同错误消息 | "用户不存在" vs "密码错误" |
27
- | 响应码差异 | code=0 vs code=1 |
28
- | 响应时间差异 | 存在用户 vs 不存在 |
29
-
30
- ## 3. 测试方法
31
-
32
- ### 3.1 用户名枚举
33
-
34
- ```bash
35
- # 用户存在
36
- curl "http://api/sys/user/checkOnlyUser?username=admin"
37
- # 响应: {"success":false,"message":"用户账号已存在","code":0,"result":true}
38
-
39
- # 用户不存在
40
- curl "http://api/sys/user/checkOnlyUser?username=notexist"
41
- # 响应: {"success":false,"message":"","code":0,"result":false}
42
- ```
43
-
44
- ### 3.2 手机号枚举
45
-
46
- ```bash
47
- curl "http://api/user/check?phone=13800138000"
48
- curl "http://api/user/existByPhone?phone=13800138000"
49
- curl "http://api/sms/send?phone=13800138000"
50
- ```
51
-
52
- ### 3.3 邮箱枚举
53
-
54
- ```bash
55
- curl "http://api/user/check?email=test@mail.com"
56
- curl "http://api/user/validateEmail?email=test@mail.com"
57
- ```
58
-
59
- ### 3.4 登录接口响应差异
60
-
61
- ```bash
62
- # 用户不存在
63
- POST /api/login
64
- {"username": "notexist", "password": "any"}
65
- # 响应: {"message":"用户不存在"}
66
-
67
- # 密码错误
68
- POST /api/login
69
- {"username": "admin", "password": "wrong"}
70
- # 响应: {"message":"密码错误"}
71
-
72
- # 用户存在但响应相同
73
- POST /api/login
74
- {"username": "notexist", "password": "wrong"}
75
- # 响应: {"message":"用户名或密码错误"} ← 统一消息(安全)
76
- ```
77
-
78
- ### 3.5 注册接口探测
79
-
80
- ```bash
81
- POST /api/user/register
82
- {"username": "admin", "password": "test"}
83
- # 响应: {"message":"该用户已注册"}
84
-
85
- POST /api/user/register
86
- {"username": "newuser", "password": "test"}
87
- # 响应: {"message":"注册成功"}
88
- ```
89
-
90
- ## 4. 枚举用户名字典
91
-
92
- ### 4.1 常见管理员账号
93
-
94
- ```
95
- admin, administrator, root, user, manager
96
- sysadmin, system, security, backup
97
- admin1, admin123, admin888
98
- root1, root123
99
- administrator, adminitrator (拼写错误)
100
- ```
101
-
102
- ### 4.2 常见测试账号
103
-
104
- ```
105
- test, test1, test123, tester
106
- demo, demo1
107
- guest, visitor
108
- default
109
- ```
110
-
111
- ### 4.3 业务相关账号
112
-
113
- ```
114
- owner, operator, developer
115
- support, helpdesk
116
- noreply, no-reply
117
- ```
118
-
119
- ## 5. 防护绕过
120
-
121
- ### 5.1 大小写混淆
122
-
123
- ```bash
124
- username=Admin
125
- username=ADMIN
126
- username=AdMiN
127
- ```
128
-
129
- ### 5.2 特殊字符
130
-
131
- ```bash
132
- username=admin
133
- username=admin\
134
- username=admin"
135
- username=admin<>
136
- ```
137
-
138
- ### 5.3 时间差异规避
139
-
140
- ```bash
141
- # 多次请求间增加延迟
142
- sleep 1
143
- curl "http://api/user/check?username=admin"
144
- ```
145
-
146
- ## 6. 关联漏洞
147
-
148
- | 后续漏洞 | 利用路径 |
149
- |----------|----------|
150
- | 暴力破解 | 确认用户名 → 定向爆破密码 |
151
- | 密码重置 | 利用已确认的用户 → 重置密码 |
152
- | 社会工程学 | 利用确认的手机号/邮箱 → 钓鱼攻击 |
153
-
154
- ## 7. 测试检查清单
155
-
156
- ```
157
- □ 测试用户查重接口(/user/checkOnlyUser)
158
- □ 测试手机号查重接口
159
- □ 测试邮箱查重接口
160
- □ 测试登录接口响应差异
161
- □ 测试注册接口探测
162
- □ 枚举常见管理员账号
163
- □ 枚举常见测试账号
164
- □ 测试大小写绕过
165
- □ 测试特殊字符绕过
166
- □ 判断响应差异是否可利用
167
- □ 评估漏洞风险和影响
168
- ```
169
-
170
- ## 8. 误报判断标准
171
-
172
- ### 8.1 核心判断原则
173
-
174
- ```
175
- 【重要】响应差异 ≠ 用户枚举漏洞!
176
-
177
- 判断逻辑:
178
- 1. 先获取正常响应基准
179
- 2. 对比有效用户和无效用户的响应
180
- 3. 差异必须是"明确的用户存在/不存在指示"
181
-
182
- 【真实漏洞特征】
183
- - 明确区分"用户不存在"和"密码错误"
184
- - 响应中直接包含"用户已存在"等字样
185
- - 响应时间有明显差异(数据库查询 vs 直接返回)
186
-
187
- 【误报特征】
188
- - 有效/无效用户返回相同错误消息
189
- - 响应差异只是"参数格式校验"失败
190
- - WAF拦截导致的响应差异
191
- ```
192
-
193
- ### 8.2 curl + 对比验证流程
194
-
195
- ```bash
196
- # 1. 【必须先执行】获取正常响应基准
197
- curl -s -X POST http://api/login \
198
- -H "Content-Type: application/json" \
199
- -d '{"username":"admin","password":"wrong"}' > enum_baseline.json
200
-
201
- # 2. 测试可能存在的用户
202
- curl -s -X POST http://api/login \
203
- -H "Content-Type: application/json" \
204
- -d '{"username":"admin","password":"wrong"}' > enum_test1.json
205
-
206
- # 3. 测试不存在的用户
207
- curl -s -X POST http://api/login \
208
- -H "Content-Type: application/json" \
209
- -d '{"username":"nonexist_abc123","password":"wrong"}' > enum_test2.json
210
-
211
- # 4. 对比两次响应
212
- diff enum_baseline.json enum_test1.json
213
- # 应该完全相同(如果都返回"用户名或密码错误")
214
-
215
- diff enum_baseline.json enum_test2.json
216
- # 判断:
217
- # - 完全相同 → 不是用户枚举漏洞(安全)
218
- # - 有明显差异 → 可能是用户枚举漏洞
219
- ```
220
-
221
- ### 8.3 多维度判断矩阵
222
-
223
- | 场景 | 响应A | 响应B | 差异 | 判断 |
224
- |------|-------|-------|------|------|
225
- | 正常 | {"msg":"用户名或密码错误"} | {"msg":"用户名或密码错误"} | 无 | ✅ 安全 |
226
- | 正常 | {"msg":"用户名或密码错误"} | {"msg":"用户不存在"} | 有 | ⚠️ 可能漏洞 |
227
- | 误报 | {"msg":"参数格式错误"} | {"msg":"用户名或密码错误"} | 有 | ❌ 误报(格式校验) |
228
- | 误报 | {"msg":"请输入密码"} | {"msg":"密码错误"} | 有 | ❌ 误报(字段缺失) |
229
-
230
- ### 8.4 Python脚本(复杂场景)
231
-
232
- ```python
233
- import requests
234
- import json
235
-
236
- class UserEnumTester:
237
- def __init__(self, target):
238
- self.target = target
239
- self.baseline = None
240
-
241
- def get_baseline(self):
242
- """获取正常响应基准(无效用户)"""
243
- resp = requests.post(
244
- f"{self.target}/login",
245
- json={"username": "nonexist_abc123", "password": "wrong"},
246
- headers={"Content-Type": "application/json"}
247
- )
248
- self.baseline = resp.json()
249
- return self.baseline
250
-
251
- def is_user_exists(self, username):
252
- """
253
- 测试用户是否存在
254
-
255
- Returns:
256
- (exists, reason, response)
257
- - exists: True/False/Unknown
258
- - reason: 判断原因
259
- - response: 完整响应
260
- """
261
- resp = requests.post(
262
- f"{self.target}/login",
263
- json={"username": username, "password": "wrong"},
264
- headers={"Content-Type": "application/json"}
265
- )
266
-
267
- if resp.status_code != 200:
268
- return False, "HTTP错误", resp
269
-
270
- try:
271
- data = resp.json()
272
- except:
273
- return False, "非JSON响应", resp
274
-
275
- # 检查响应是否与基准完全相同
276
- if self.baseline and data == self.baseline:
277
- return False, "响应与基准相同(可能是安全)", data
278
-
279
- # 检查是否有明确的用户存在指示
280
- msg = data.get('msg', '').lower()
281
- code = str(data.get('code', ''))
282
-
283
- # 用户不存在的指示
284
- not_exist_keywords = ['不存在', 'not exist', 'not found', '用户不存在']
285
- # 用户存在的指示
286
- exist_keywords = ['已存在', 'exist', '用户已注册', '密码错误', '密码不匹配']
287
-
288
- for kw in not_exist_keywords:
289
- if kw in msg:
290
- return False, f"响应包含'{kw}',用户可能不存在", data
291
-
292
- for kw in exist_keywords:
293
- if kw in msg:
294
- return True, f"响应包含'{kw}',用户可能存在", data
295
-
296
- # 检查响应码差异
297
- if self.baseline:
298
- if data.get('code') != self.baseline.get('code'):
299
- return None, f"响应码不同(A:{self.baseline.get('code')} B:{data.get('code')})", data
300
-
301
- return None, "响应有差异但无法判断", data
302
-
303
- def run_tests(self, usernames):
304
- """批量测试用户枚举"""
305
- print(f"\n=== 用户枚举测试 ===\n")
306
-
307
- # 获取基准
308
- self.get_baseline()
309
- print(f"基准响应: {self.baseline}\n")
310
-
311
- results = {'exists': [], 'not_exists': [], 'unknown': []}
312
-
313
- for username in usernames:
314
- exists, reason, resp = self.is_user_exists(username)
315
-
316
- if exists is True:
317
- results['exists'].append({
318
- 'username': username,
319
- 'reason': reason,
320
- 'response': resp
321
- })
322
- print(f"[存在] {username}: {reason}")
323
- elif exists is False:
324
- results['not_exists'].append({
325
- 'username': username,
326
- 'reason': reason,
327
- 'response': resp
328
- })
329
- print(f"[不存在] {username}: {reason}")
330
- else:
331
- results['unknown'].append({
332
- 'username': username,
333
- 'reason': reason,
334
- 'response': resp
335
- })
336
- print(f"[未知] {username}: {reason}")
337
-
338
- return results
339
-
340
- # 使用示例
341
- if __name__ == "__main__":
342
- tester = UserEnumTester("http://api")
343
-
344
- test_users = [
345
- 'admin', 'administrator', 'root', 'user', 'test',
346
- 'demo', 'guest', 'nonexist_abc123', 'superadmin'
347
- ]
348
-
349
- results = tester.run_tests(test_users)
350
-
351
- print(f"\n=== 测试结果汇总 ===")
352
- print(f"存在: {len(results['exists'])}个")
353
- print(f"不存在: {len(results['not_exists'])}个")
354
- print(f"未知: {len(results['unknown'])}个")
355
-
356
- # 如果存在unknown,需要进一步分析
357
- if results['unknown']:
358
- print(f"\n[注意] 存在{len(results['unknown'])}个无法确认的用户")
359
- print("建议:人工分析这些用户的响应,确定是否为漏洞")
360
- ```
361
-
362
- ## 9. 实战判断案例
363
-
364
- ### 案例1:安全的登录接口
365
-
366
- ```
367
- 【场景】:所有用户名返回相同错误消息
368
-
369
- curl测试:
370
- curl -X POST /api/login -d '{"username":"admin","password":"wrong"}'
371
- → {"code":"90000","msg":"用户名或密码错误。"}
372
-
373
- curl -X POST /api/login -d '{"username":"nonexist","password":"wrong"}'
374
- → {"code":"90000","msg":"用户名或密码错误。"}
375
-
376
- 判断:
377
- - 响应完全相同
378
- - 结论:【安全】不是用户枚举漏洞
379
- ```
380
-
381
- ### 案例2:真实用户枚举
382
-
383
- ```
384
- 【场景】:有效/无效用户返回不同消息
385
-
386
- curl测试:
387
- curl -X POST /api/login -d '{"username":"admin","password":"wrong"}'
388
- → {"code":"90001","msg":"密码错误,用户账号存在。"}
389
-
390
- curl -X POST /api/login -d '{"username":"nonexist","password":"wrong"}'
391
- → {"code":"90002","msg":"用户不存在。"}
392
-
393
- 判断:
394
- - 有效用户:"密码错误,用户账号存在"
395
- - 无效用户:"用户不存在"
396
- - 结论:【确认漏洞】可枚举有效用户
397
- ```
398
-
399
- ### 案例3:参数格式校验误报
400
-
401
- ```
402
- 【场景】:响应差异但不是用户枚举
403
-
404
- curl测试:
405
- curl -X POST /api/login -d '{"username":"","password":""}'
406
- → {"code":"90003","msg":"参数不能为空。"}
407
-
408
- curl -X POST /api/login -d '{"username":"admin","password":"wrong"}'
409
- → {"code":"90000","msg":"用户名或密码错误。"}
410
-
411
- 判断:
412
- - 差异是"参数为空" vs "用户名或密码错误"
413
- - 这是参数格式校验,不是用户枚举
414
- - 结论:【误报】需要填充有效用户名再测试
415
- ```
416
-
417
- ## 10. 风险评估
418
-
419
- | 风险级别 | 条件 |
420
- |----------|------|
421
- | 高 | 可快速枚举大量用户/邮箱,无限制 |
422
- | 中 | 有一定限制但可枚举个 |
423
- | 低 | 有严格限制但仍可枚举 |