一、漏洞描述:
摘要:
MD2、MD4、MD5、RIPEMD-160 和 SHA-1 是常用的加密散列算法,通常用于验证消息和其他数据的完整性。然而,由于最近的密码分析研究揭示了这些算法中存在的根本缺陷,因此它们不应该再用于安全性关键的上下文中。
由于有效破解 MD 和 RIPEMD 散列的技术已得到广泛使用,因此不应该依赖这些算法来保证安全性。对于 SHA-1,目前的破坏技术仍需要极高的计算能力,因此比较难以实现。然而,攻击者已发现了该算法的致命弱点,破坏它的技术可能会导致更快地发起攻击。缺陷描述:
弱加密散列值无法保证数据完整性,且不能在安全性关键的上下文中使用。
二、解决方案:
官方建议:
停止使用 MD2、MD4、MD5、RIPEMD-160 和 SHA-1 对安全性关键的上下文中的数据进行验证。
目前,SHA-224、SHA-256、SHA-384、SHA-512 和 SHA-3 都是不错的备选方案。
但是,由于安全散列算法 (Secure Hash Algorithm) 的这些变体并没有像 SHA-1 那样得到仔细研究,因此请留意可能影响这些算法安全性的未来研究结果。
对于没有上线的系统我们可能还可以采用官方的建议,如果是已经上线并产生了大量数据的系统,针对这种漏洞,我们只能通过更复杂的调用绕过了。。。
临时修复方案:
这里我项目中主要是使用了 Apache 的 commons-codec
编码解码工具包,来实现 md5
加密和 SHA-1
加密。
我们临时处理的方式非常简单,就是通过使用 Hutool
的工具类来替换掉 commons-codec
工具包。
md5加密:
修复前:
import org.apache.commons.codec.digest.DigestUtils;
byte[] md5Bytes = DigestUtils.md5("test".getBytes());
String md5Hex = DigestUtils.md5Hex("test".getBytes());
修复后:
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
byte[] md5Bytes = new Digester(DigestAlgorithm.MD5).digest(pwd);
String md5Hex = new Digester(DigestAlgorithm.MD5).digestHex("test");
SHA-1加密:
修复前:
import org.apache.commons.codec.digest.DigestUtils;
byte[] sha1Bytes = DigestUtils.sha1(System.currentTimeMillis() + "");
String sha1Hex = DigestUtils.sha1Hex(System.currentTimeMillis() + "");
修复后:
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
byte[] sha1Bytes = new Digester(DigestAlgorithm.SHA1).digest(System.currentTimeMillis() + "");
String sha1Hex = new Digester(DigestAlgorithm.SHA1).digestHex(System.currentTimeMillis() + "");
关于 SHA-1 摘要算法我们可以验证一下,并打印下其它 SHA 加密方式看看:
public static void main(String[] args) {
long l = System.currentTimeMillis();
String sha1Hex = DigestUtils.sha1Hex(l + "");
String sha1Hex2 = new Digester(DigestAlgorithm.SHA1).digestHex(l + "");
System.out.println(Objects.equals(sha1Hex, sha1Hex2));
System.out.println("SHA1: " + new Digester(DigestAlgorithm.SHA1).digestHex(l + ""));
System.out.println("SHA256: " + new Digester(DigestAlgorithm.SHA256).digestHex(l + ""));
System.out.println("SHA384: " + new Digester(DigestAlgorithm.SHA384).digestHex(l + ""));
System.out.println("SHA512: " + new Digester(DigestAlgorithm.SHA512).digestHex(l + ""));
}
执行结果:
true
SHA1: a178401f0dc8c03177978bfc5a9e7de7d3b41fdd
SHA256: 8c69e4b1ec8034b4c58c23633986f65ff8d8e159f1775560bf50881ba6030ea7
SHA384: 226d77d64f029eaeb5b5c20e57c5270f0ceedd14e468207e6a30cddc32f96f954e5a225eacf43aca345be1d8629e37b1
SHA512: d0f67ffe5abebf1955762871dc3991e4cddb620b803e32969d09a41457a0c1f273532bbb0a89b94b965ac1dbebb3800ef0f47fd8b40a4d56ddfe8dfb0d684696
我们可以看到替换后的摘要串和之前是一致的,不同SHA加密算法加密后的长度会不一样,而且数字越大加密后的内容越长。
整理完毕,完结撒花~ 🌻