16

CVE-2020-0601漏洞分析

 4 years ago
source link: https://www.anquanke.com/post/id/197520
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

iyEnYvu.png!web

0x00 漏洞描述

2020年1月15日,微软公布了1月份的补丁更新列表,其中存在一个位于CryptoAPI椭圆曲线密码(ECC)证书检测绕过相关的漏洞(CVE-2020-0601),该漏洞为NSA发现并汇报给微软。攻击者可以利用这个漏洞,使用伪造的代码签名证书对恶意的可执行文件进行签名,并以此恶意文件来进行攻击。

0x01 补丁分析

从微软的官方介绍上可知,此漏洞存在于crypt32.dll文件。在官方网站下载了补丁文件升级更新后,新的crypt32.dll与未更新的版本对比如下:

MFJnAjR.png!web

从图中可以看出,CertDllVerifyMicrosoftRootCertificateChainPolicy函数存在改动,查看引用该函数的地方:

amUBBny.png!web

从图可知,函数CertVerifyCertificateChainPolicy中有两处调用了CertDllVerifyMicrosoftRootCertificateChainPolicy函数,查看CertVerifyCertificateChainPolicy的代码:

baYFfaY.png!web

从上图代码可知,函数CertVerifyCertificateChainPolicy将四个参数pszPolicyOID, pChainContext, pPolicyPara, pPolicyStatus直接传递给了CertDllVerifyMicrosoftRootCertificateChainPolicy,并未做处理。接着查看CertDllVerifyMicrosoftRootCertificateChainPolicy的代码。

jAbmauQ.png!web

注意到CertDllVerifyMicrosoftRootCertificateChainPolicy函数中有多处形如memcmp(v16, &pbComputedHash, 0x20u)的内存对比代码,其中v16是crypt32.dll某处固定的数据,pbComputedHash是由CryptHashCertificate2函数计算过的hash值,0x20u是指对比的内存长度,刚好是ECC数字签名证书的指纹hash长度,这可以通过查看ECC根证书的详细信息可知。

iAjmE3y.png!web

而CryptHashCertificate2函数传入的值由CertDllVerifyMicrosoftRootCertificateChainPolicy的参数解析而来,并且只包含了公钥信息。由此可以判断,虽然函数CertVerifyCertificateChainPolicy将参数pszPolicyOID, pChainContext, pPolicyPara, pPolicyStatus都传递给了CertDllVerifyMicrosoftRootCertificateChainPolicy函数,但CertDllVerifyMicrosoftRootCertificateChainPolicy函数只利用了其中的公钥信息,存在参数校验不全的逻辑缺陷。至于为什么只校验公钥信息就会被伪造的数字签名绕过检查,在介绍CVE-2020-0601漏洞原理之前,我们先来简单介绍下椭圆曲线数字签名算法(ECDSA)。

0x02 椭圆曲线数字签名算法(ECDSA)

在2009年修订的FIPS 186加入了基于椭圆曲线密码的数字签名方法,称其为椭圆曲线数字签名算法(ECDSA)。由于椭圆曲线密码效率方面的优势,ECDSA的应用越来越广泛。

ECDSA算法过程如下:

  • 参与数字签名的所有方都使用相同的全局域参数,用于定义椭圆曲线以及曲线上的基点。
  • 签名者首先需要生成一对公钥、私钥。签名者可以选择一个随机数作为私钥,使用随机数和基点,可以计算椭圆曲线上的另一个解点,作为公钥。
  • 对于待签名的消息计算其Hash值。签名者使用私钥、全局域参数、Hash值产生签名,包括两个整数r和s。
  • 验证者使用签名者的公钥、全局域参数、整数s作为输入,计算v,并与r比较。如果两者相等,则签名通过。

0x03 漏洞原理

通常,签名者产生一对公私钥后,要去证书中心(certificate authority,简称CA),为公钥做认证,以此来证明签名者本身身份。证书中心用自己的私钥,对签名者的公钥和一些相关信息一起做签名,生成数字证书(Digital Certificate)。由补丁分析部分可知,微软在对数字签名做合法校验时,支持椭圆曲线参数的自定义输入,又只对公钥信息做校验,存在严重缺陷。

攻击者可以传入自定义的全局域参数、签名信息s,只需要公钥信息与系统ECC根证书Microsoft ECC Product Root Certificate Authority 2018的公钥保持一致,就可以绕过校验逻辑,让数字签名信息看起来就是ECC根证书签发的一样。而这,是很容易做到的。

假设ECC根证书的私钥是d(对攻击者未知),基点是G,公钥是Q=dG。攻击者可以选择跟ECC根证书一样的椭圆曲线,只需d’=1(单位元),G‘=Q,则Q‘=d’G’=Q,从而完成攻击。

0x04 漏洞验证

提取ECC根证书公钥信息

QbemErA.png!web

生成伪造的ECC根证书

MBJJZvq.png!web

生成代码签名用的证书,并用伪造的ECC根证书做签名

R7jqArb.png!web

打包数字签名证书

N7jEzyf.png!web

对可执行文件CVE20200601.exe签名

YVFNVvz.png!web

在未打补丁的机器上,可执行文件CVE20200601.exe的数字签名校验通过

AJfmyaR.png!web

QRRjQbz.png!web

Bz2Mzya.png!web

打完补丁后,可执行文件CVE20200601.exe的数字签名信息无法验证。

f6BZNnr.png!web

0x05 参考资料

https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-0601

《密码编码学与网络安全——原理与实践(第六版)》

http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

https://github.com/ollypwn/cve-2020-0601

https://medium.com/hackernoon/bluetooth-hacking-cheating-in-elliptic-curve-billiards-c092fdf70aae


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK