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安全漏洞修復建議
來自:https://zhuanlan.zhihu.com/p/22917510