不安全的hash算法使用风险
漏洞描述:
应用使用如MD5和SHA-1不安全的Hash算法。
漏洞原理:
业界已发现了针对MD5和SHA-1有效的碰撞攻击方法。
示例风险代码如下:
MessageDigest md = MessageDigest.getInstance("MD5"); // 风险代码,使用不安全的HASH算法
try {
md.update(toChapter1);
MessageDigest tc1 = md.clone();
byte[] toChapter1Digest = tc1.digest();
md.update(toChapter2);
…
} catch (CloneNotSupportedException cnse) {
throw new DigestException("couldn't make digest of partial content");
}
修复建议:
使用SHA-256或更高安全等级的Hash算法。
示例代码如下:
MessageDigest md = MessageDigest.getInstance("SHA-256"); // 使用安全的HASH算法
try {
md.update(toChapter1);
MessageDigest tc1 = md.clone();
byte[] toChapter1Digest = tc1.digest();
md.update(toChapter2);
…
} catch (CloneNotSupportedException cnse) {
throw new DigestException("couldn't make digest of partial content");
}
不安全随机数使用风险
漏洞描述:
应用使用随机数时使用不安全的生成方法
漏洞原理:
使用Random方法生成的随机数容易被预测;在种子(seed)固定时,即使SecureRandom生成的随机数也容易被预测
示例风险代码如下:
案例一:
Random localRandom = new Random(System.currentTimeMillis()); // 风险代码:使用不安全的随机数生成器
案例二:
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); // 风险代码:使用安全的随机数生成器,但使用了固定种子
byte[] seed = "hello".getBytes();
sr.setSeed(seed);
修复建议:
使用安全的随机数生成器SecureRandom,并且不要显式的设置种子。
示例代码如下:
byte[] rand = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(rand);
对称加密使用固定IV风险
漏洞描述:
对称加密中使用固定IV(Initial Vector, 初始化向量)
漏洞原理:
对称加密中需要设置IV协助产生密文,如果使用固定的IV,会导致密文的可预测性提高,容易受到字典式攻击。
CBC加密模式容易遭受上述风险攻击。
示例风险代码如下:
IvParameterSpec iv_ = new IvParameterSpec(“1234567890”.getBytes());//风险代码,使用常量vector
修复建议:
在初始化IVParameterSpec时,使用安全随机数生成方式,不使用常量vector
示例代码如下:
Byte[] rand = new byte[16];
SecureRandom r = new SecureRandom();
r.nextBytes(rand);
IvParameterSpec iv = new IvParameterSpec(rand);
根据业务需求,随机IV可随密文一同传输到服务器
固定盐风险
漏洞描述:
在加密过程中, 使用PBE加密算法时采用固定的盐参数
漏洞原理:
PBE(Password Based Encryption)算法是一种基于口令的加密算法,一般使用长度较短的口令和随机生成的盐生成长度较长的盐,如果盐不是随机生成的,则会导致加密强度大大降低,攻击者可采用字典攻击等方式破解。
示例风险代码如下:
KeySpec keySpec = new PBEKeySpec(Constant.PASS.toCharArray(), "0123456789!@#$%^".getBytes(), 1000, 256); //使用固定盐
修复建议:
使用随机化的盐
示例代码如下:
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt); //使用随机盐
KeySpec keySpec = new PBEKeySpec(Constant.PASS.toCharArray(), salt, 1000, 256);
} catch (Exception e) {
//
return e.toString();
}
敏感密钥硬编码漏洞
漏洞描述:
- 应用将对称加密算法使用的密钥硬编码在代码中
- 应用将RSA加密算法使用的私钥硬编码在代码中。
漏洞原理:
- 对称加密算法使用的密钥被硬编码在了代码中,例如:
final byte[] SECRET\_KEY = "0123456789!@#\$%^".getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET\_KEY, "AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT\_MODE, secretKeySpec);
攻击者可以通过反编译找到密钥,导致加密失效。
- 开发者将RSA加密算法的私钥硬编码在了代码中,导致私钥泄露,进而使加密过程失效。
修复建议:
开发功能的编码与实现,不得硬编码敏感密钥或口令。特殊情况,业务需要举证必要性并进行安全评审。
禁止终端应用将敏感密钥或口令直接硬编码写在代码或配置文件中。常见的对称加解密相关的业务场景:
1、终端加密敏感数据,在本地安全存储的场景:在KeyStore中生成对称密钥,同时保证每个设备产生的密钥不一样。终端应用将生成的密钥及时存储在安全模块 KeyStore中。
2、终端加密敏感数据,上传到服务器后台的场景:使用数字信封;
3、终端加密非敏感数据,在本地临时存储的场景:推荐终端使用设备及应用的独立因子,派生出对称密钥进行加密。
另外,开发者使用RSA加密时,本地应使用公钥,而在服务端使用私钥。