HTTPS 協議降級攻擊原理
0x00 HTTPS
在傳統流行的web服務中,由於http協議沒有對數據包進行加密,導致http協議下的網路包是明文傳輸,所以只要攻擊者攔截到http協議下的數據包,就能直接窺探這些網路包的數據。
HTTPS 協議就是來解決這個問題的,關於HTTPS協議的原理由於不是本文的主要討論內容,所以大家可以到大型網站的 HTTPS 實踐(一)—— HTTPS 協議和原理這裡查看。
簡而言之,HTTPS協議在應用層的http協議和以及傳輸層TCP協議之間的會話層加入了 SSL/TLS協議,用作加密數據包。會話層的這個加密協議,在真正數據傳輸之前,進行握手通信,握手的信息交換主要包括:雙方確認加密協議的版本,確認身份(其中瀏覽器客戶端的身份有時是不需要確認的),確認傳輸真正數據的加密密碼(對稱加密)。
在用作信息傳輸的加密密碼確認之後,接下來的通信數據都會加密後再傳輸,從而達到防竊取的作用。
0x01 HTTPS 協議降級
那麼使用了https就能確保安全傳輸了嗎?
可以說理想上是的,現實卻不是。
原因簡單來說就是:設計和實現SSL/TLS協議出現了漏洞,導致攻擊者同樣可以攻擊一些舊版本的SSL/TLS協議。當SSL/TLS加密協議漏洞爆出來之後,最新版本的SSL/TLS協議修復了已知漏洞,但舊版本的加密協議卻變得不安全了。
那麼什麼又是「HTTPS協議降級」?
在上一小節我們提到SSL/TLS協議通過握手來確定通信信息,其中握手雙方要統一加密協議版本。
在握手過程中這樣確認加密協議版本:
- 由客戶端(如瀏覽器)發送第一個數據包 ClientHello,這個數據包中保存著客戶端支持的加密協議版本。
- 伺服器收到這個ClientHello數據包,查看裡面客戶端支持的加密協議版本,然後匹配伺服器自己支持的加密協議版本,從而確認雙方應該用的加密協議版本。
- 伺服器發送ServerHello數據包給客戶端,告訴客戶端要使用什麼加密協議版本。
在上述過程中,如果客戶端發送給伺服器的ClientHello數據包中說自己僅支持某個有漏洞的舊版本加密協議(比如僅支持SSLv3.0),伺服器有兩種可能:
- 伺服器支持很多版本,其中包括有漏洞的舊版本和新版本(包括了SSLv3.0協議),那麼伺服器會認可使用有漏洞的舊版本協議,從而告訴客戶端使用有漏洞的舊版本(可以使用SSLv3.0)。
- 伺服器不支持有漏洞的舊版本,拒絕客戶端的這次請求,握手失敗。
對於攻擊者,作為中間人只能監聽到加密過的數據,如果這些數據通過沒有漏洞的加密版本加密,攻擊者並不能做什麼。
但是,如果伺服器提供有漏洞的舊版本加密協議的支持,而同時攻擊者又能作為中間人控制被攻擊者的瀏覽器發起漏洞版本的HTTPS請求,那雖然攻擊者監聽到的也是加密過的數據,但因為加密協議有漏洞,可以解密這些數據,所以數據就和明文傳輸沒有什麼差別了。
這就是HTTPS協議降級。
0x02 SSLv3.0 的AES加密原理
攻擊者通過握手將HTTPS通信協議降低到SSLv3.0之後,將會攔截到經過SSLv3.0加密過的數據,Padding Oracle攻擊可以解密這些數據。
為什麼叫 Padding,我們從SSLv3.0的加密原理說起。
也是在第一小節,HTTPS握手過程中,通信雙方還確認了一個「加密密碼」,這個密碼是雙方在握手過程中使用非對稱加密的方式協商出來的對稱加密密碼。攻擊者能攔截到的數據就是被這個密碼加密的。
這個對稱加密使用AES加密,AES塊密碼會把要加密的明文切分成一個個整齊的塊(如將明文以16個位元組為一塊分成很多塊),如果最後一塊不足一塊,則會填充(Padding)滿一塊,再進行加密。這個填充就是Padding Oracle攻擊的關鍵。
AES是典型的塊密碼,塊密碼的加密方式有很多種,如果你不了解,可以查看塊密碼的工作模式。
SSLv3.0中使用AES-CBC模式加密,我們來看加密和解密流程:
加密過程圖示:
加密過程:
- 明文首先被分成很多明文塊,所有明文塊的位元組長度都一樣,其中最後一個明文塊經過了填充,若假設最後一個填充位元組值為L,則填充內容為值為L的位元組重複L次(不包括最後一個位元組本身) 。
- 加密從第一個明文塊開始鏈式依次進行,其中,第一個明文塊先和初始化的向量進行異或,之後使用加密key加密,生成第一個密文塊。
- 將第一個密文塊與第二個明文塊異或,然後使用加密key加密,生成第二個密文塊。
- 以此類推,第N個密文塊,由第N-1個密文塊和第N個明文塊異或,然後使用加密key加密獲得。
- 將所有獲得的密文塊依次拼接起來,就得到了最後的加密數據,這個數據是暴露在網路流量中的數據,也是攻擊者可能截獲的數據。
解密過程圖示:
解密過程:- 將密文內容分為若干個密文塊,每個密文塊和加密時的明文塊長度一樣,此時由於加密時經過了填充,密文內容肯定能整齊的分割成整數個密文塊。
- 對於第一個密文塊,使用加密key解密之後,與加密時的初始化響亮異或獲得第一個明文塊。
- 對於其他的密文塊,如第N個,使用加密key解密之後,與第N-1個密文塊異或,獲得相應的明文。
這就是SSLv3.0的加密原理過程。
0x03 CBC模式加密 的 Padding Oracle攻擊
上一節我們解釋了CBC模式加密過程,這種模式使用不當會遭到針對於Padding的攻擊。
對於SSL協議,需要加密的數據包括信息本身和信息的MAC摘要值,在協議設計初期,由於大家考慮不周,使用了「先做信息摘要MAC DATA,再做加密」的方式(MAC-then-encrypt)。
MAC-then-encrypt,這種方式可能遭到Padding Oracle攻擊。SSL協議在這種方式下,數據格式如圖:
這是一次請求要傳遞的數據結構示意,其中Data為最重要的數據,包括 cookie甚至用戶名密碼等信息,HMAC 如圖示是Data以及其他一些序列數據的MAC摘要,最後是補充位元組的Padding。在這種數據結構下,加密數據傳輸到接收者手裡,會解密然後依次驗證Padding數據和HMAC數據,來確認數據是正確的。
因此,接收者解密驗證時主要有三種可能發生的情況:
- Padding數據錯誤,拒絕,返回。
- HMAC數據錯誤,拒絕,返回。
- 正確接收。
這3種返回給予了攻擊者啟示,我們再來看解密過程:
留意最後一個密文塊,這個密文塊首先會用加密key進行解密,然後與倒數第二個密文塊進行異或。攻擊者是能夠截獲到所有的密文內容的。
我們提到過Padding數據的規則是:若假設最後一個填充位元組值為L,則填充內容為值為L的位元組重複L次(不包括最後一個位元組本身) 。而驗證padding的過程也是按照規則來的:讀取最後一個位元組的值,並移除最後一個位元組,然後驗證剩下的padding為L個值為L的位元組。
也就是說,當最後一個位元組值為 0x00 的時候,padding驗證會直接通過。
假設:
- 倒數第二個密文塊的最後一個位元組值為 x(攻擊者可見的)。
- 最後一個密文塊,解密後最後一個位元組值為 a (攻擊者不可見)。
- 最後一個明文塊最後一個位元組為 m (攻擊者不可見)。
可知, a = x 異或 m 並且 m = x 異或 a。
然後攻擊者不斷修改x的值,發送給接收者,那麼m的值也會不斷變化,並發生padding數據驗證失敗返回。除非 m 變成 0x00, 此時不會返回padding數據驗證失敗,而會返回HMAC數據驗證失敗。假設此時, m 的值被改為了 c,如圖。
可知, a = c 異或 0x00。由於 a = x 異或 m 並且 m = x 異或 a。
所以 m 也就是明文, m = x 異或 c 異或 0x00。其中, x攻擊者已知, c通過不同的返回獲知。 從而破解了明文中的最後一個位元組。
有了 m 的值,也同時得到了 a 的值, 可以通過修改 x 的值控制m,比如修改 x 的值使
m = 0x01 = x 異或 a。
將 m 設置成 0x01 的時候,遍歷倒數第二個密文塊的倒數第二個位元組(最多256次),通過判斷是否通過padding驗證,就能同理求出另外一個位元組了。
以此類推可以解密整個數據包。
0x04 Padding Oracle攻擊的防範
通過上一節可以看到攻擊者是通過padding驗證返回 和 mac驗證返回結果不同來獲得信息的,實際上,即使padding驗證失敗和mac驗證失敗都返回同樣結果,攻擊者也可以通過響應時間的不同通過 timing的方式獲得信息。
所以在協議中將驗證失敗的響應時間和響應結果統一,使攻擊者不能區分能防範這種攻擊。
而對於SSL/TLS協議的使用者,我們可以響應號召在自己伺服器的加密協議支持列表上去掉SSLv3.0 。
0x05 參考資料
- Padding oracles and the decline of CBC-mode cipher suites
- The Cryptographic Doom Principle
- POODLE attacks on SSLv3
- SSL v3 Poodle安全漏洞修復建議
推薦閱讀:
※0xA1: 新官上任三把火
※想做黑客?先看看這個信息安全資源列表吧~
※如何成為一名信息安全工程師?
※新勒索軟體DynA-Crypt不僅要加密你的文件 而且竊取並刪除它們
※LastPass 近日「零日漏洞」的解釋