C#随机数生成器漏洞分析与利用

本文详细分析了C#中Random类的安全漏洞,探讨了如何利用系统时钟种子预测密码重置令牌,实现账户接管攻击。文章包含黑盒测试方法和数学逆向分析,提供了完整的漏洞利用方案。

C#随机数生成器漏洞分析与利用

漏洞概述

在C#中,使用new Random().Next(min, max)生成密码重置令牌存在严重安全风险。由于Random类默认使用系统时钟(Environment.TickCount)作为种子,在1毫秒时间窗口内创建的多个Random实例将产生相同的随机数序列。

漏洞代码示例

1
2
3
var num = new Random().Next(min, max);
var token = make_password_reset_token(num);
save_reset_token_to_db(user, token);

C# PRNG工作原理

Random类的参考实现显示,当无参构造函数被调用时:

1
2
3
public Random()
    : this(Environment.TickCount) {
}

内部状态(SeedArray[55])基于32位种子构建。所有PRNG输出都由其种子决定,在这种情况下,种子本质上是时间。

漏洞利用方法

单包攻击

利用Burp Suite的Repeater组功能,在1毫秒时间窗口内同时发送两个密码重置请求:

  • 监控往返时间差异(显示在Burp右下角)
  • 当时间差≤1毫秒时,两个账户将收到相同的重置令牌
  • 通过测试账户验证漏洞存在后,针对管理员账户实施攻击

黑盒测试方法

  1. 创建两个测试账户
  2. 使用Burp Repeater同时发送重置请求
  3. 检查邮件中的令牌是否重复
  4. 确定有效的时间差窗口
  5. 在实际攻击中,仅当时间差在测试范围内时才尝试登录

修复方案

使用加密安全的随机数生成器:

1
2
3
// 使用RandomNumberGenerator替代Random
using System.Security.Cryptography;
var rng = RandomNumberGenerator.Create();

数学逆向分析(进阶)

种子算法数学原理

SeedArray中的操作都是在模MBIGInt32.MaxValue,即2^31-1)下进行的,形成一个伽罗华域。

通过代数运算,可以将任何SeedArray元素表示为:

1
a*Seed + b mod MBIG

csharp_rand.py库功能

该库能够:

  • 预测Random::Next的输出
  • 从输出反推原始种子
  • 在不同输出间建立数学关系

示例:

1
2
3
4
5
>>> from csharp_rand import csharp_rand
>>> cs = csharp_rand()
>>> first = cs.sample_equation(0)
>>> print(first)
rand = seed * 1121899819 + 1559595546 mod 2147483647

整数下流问题

在特定种子值下,原始实现存在整数下流问题,导致某些输出存在"碰撞" - 两个不同的种子产生相同的第13个输出。

结论

这种攻击虽然简单,但危害严重。安全开发中应始终:

  • 查阅文档了解API的安全使用方式
  • 对安全关键操作使用加密安全的RNG
  • 在实际环境中测试"安全"代码
  • 对安全令牌进行模糊测试

该漏洞利用方法不仅适用于C#,也可能影响其他使用类似PRNG实现的编程语言和框架。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计