当前位置:首页 > 综合

openssl des漏洞

2016年那会儿,漏洞我还在做安全审计,漏洞有天凌晨被叫起来处理一个线上事故。漏洞某金融客户的漏洞VPN网关突然大面积不可用,日志里刷屏的漏洞报错都指向同一个东西——OpenSSL的DES加密握手失败。当时第一反应是漏洞证书问题,排查了两小时才发现,漏洞根源在OpenSSL 1.0.1系列里DES相关的漏洞一个实现缺陷。那是漏洞我第一次真切感受到,一个上世纪七十年代设计的漏洞加密算法,到了移动互联网时代还能以这种方式把人从床上拽起来。漏洞

DES本身的漏洞问题其实早就不是秘密。56位的漏洞有效密钥长度,在1998年就被EFF用一台25万美元的漏洞机器在56小时内暴力破解了。到了今天,漏洞用GPU集群跑DES,几小时甚至几分钟就能出结果。但问题在于,OpenSSL作为基础设施,不能简单地把DES删掉了事。大量老旧的嵌入式设备、工业控制系统、甚至某些银行后台的遗留模块,还在依赖DES和3DES做通信加密。你把它砍了,这些系统直接瘫痪。所以OpenSSL团队选择的是保留但限制,而这个过程中就埋下了不少坑。

那个被反复利用的“Sweet32”

2016年公开的CVE-2016-2183,也就是Sweet32攻击,算是OpenSSL DES相关漏洞里影响最广的一个。原理不复杂:3DES的块大小只有64位,当同一密钥加密的数据量超过约32GB时,生日悖论会让密文块发生碰撞,攻击者就能通过大量流量分析还原出明文。听起来32GB很大?在HTTPS长连接场景下,一台高流量的服务器几个小时内就能达到这个量级。更麻烦的是,OpenSSL当时对3DES的默认使用没有任何数据量限制,也不会主动警告。很多运维根本不知道自己的服务在跑3DES,直到被扫出来。

我后来在内部做了一次扫描,发现公司里至少17个对外服务还在用3DES套件,其中三个是核心支付网关。修复方案倒不复杂,在cipher list里禁用DES和3DES就行,但改配置之前得先确认没有客户端依赖它。结果一查,两个老版本的Android客户端确实只支持3DES,升级客户端又涉及发版和用户更新,拖了将近半年才彻底切干净。

OpenSSL代码里的DES实现细节

OpenSSL的DES实现主要在crypto/des/目录下,里面有一堆看起来像天书的S-box查表和位运算。早期版本里,DES_encrypt1和DES_encrypt2这两个函数在处理输入输出时,对某些边界条件的检查不够严谨。比如当输入长度不是8字节整数倍时,部分代码路径会读取超出缓冲区末尾的数据,虽然不一定会导致崩溃,但在特定内存布局下可能泄露栈上的敏感信息。这类问题在2014-2018年间被不同研究者反复报告过,OpenSSL的修复方式通常是加长度校验,但每次改动都可能影响性能,而DES的性能本来就不怎么样。

还有个更隐蔽的问题:OpenSSL支持多种DES模式,ECB、CBC、CFB、OFB。ECB模式在API层面没有强制禁止,只是文档里建议不要用。结果就是,直到今天,你还能在一些开源项目的代码里看到EVP_des_ecb()的调用。ECB模式下相同的明文块会产生相同的密文块,对于结构化数据来说,这等于把信息直接暴露出来。我见过一个日志加密模块,用DES-ECB加密JSON日志,攻击者不需要密钥就能推断出日志的字段结构和部分内容。

实际运维中的坑

禁用DES这件事,在OpenSSL层面操作起来不算难。修改openssl.cnf里的CipherString,或者在代码里设置SSL_CTX_set_cipher_list排除DES相关套件。但坑在于,很多中间件和框架会自己维护一份cipher list,比如某些版本的Nginx、Tomcat、Node.js的TLS模块,它们可能硬编码了包含3DES的默认列表。你改了系统OpenSSL配置,应用层不生效。更离谱的是,有些Java应用通过JSSE调用OpenSSL,而JSSE的cipher策略又跟JDK版本绑定,升级JDK比升级OpenSSL麻烦得多。

我个人的判断是,DES在OpenSSL里还会存在很长一段时间,因为移除它的破坏性远大于保留它的风险。但每个运维和开发都应该主动检查自己的服务是否还在协商DES/3DES,尤其是在对外暴露的TLS端点上。一个简单的nmap --script ssl-enum-ciphers就能扫出来。别等到被扫出漏洞报告了才动手,那时候往往已经晚了。

分享到: