漏洞 3(核心):弱随机数生成器用于安全敏感值
漏洞 3(核心):弱随机数生成器用于安全敏感值
代码证据
private String generateSessionToken() { |
出处:Login.java,第 183-189 行。
逐行解释
| 代码 | 含义 |
|---|---|
new Random() |
创建 Java 的普通随机数生成器 |
StringBuilder sb = new StringBuilder(16) |
准备生成 16 个字符 |
for (int i = 0; i < 16; i++) |
循环 16 次 |
random.nextInt(62) |
从 0-61 里随机挑一个数 |
| 62 字符集 = A-Z(26) + a-z(26) + 0-9(10) | 每次从这 62 个字符里挑一个 |
最终结果: 一个 16 位的随机字符串。
表面上看起来很随机
- 16 位长度
- 看起来可能性很多
- 每次生成的都不一样
但实际上它用的是 java.util.Random
java.util.Random 是 Java
自带的"普通"随机数生成器,不是密码学安全的随机数生成器。
Random 的工作原理(简化版)
种子(seed) → 算法 → 输出 |
Java 的 Random 用的是
线性同余算法(LCG): - 种子是 48 位 -
算法是确定性的 - 知道种子就能算出所有后续值
48 位种子意味着什么
2^48 ≈ 2.8 × 10^14(2.8 万亿)种可能
这个数字看起来很大,但实际上: - 用普通电脑可以在一段时间内枚举完 - 如果攻击者知道算法(通过反编译 APK),可以离线暴力破解 - 甚至不需要实际尝试,只需要在本地计算
为什么这个 App 的 token 特别脆弱
普通随机数不可预测,但这个 token 是"身份凭证":
预测出 token → 直接进入别人账户 |
如果 token 是随机 16 位密码: - 攻击者不知道密码就登不进去
如果 token 是可预测的随机数: - 攻击者不需要密码,只需要预测出 token - 直接绕过登录
和普通"用了不安全 API"的区别
| 场景 | 为什么问题不大 |
|---|---|
| 用 Random 生成一个随机显示颜色 | 预测到了也无所谓 |
| 用 Random 生成 session token | 预测到了 = 冒充别人 |
这就是"Security-Sensitive"的真正含义:
这个随机数的输出结果会直接影响安全。
这就是 CWE-338
CWE-338 — Use of a Broken or Risky Cryptographic Algorithm
用不适合密码学安全场景的随机数生成器,来生成安全敏感的凭证值。
对作业的重要性
这个漏洞是整个 Task 3 的主漏洞,因为: 1. ✅ 直接对应作业 rubric 的 randomness / cryptography 方向 2. ✅ 有具体的代码证据 3. ✅ 有清晰的攻击路径和影响分析 4. ✅ 有技术上的深度(48-bit LCG、可量化)