CVE-2020-0601深度分析

2020-02-19 6,426

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


补丁变化

Windows CryptoAPI包含多个不同的库,该漏洞位于crypt32.dll中。研究人员对该DLL的补丁和原始DLL进行差异分析,结果如下所示:

image.png

图 1. 使用BinDiff对crypt32.dll文件和补丁文件进行差异分析

DLL文件的变化

对比这两个DLL文件,研究人员发现有5个新的函数加入了最新的补丁中,还有5个原有的函数发生了变化。
首先,可以看到修改的函数名:

image.png

图 2. crypt32.dll文件中修改的函数名

可以看出CCertObject类的constructordestructor都发生了微小的变化,但最大的变化位于ChainGetSubjectStatus()CCertObjectCache::FindKnownStoreFlags()中。
然后,看一下新加入的函数名:

image.png

图 3. crypt32.dll中新加入的函数名
ChainLogMSRC54294Error()函数就是一个新加入的函数用来帮助Windows event logging对潜在的漏洞利用尝试进行记录。其目的可以通过以下内容来确定:

image.png

图 4. 表明函数ChainLogMSRC54294Error()的块

该块传递了一个含有与该漏洞相关的CVE编号的字符串到外部库函数CveEventWrite中,这是一个相对较新的Event Tracing API函数,会将CVE相关的事件写入Windows Event Log中。

利用这些信息,研究人员分析了该函数的交叉引用,发现了关于事件记录的环境情况。在本例中,只有ChainLogMSRC54294Error()的直接引用是在函数ChainGetSubjectStatus()中,该函数在更新的几个函数中变化最大:

image.png

图 5. 函数ChainGetSubjectStatus()检查ChainLogMSRC54294Error()的引用情况

查看到新记录函数的调用环境可以发现,该函数是根据调用CryptVerifyCertificateSignatureEx()ChainComparePublicKeyParametersAndBytes()的特定结果才调用的,后者是补丁中新加入的一个函数。因此,ChainGetSubjectStatus()是一个很好的分析目标。

CryptoAPI中的证书验证

为了理解ChainGetSubjectStatus()参与的过程,首先要了解一个典型的程序如何使用CryptoAPI来处理证书。

本文中研究人员用Powershell的Invoke-Webrequest cmdlet来进行分析。Powershell加载后,到含有可信证书的系统证书库的handler会通过调用CertOpenStore来获取,所以存储会在必要的时间使用。然后,这些证书库会加入到“collection”中,collection就像一个大的合并证书库一样。

Invoke-Webrequest这样的命令用于用来发送TLS上的Https请求到服务器时,服务器就会呈现一个含有终端证书和其他证书的TLS证书握手消息,这些证书会用来验证证书链。在接收到证书后,其他内存中的库就会通过调用CertOpenStore()来创建。然后,接收到的证书会通过函数 CertAddEncodedCertificateToStore()添加到新的库中,该函数会常见一个含有到证书库的handle的CERT_CONTEXT结构,一个指向原始编码证书的指针,一个指向CERT_INFO结构的指针,其中CERT_INFO结构与证书的ASN.1结构对应。

比如,下面这些结构就是通过调用到终端证书的CertAddEncodedCertificateToStore()创建的:

image.png

图 6. 调用CertAddEncodedCertificateToStore()创建的结构

结论

通过对CVE-2020-0601漏洞的分析,研究人员得出以下结论:

  • 终端证书的签名是用伪造的root证书和其他包含的椭圆曲线参数验证的。

  • 伪造的root证书签名是用自签名的证书验证的,还说使用其中包含的椭圆曲线参数。

  • 伪造的root证书匹配的证书位于系统证书库中,伪造的和合法的root证书都保存在这里。

  • 伪造的和合法的root证书的公钥哈希值都会被检查,如果哈希值匹配,就不再验证伪造的root证书,导致伪造终端证书的成功验证。

那么微软是如何处理该漏洞的呢?在图5中,可以看出加入了一个到新函数ChainComparePublicKeyParametersAndBytes()的调用,替换了原来的发行者和可信root公钥哈希之间的简单比较,会比较可信root证书和用来验证终端证书签名的证书的公钥参数和字节。如果比较失败,就会调用CryptVerifySignatureEx()来重新验证终端证书签名。

更多参见:https://blog.trendmicro.com/trendlabs-security-intelligence/an-in-depth-technical-analysis-of-curveball-cve-2020-0601/


本文作者:ang010ela

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/123102.html

Tags:
评论  (0)
快来写下你的想法吧!

ang010ela

文章数:56 积分: 711

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号