細(xì)致分析Padding Oracle滲透測(cè)試全解析

大數(shù)據(jù)

作者:Sherkey

最近在研究Padding Oracle滲透測(cè)試,發(fā)現(xiàn)網(wǎng)上沒(méi)有詳細(xì)講原理的文章。因此自己整理了這樣一篇,希望哪怕是沒(méi)有密碼學(xué)基礎(chǔ)的朋友也能看完后完全理解攻擊的原理。

一、基礎(chǔ)知識(shí)介紹

本節(jié)針對(duì)無(wú)密碼學(xué)基礎(chǔ)的讀者,若均理解可直接跳過(guò)。

1.1 什么是分組密碼?

以下定義來(lái)自維基百科:

在密碼學(xué)中,分組加密(英語(yǔ):Block cipher),又稱(chēng)分塊加密塊密碼,是一種對(duì)稱(chēng)密鑰算法。它將明文分成多個(gè)等長(zhǎng)的模塊(block),使用確定的算法和?對(duì)稱(chēng)密鑰對(duì)每組分別加密解密。

簡(jiǎn)單來(lái)說(shuō),就是將明文進(jìn)行分組,每組分別加密,最后再連在一起形成密文。AES, DES等加密方法均屬于分組加密。

1.2 什么是PKCS#5?

正如1.1中所說(shuō),分組密碼中,需要對(duì)明文進(jìn)行分組。

但是分組要求每個(gè)塊的大小都要相同。

那么問(wèn)題就來(lái)了,如果說(shuō)我的明文是‘testabc’,而我用的分組密碼是五個(gè)一組。這樣第一組內(nèi)容是‘testa’,那么第二組只剩下了‘bc’,不夠五個(gè),應(yīng)該怎么辦呢?

這是就要用到一種填充方式,用來(lái)把最后空出來(lái)的幾位填滿(mǎn)。

而PKCS#5,就是一種由RSA信息安全公司設(shè)計(jì)的填充標(biāo)準(zhǔn)。

對(duì)于PKCS#5標(biāo)準(zhǔn)來(lái)說(shuō),一般缺少幾位,就填充幾位那個(gè)數(shù)字。

比方說(shuō),在上面的例子里,我們有三位空缺,那么就要在空缺處都填上3 。這樣,第二組的內(nèi)容就變成了‘bc333’ 。

這里需要注意的是,比如說(shuō),如果每個(gè)分組是8字節(jié),我的明文是‘testabcd’,這樣恰好是8字節(jié)了。但是按照PKCS#5的標(biāo)準(zhǔn),我們?nèi)匀恍枰诤竺嫣砑右粋€(gè)塊,塊里的內(nèi)容全部填充為8 (因?yàn)橐粋€(gè)塊大小為8字節(jié),而第二個(gè)塊全部為空,因此有8位需要填充)。

1.3 CBC模式

在密碼學(xué)中,分組密碼有許多的工作模式。

可能有人會(huì)問(wèn),我們直接分組以后加密不就好了嗎,為什么需要設(shè)計(jì)模式呢?

沒(méi)錯(cuò),其實(shí)分組后直接加密也是一種設(shè)計(jì)模式,名為電子密碼本(Electronic codebook,ECB)模式。

大數(shù)據(jù)

如圖所示,其實(shí)就是每個(gè)分組的明文均利用相同的密鑰進(jìn)行加密。

但是這種模式明顯有個(gè)缺點(diǎn),那就是所有的密鑰都相同,導(dǎo)致相同的明文,一定會(huì)被加密成相同的密文。

這樣很顯然是一種不安全的模式。因?yàn)樗荒芴峁﹪?yán)格的數(shù)據(jù)保密性??梢月?lián)想一下最簡(jiǎn)單的凱撒密碼,相同的明文加密后得到相同的密文,導(dǎo)致這種方式難以阻擋頻率攻擊。

那么為了讓我們加密后的信息更加難以破解,在1976年,IBM發(fā)明了密碼分組鏈接(CBC,Cipher-block chaining)模式。

如下圖所示。

大數(shù)據(jù)

我們可以看到,這里加入了一個(gè)初始向量(IV, Initialization Vector)。在第一塊明文進(jìn)行加密之前,需要先與初始向量進(jìn)行異或。而產(chǎn)生的密文,將與下一組明文進(jìn)行異或。在這種方法中,每個(gè)密文塊都依賴(lài)于它前面的所有明文塊。

這種模式使原本獨(dú)立的分組密碼加密過(guò)程形成迭代,使每次加密的結(jié)果影響到下一次加密。這樣無(wú)疑比ECB模式要安全了許多。

上圖分別是CBC模式下加密和解密的過(guò)程。我們可以看到在中間寫(xiě)著B(niǎo)lock Cipher Encryption 的方塊那里即是加密算法,本文中就用AES來(lái)舉例。

而Initiallzation Vector(IV)即是初始向量,也是本攻擊方式所重點(diǎn)利用的地方。

1.4 異或

在密碼學(xué)里,異或是一種很重要的運(yùn)算方式。

具體表現(xiàn)在,一個(gè)數(shù)字連著異或兩次另一個(gè)數(shù)字后,得到的值還是它本身。

比方說(shuō),65 ^ 66 = 3

3 ^ 66 = 65

在下面我們會(huì)利用到這個(gè)重要的運(yùn)算。

二、破解過(guò)程詳解

文章開(kāi)頭說(shuō)了,這是一種針對(duì)CBC模式的攻擊。與你具體選擇的是哪種加密方式是沒(méi)有關(guān)系的。

也就是說(shuō),在上面CBC加密模式的圖里,不管你在‘Block Cipher Decryption’那個(gè)框里選的是AES加密,還是DES加密,都無(wú)所謂,只要服務(wù)器配置不正確,我們都有機(jī)會(huì)破解。

那么這是如何做到的呢?在說(shuō)明攻擊方式之前,我們先來(lái)了解一下正常的解密方式是如何的。

2.1 正常解密過(guò)程

我們先來(lái)分析一下正常狀態(tài)下,服務(wù)器的解密過(guò)程。

首先,CBC模式下AES的解密需要知道IV值與密鑰。這個(gè)應(yīng)該很好理解?!瓸lock Cipher Decryption’肯定需要知道密鑰來(lái)解密,而CBC模式需要IV值來(lái)解密。

而服務(wù)器端僅僅保留了密鑰,沒(méi)有保留IV值。因?yàn)槟J(rèn)情況下加密后的文件會(huì)把IV值附在文件開(kāi)頭,因此服務(wù)器會(huì)直接使用傳給它的文件開(kāi)頭8或16位(視加密方式而定),作為IV值。

在此我們停一下,先舉個(gè)例子,詳細(xì)解釋一下CBC模式下AES加密過(guò)的密文如何正常解密得到明文。

比方說(shuō),我們有密文’9F0B13944841A832B2421B9EAF6D9836813EC9D944A5C8347A7CA69AA34D8DC0DF70E343C4000A2AE35874CE75E64C31′ 。這段密文用CBC模式下AES加密,并且已知key和IV值。

接下來(lái)我們進(jìn)行解密。

首先,AES是一種分組密碼,每組由16字節(jié)組成。密文是用十六進(jìn)制表示的,也就是相鄰兩位數(shù)字合在一起組成一個(gè)十六進(jìn)制數(shù),用來(lái)表示一字節(jié)。密文長(zhǎng)度為96,按照32一組進(jìn)行分組,則恰好可以分為三組。我們把這三組密文存到一個(gè)數(shù)組C里,以后用C[0], C[1], C[2]來(lái)表示這三組密文。

然后我們看一下解密用的圖。

大數(shù)據(jù)

如上圖所示,我已經(jīng)在圖中標(biāo)出了C[0], C[1], C[2]的位置。我們正常解密時(shí),先用C[0]與Key解密AES,然后得到一個(gè)中間值,這個(gè)中間值與IV值進(jìn)行異或,得到第一段明文。而C[0]作為新的IV值,與C[1]在AES解密后的中間值進(jìn)行異或,從而得到第二段明文。第三段以此類(lèi)推。這就是一個(gè)正常解密的過(guò)程。

下圖中把“中間值”這個(gè)概念用紅圈表示了出來(lái)。千萬(wàn)千萬(wàn)要好好看懂解密過(guò)程以及“中間值”究竟代表什么,這是本攻擊的關(guān)鍵。

大數(shù)據(jù)

而Padding Oracle 攻擊的重點(diǎn),就在于上一段提到的中間值。

我們繼續(xù)聊服務(wù)器端正常情況下如何解密。其實(shí)和我們上面分析的差不多。區(qū)別在于,我們解密的時(shí)候是從左往右,也就是先從C[0]開(kāi)始解密;而服務(wù)器是從右往左,也就是先解密C[2]。

那么問(wèn)題又來(lái)了:服務(wù)器如何知道自己解密后得到的結(jié)果是否正確呢?

因?yàn)榉?wù)器無(wú)法判斷解密后明文是否有具體含義,因此它也就不從含義上去判斷。它判斷的方式很簡(jiǎn)單粗暴,就是利用Padding值來(lái)進(jìn)行判斷。

在1.2處我們了解了PKCS#5標(biāo)準(zhǔn)下的填充方式。我們已經(jīng)知道,明文加密之前肯定會(huì)在末尾附上一段Padding值用來(lái)填充。

那么接下來(lái),服務(wù)器從C[2]進(jìn)行解密。比如說(shuō),一開(kāi)始明文最后Padding值為0×05,也就是最后五位應(yīng)該均為5 。而服務(wù)器解密后,發(fā)現(xiàn)也確實(shí)如此,那么它就認(rèn)為這次解密時(shí)正確的。而如果服務(wù)器發(fā)現(xiàn)解密后Padding值為0×05 ,但是只有最后四位的值為0×05 ;或者說(shuō)它解密后得到的Padding值為0×04 ,但是最后五位都是0×04 ,那么就造成了Padding的值與數(shù)目不相符,服務(wù)器就會(huì)認(rèn)為解密失敗,從而報(bào)錯(cuò)。

我們可以從其他參考文章的描述中看到:

如果解密過(guò)程沒(méi)有問(wèn)題,明文驗(yàn)證(如用戶(hù)名密碼驗(yàn)證)也通過(guò),則會(huì)返回正常 HTTP 200如果解密過(guò)程沒(méi)有問(wèn)題,但是明文驗(yàn)證出錯(cuò)(如用戶(hù)名密碼驗(yàn)證),則還是會(huì)返回 HTTP 200,只是內(nèi)容上是提示用戶(hù)用戶(hù)名密碼錯(cuò)誤如果解密過(guò)程出問(wèn)題了,比如Padding規(guī)則核對(duì)不上,則會(huì)爆出 HTTP 500錯(cuò)誤。

其實(shí)就是我們剛才說(shuō)的判斷方式的更具體應(yīng)用。

而知道服務(wù)器的判斷方式以后,我們就可以在這里做文章了。

2.2 攻擊過(guò)程

大數(shù)據(jù)

本次攻擊的關(guān)鍵,集中在我用紅圈圈起來(lái)的地方。

也就是C[0]. C[1]. C[2]分別用key對(duì)AES進(jìn)行解密,但是還沒(méi)有與IV值異或的那個(gè)值。本文把那個(gè)值稱(chēng)為中間值。

大數(shù)據(jù)

上圖是正常解密的結(jié)果。而本次攻擊的關(guān)鍵,就在被綠色標(biāo)注的那一行。

本文把綠色標(biāo)注那一行的值稱(chēng)為中間值。

根據(jù)上面的CBC模式解密的圖,我們可以知道,解密會(huì)先使用AES解密得到一個(gè)中間值,然后在通過(guò)中間值與IV值的異或,最后得到明文。

而padding oracle攻擊的本質(zhì),其實(shí)就是通過(guò)傳遞密文以及自己猜測(cè)的IV值,通過(guò)觀察服務(wù)器對(duì)padding判斷的結(jié)果,進(jìn)而反推出中間值,最后用中間值與正確的IV異或得到明文。

也就是這個(gè)攻擊直接跳過(guò)了AES,而針對(duì)CBC進(jìn)行攻擊。

需要注意的是,自己傳遞的IV值與正確的IV值不能混淆。鑒于圖中自己傳遞的IV值為黃色,因此下稱(chēng)自己傳遞的IV值為黃IV,正確的IV值為原IV。

我們?cè)賮?lái)想想服務(wù)器是怎么解密的:從右往左。

大數(shù)據(jù)

再看看CBC模式解密的那張圖,從右往左,就是說(shuō)先解密C[2]。而解密時(shí),就會(huì)用C[1]當(dāng)做IV值,來(lái)與C[2]解密后得到的中間值進(jìn)行異或,進(jìn)而得到明文。

而我們首先需要自己構(gòu)造C[1]中的值,也即在上面圖片中的黃IV值,構(gòu)造以后與C[2]解密得到的中間值進(jìn)行異或。

并且根據(jù)上面服務(wù)器判斷解密過(guò)程是否正確的條件來(lái)看,只要最后padding值與個(gè)數(shù)相對(duì)應(yīng)即可。

因此,我們可以一位一位的構(gòu)造,第一次先通過(guò)改變黃IV值,產(chǎn)生padding結(jié)果為1的情況,即可倒推出中間值。

那么我們開(kāi)始進(jìn)行破解。

2.3 第一次循環(huán)

還記得我們前面提到的服務(wù)器判斷方式嗎?就是只需要padding的值與個(gè)數(shù)相符即可。

而在第一次循環(huán)里,我們只需要構(gòu)造C[1],使得與C[2]產(chǎn)生的中間值異或以后,得到的最后一位為0×01即可。

C[1]是一個(gè)十六位的數(shù)組(相鄰兩位算作一個(gè)十六進(jìn)制數(shù))。我們可以使它前15位均為隨機(jī)數(shù)。因?yàn)槿绻请S機(jī)數(shù)的話(huà),與中間值異或后的結(jié)果也是一個(gè)隨機(jī)數(shù),不太可能恰好是0×01,因此就避免了你最后一位得到0×01,而前一位恰好也是0×01導(dǎo)致個(gè)數(shù)不符,服務(wù)器判斷為錯(cuò)的尷尬。C[1]最后一位從00到ff進(jìn)行嘗試。根據(jù)上面所說(shuō),會(huì)有一個(gè)值恰好與C[2]解密后的中間值異或后會(huì)得到0×01這個(gè)結(jié)果。這時(shí)服務(wù)器返回顯示正確。

返回正確時(shí),意味著如下公式成立:

C1 ^ 中間值的最后一位 = 0×01

那么按照異或運(yùn)算的性質(zhì),我們不難得到:

中間值的最后一位 = C1 ^ 0×01

這樣我們就成功得到了中間值的最后一位。

2.4 第二次至第N次循環(huán)

Padding值為1的情況結(jié)束后,再用同樣方法嘗試2 。但是要注意,為了讓服務(wù)器判斷正確,我們需要使最后兩位結(jié)果都為2 。那么,倒數(shù)第二位是我們本次循環(huán)的嘗試位,倒數(shù)第一位如何確定呢?

因?yàn)槲覀冊(cè)趐adding值為1的時(shí)候,已經(jīng)通過(guò)嘗試得到了正確的中間值。因此,我們只需要將中間值與0×02進(jìn)行異或的結(jié)果放到此處即可。

參考下式會(huì)更容易理解:

C1?= 上一步得到的中間值最后一位 ^ 0×02

這里可能有人會(huì)問(wèn),為什么這一步的C1和上一步的不一樣了?

這是因?yàn)槲覀兪窃谕ㄟ^(guò)窮舉法來(lái)破解。我們?cè)诟F舉的時(shí)候,是把整個(gè)C[1]都當(dāng)做了可以改變的對(duì)象,目的就是通過(guò)改變C[1]來(lái)解除C[2]的中間值。因此上一步我們求出來(lái)了中間值以后,C1就可以被我們繼續(xù)改變了。

而在這一次,我們是為了讓padding值為2,這就意味著最后兩位都需要為0×02。而倒數(shù)第二位是我們這次窮舉需要改變的值,那么我們就需要讓C1與最后一位的中間值異或以后,能得到0×02。

而最后一位中間值我們已經(jīng)求得了。因此在這一輪循環(huán)里,我們要讓C1固定,這樣異或后的結(jié)果為0×02,我們也就可以愉快的繼續(xù)窮舉倒數(shù)第二位了。

之后的操作也與此相同。第n輪循環(huán)的時(shí)候,只要把C[1]倒數(shù)第n-1一直到倒數(shù)第一位的值全部固定,使得他們與得到的中間值異或后得到n就可以了。

在整個(gè)C[2]破解結(jié)束后,我們會(huì)得到這個(gè)塊中所有的中間值。這時(shí),我們只需要掏出未經(jīng)改變的C[1] ,也就是原IV,與中間值異或,就可以得到C[2]塊的全部明文了。

之后我們?cè)儆孟嗤姆椒ㄆ平釩[1],就能得到全部明文了。

極客網(wǎng)企業(yè)會(huì)員

免責(zé)聲明:本網(wǎng)站內(nèi)容主要來(lái)自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請(qǐng)進(jìn)一步核實(shí),并對(duì)任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對(duì)有關(guān)資料所引致的錯(cuò)誤、不確或遺漏,概不負(fù)任何法律責(zé)任。任何單位或個(gè)人認(rèn)為本網(wǎng)站中的網(wǎng)頁(yè)或鏈接內(nèi)容可能涉嫌侵犯其知識(shí)產(chǎn)權(quán)或存在不實(shí)內(nèi)容時(shí),應(yīng)及時(shí)向本網(wǎng)站提出書(shū)面權(quán)利通知或不實(shí)情況說(shuō)明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實(shí)情況證明。本網(wǎng)站在收到上述法律文件后,將會(huì)依法盡快聯(lián)系相關(guān)文章源頭核實(shí),溝通刪除相關(guān)內(nèi)容或斷開(kāi)相關(guān)鏈接。

2017-10-18
細(xì)致分析Padding Oracle滲透測(cè)試全解析
作者:Sherkey 最近在研究Padding Oracle滲透測(cè)試,發(fā)現(xiàn)網(wǎng)上沒(méi)有詳細(xì)講原理的文章。因此自己整理了這樣一篇,希望哪怕是沒(méi)有密碼學(xué)基礎(chǔ)的朋友也能

長(zhǎng)按掃碼 閱讀全文