WIKI

15.3 随机数生成漏洞

(1)描述

SecureRandom的使用不当会导致生成的随机数可被预测,该漏洞存在于Android系统随机生成数字串安全密钥的环节中。该漏洞的生成原因是对SecureRandom类的不正确使用方式导致生成的随机数不随机。

 

(2)风险等级

(3)影响范围

Android 4.2之前,Android API 17以后SecureRandom的默认实现方式从Cipher.RSA换到了OpenSSLSecureRandom新的实现方式不能将自己的seed替换掉系统的seed

(4)检测方法

检测类型:静态分析

检测是否调用了SecureRandom(byte[]seed)或者setSeed(long seed)setSeed(byte[]seed)方法。

 

Ljava/security/SecureRandom;-><init>([B)V

Ljava/security/SecureRandom;->setSeed([B)V

Ljava/security/SecureRandom;->setSeed(J)V

 

例如:

SecureRandom secureRandom = new SecureRandom();

        byte[] b = new byte[] { (byte) 1 };

        secureRandom.setSeed(b);

        // Prior to Android 4.2, the next line would always return the same number!

        Log.v("wgc","-------------------------------");

        Log.v("wgc","Test1:" + secureRandom.nextInt());

       

        SecureRandom secureRandom2 = new SecureRandom(new byte[] { (byte) 1 });

        Log.v("wgc","Test2:" + secureRandom2.nextInt());

       

        SecureRandom secureRandom3 = new SecureRandom();

        secureRandom3.setSeed(10L);

        Log.v("wgc","Test3:" + secureRandom3.nextInt());

       

        SecureRandom secureRandom4 = new SecureRandom();

        secureRandom4.nextBytes(b);

        secureRandom4.setSeed(10L);

        Log.v("wgc","Test4:" + secureRandom4.nextInt());

       

        SecureRandom secureRandom5 = new SecureRandom();

        Log.v("wgc","Test5:" + secureRandom4.nextInt());

可见只有方法4和方法5才真正做到了随机值。

(5)修复建议

ü  不要使用自定义随机源代替系统默认随机源(推荐)除非有特殊需求,在使用SecureRandom类时,不要调用以下函数:SecureRandom类下SecureRandom(byte[]seed)setSeed(long seed)setSeed(byte[]seed)方法。

ü  在调用setSeed方法前先调用任意nextXXX方法。具体做法是调用setSeed方法前先调用一次SecureRandom#nextBytes(byte[]bytes)方法,可以避免默认随机源被替代,详细见参考资料。

(6)参考资料

ü  https://developer.android.com/reference/java/security/SecureRandom.html

ü  http://drops.wooyun.org/papers/5164

ü  http://jaq.alibaba.com/blog.htm?id=47