漏洞 3(核心):弱随机数生成器用于安全敏感值

漏洞 3(核心):弱随机数生成器用于安全敏感值

代码证据

private String generateSessionToken() {
Random random = new Random();
StringBuilder sb = new StringBuilder(16);
for (int i = 0; i < 16; i++) {
sb.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
.charAt(random.nextInt(62)));
}
return sb.toString();
}

出处: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、可量化)