该文主要针对CVE-2020-1971
漏洞,提供的Openssl升级方案。可先翻阅到文末,排查是否有对外服务使用openssl,如果没有,则可不升级。
openssl 1.0.2 用户
Openssl官方提示:OpenSSL 1.0.2 is out of support and no longer receiving public updates. Extended
,也就是说,1.0.2不维护了,不对公众提供支持了。这个时候,我们怎么修复CVE-2020-1971呢?
support is available for premium support customers:
https://www.openssl.org/support/contracts.html
1、官网下载对外发行的1.0.2u版本
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz
2、解压缩
tar -zvxf openssl-1.0.2u.tar.gz
3、下载并替换 crypto/x509v3/v3_genn.c
文件
wget https://purpleroc-blog-8gymra6s96518e6a-1253382304.tcloudbaseapp.com/v3_genn.c -O openssl-1.0.2u/crypto/x509v3/v3_genn.c
或自行修改,文件改动如下:
diff crypto/x509v3/v3_genn.c crypto/x509v3/v3_genn.c_bak110,140d109< static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)< {< int res;<< if (a == NULL || b == NULL) {< /*< * Shouldn't be possible in a valid GENERAL_NAME, but we handle it< * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here< */< return -1;< }< if (a->nameAssigner == NULL && b->nameAssigner != NULL)< return -1;< if (a->nameAssigner != NULL && b->nameAssigner == NULL)< return 1;< /* If we get here then both have nameAssigner set, or both unset */< if (a->nameAssigner != NULL) {< res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);< if (res != 0)< return res;< }< /*< * partyName is required, so these should never be NULL. We treat it in< * the same way as the a == NULL || b == NULL case above< */< if (a->partyName == NULL || b->partyName == NULL)< return -1;<< return ASN1_STRING_cmp(a->partyName, b->partyName);< }<150,152d118< result = ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address);< break;<154,155c120< // result = ASN1_TYPE_cmp(a->d.other, b->d.other);< result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);---> result = ASN1_TYPE_cmp(a->d.other, b->d.other);202,204d166< a->d.x400Address = value;< break;<206,207c168< // a->d.other = value;< a->d.ediPartyName = value;---> a->d.other = value;241,242d201< return a->d.x400Address;<244,245c203< //return a->d.other;< return a->d.ediPartyName;---> return a->d.other;
4、修改版本信息
$ cd openssl-1.0.2used -i 's/OpenSSL 1.0.2u/OpenSSL 1.0.2x Self Change/g' ./crypto/opensslv.h
5、设定Openssl 安装路径
./config --prefix=/usr/local/openssl
6、编译
make
7、安装
make install
8、替换旧版本
mv /usr/bin/openssl /usr/bin/openssl.bakmv /usr/include/openssl /usr/include/openssl.bakln -s /usr/local/openssl/bin/openssl /usr/bin/opensslln -s /usr/local/openssl/include/openssl /usr/include/opensslecho "/usr/local/openssl/lib" >> /etc/ld.so.confldconfig -v
9、查看新Openssl版本
openssl version
返回OpenSSL 1.0.2x Self Change 20 Dec 2019
Openssl 1.1.1 用户
1、下载官方源码
wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_1i.tar.g
2、解压缩
tar -zvxxf OpenSSL_1_1_1i.tar.gz
3、进入源码目录
cd openssl-OpenSSL_1_1_1i/
4、设定Openssl安装目录
./config --prefix=/usr/local/openssl
5、编译
make
6、安装
make install
7、替换旧版本
mv /usr/bin/openssl /usr/bin/openssl.bakmv /usr/include/openssl /usr/include/openssl.bakln -s /usr/local/openssl/bin/openssl /usr/bin/opensslln -s /usr/local/openssl/include/openssl /usr/include/opensslecho "/usr/local/openssl/lib" >> /etc/ld.so.confldconfig -v
8、查看新Openssl版本
$ openssl version
返回OpenSSL 1.1.1i 8 Dec 2020 (Library: OpenSSL 1.1.1g 21 Apr 2020)
更新Openssl之后
更新Openssl后,需要排查对外服务是否静态编译方式使用openssl。这里针对一些对外服务(为啥是对外服务,因为对外受到的攻击可能性更大,只排查对外可以减少工作量)提供一些对外服务的排查方式。
如果是静态编译的,则这些对外服务,需要制定上面更新的openssl库重新编译。
A、Nginx
执行nginx -V
可以看到Nginx是静态编译的Openssl 检测及更新Nginx,参照:https://www.cnblogs.com/unqiang/p/6836090.html
B、OpenSSH
同理,执行ssh -V
检测及更新OpenSSH,参照:https://blog.51cto.com/techsnail/2138927
C、Apache
同理,执行apache2 -V
如果网站支持https的话,还需要判断mod_ssl
是否静态编译openssl。 ldd {apache root}/modules/mod_ssl.so | grep ssl
看libssl.so*
是否指向新编译的 libssl.so*
。如果不是,则需要重新编译mod_ssl
。
更新Apache,参照:https://blog.chenzhang.org/post/dev/upgrading-openssl-for-apache-on-ubuntu/
其余的服务,基本类似操作。