AES-128-CBC字節(jié)翻轉(zhuǎn)攻擊(詳細(xì))

CBC加密流程

(瀏覽了各路大神的博客帖子,終于把這個(gè)研究明白了,所以寫(xiě)出一個(gè)博文當(dāng)做自己的筆記哥遮,把自己的理解加入進(jìn)去,因?yàn)橹皩W(xué)習(xí)時(shí)剛開(kāi)始還是難理解陵究,后面跌跌撞撞的還是明白了眠饮,希望想學(xué)到這個(gè)知識(shí)的朋友可以從這篇文章中得到一些收獲。)

0x1加密:

兩個(gè)單詞:Plain代表明文铜邮。Cipher代表密文

Xor:異或仪召,異或運(yùn)算 例如1 ^ 999 = 998。同樣 998 ^ 999 =1 松蒜,繼續(xù) 999 ^ 1 =998

加密步驟為:

? 1.將明文每16個(gè)字節(jié)分一組扔茅,并設(shè)置一個(gè)初始向量iv,iv為固定的16個(gè)字節(jié)一般是隨機(jī)生成秸苗。(如果最后一組不夠十六個(gè)字節(jié)召娜,則會(huì)通過(guò)補(bǔ)充\x0n (n代表缺少的個(gè)數(shù) )來(lái)填滿,例如第三組目前是10個(gè)字節(jié)难述,那么后面的六個(gè)字節(jié)全部都是\x06萤晴,如果超出10則用16進(jìn)制字符代表例如\x11則表示成\x0b)

? 2.將明文第一組與初始向量iv進(jìn)行xor得出一個(gè)待加密的C。

? 3.將C進(jìn)行一個(gè)函數(shù)加密胁后,這個(gè)函數(shù)是對(duì)稱(chēng)的也是未知的店读,解密的時(shí)候也需要用到這個(gè)函數(shù)。(此時(shí)加密后的C,也就是encrypt(C)我們稱(chēng)他為cipher1)

同理 對(duì)第二組明文進(jìn)行相同操作攀芯,只是此時(shí)的初始向量iv是前一組的密文(也就是cipher1)

? 4.此時(shí)第二組的明文與第一組的密文進(jìn)行xor得到第二組的C屯断。

? 5.將C進(jìn)行同樣的函數(shù)加密生成cipher2。之后的每一組都通過(guò)這樣的方式。

? 6.將所有的cipher組連接到一起殖演,生成了密文Ciphertext氧秘。

下面我們模擬一下cbc加密模式的過(guò)程:

(以下的加密解密過(guò)程都是模擬的,真實(shí)情況是不需要我們?nèi)?xiě)代碼的 拿php舉例趴久。

$ciphertext=openssl($plain,"aes-128-cbc",'***********',OPENSSL_RAW_DATA,$iv)丸相,

這條代碼的功能就是產(chǎn)生一個(gè)Ciphertext,你只需要給它一個(gè)明文彼棍,給他一個(gè)初始iv灭忠,函數(shù)會(huì)自動(dòng)幫助你去生成密文。模擬加密解密過(guò)程是為了幫助我們理解他的加密模式座硕,從而了解此加密模式的漏洞機(jī)制弛作。)

我們還是按照加密過(guò)程來(lái)開(kāi)始:

1.先把明文進(jìn)行文組。

以下的代碼我稱(chēng)未知加密函數(shù)為encrypt()? 解密函數(shù)為decrypt()华匾。Plain1代表的是明文第一組映琳,Plain2代表明文第2組。cipher1表示密文第一組蜘拉,cipher2表示密文第二組萨西。。(每組的密文和明文都是16個(gè)字節(jié)诸尽。密文組和明文組的每一個(gè)字節(jié)都是對(duì)應(yīng)的)也就是說(shuō):

密文組1的第[三]個(gè)字節(jié)=未知函數(shù)加密(明文組1的第[三]個(gè)字節(jié)? XOR 初始IV的第[三]個(gè)字節(jié))

代碼表示為:cipher1[2]=encrypt(plain1[2] Xor IV[2])

建立一個(gè)循環(huán)來(lái)代表可以寫(xiě)成

For($i=0;$i<=15;$i++){

$Cipher1[$i]=encrypt($Plain1[$i] xor $Iv[$i]);

}

這時(shí)分組1的密文已經(jīng)獲取完畢原杂,下面我們模擬一下分組2的密文:

此時(shí)分組2的明文與第一組的密文進(jìn)行xor得到第二組的C,再把C進(jìn)行encrypt函數(shù)加密您机,得到了想要的密文。代碼表示:

For($i=0;$i<=15;$i++){

$Cipher2[$i]=encrypt($Plain2[$i] xor $Cipher1[$i]);

}

同樣分組2的密文已經(jīng)獲取完畢

我們把cipher1和cipher2連接起來(lái)年局,便產(chǎn)生了Ciphertext(這里舉例明文只有32個(gè)字節(jié))

Ciphertext=cipher1.cipher2;

現(xiàn)在我們有了Ciphertext了际看,那么這個(gè)是不是我們從cookie中看到的呢?其實(shí)并不是矢否,因?yàn)榧用芎蟮膬?nèi)容有很多是不可見(jiàn)字符仲闽,如果想讓密文可視化,普遍都采用base64進(jìn)行編碼僵朗,這樣就可以看到了赖欣。但是解密的時(shí)候一定要再解碼回去才可以解密。

0x2:解密

解密的過(guò)程:

? 1.將Ciphertext密文分組验庙。

? 2.用函數(shù)對(duì)第一組的密文解密顶吮,然后和IV進(jìn)行xor得到Plain1。

? 3.用函數(shù)對(duì)第二組密文解密粪薛,然后和第一組的密文xor得到Plain2悴了。

我們來(lái)繼續(xù)模擬一下解密的過(guò)程:

(以下稱(chēng)呼未知解密函數(shù)為decrypt,同樣解密的過(guò)程也是我們模擬出來(lái)的,現(xiàn)實(shí)中是不需要我們?nèi)?xiě)代碼進(jìn)行加密解密的湃交,拿php舉例的函數(shù)是$Plaintext=openssl_decrypt($ciphertext,"aes-128-cbc",'***********',OPENSSL_RAW_DATA,$iv))

1.對(duì)整個(gè)Ciphertext進(jìn)行分組熟空,每16個(gè)字節(jié)為一組。這里還是稱(chēng)呼cipher1是第一組搞莺,cipher2是第二組

2.從第1組開(kāi)始息罗,我們的目的是得到Plain1

Plain1=decrypt(cipher1)XOR? iv

同樣每個(gè)字節(jié)都是

For($i=0;$i<=15;$i++){

$Plain1[$i]=decrypt($Cipher1[$i]) Xor $Iv[$i];

}

這樣循環(huán)之后Plian1明文第一組已經(jīng)出來(lái)了,接下來(lái)看一下Plian2明文第二組如何去做才沧。

原理是通過(guò)前一組的密文和本組函數(shù)解密后的值進(jìn)行異或運(yùn)算得到明文2迈喉。

For($i=0;$i<=15;$i++){

$Plain2[$i]=decrypt($Cipher2[$i]) Xor $Cipher1[$i];

}

這時(shí)我們同樣得到了明文組2,下面我們把Plain1和Plian2連接起來(lái)糜工。得到了原本的明文Plaintext


0x3:攻擊

剛剛我們已經(jīng)了解了加密和解密的過(guò)程弊添,此時(shí)的重點(diǎn)來(lái)了,如果我們改變了第一組的密文捌木,令它去和函數(shù)解密后的第二組密文(decrypt(Cipher2))進(jìn)行異或油坝,這時(shí)我們就會(huì)得到不一樣的第二組明文,我們此時(shí)是可以通過(guò)控制第一組的密文來(lái)得到我們想要的第二組的明文的刨裆。這就是所謂的cbc字節(jié)翻轉(zhuǎn)攻擊澈圈。后面會(huì)詳細(xì)講解攻擊過(guò)程。先想想以下的問(wèn)題帆啃。

如何利用瞬女?

設(shè)有一個(gè)驗(yàn)證輸入內(nèi)容的WEB應(yīng)用程序是先驗(yàn)證內(nèi)容有沒(méi)有非法字符,然后再進(jìn)行aes-128-cbc加密所傳輸?shù)臄?shù)據(jù)努潘,并且解密后的數(shù)據(jù)沒(méi)有經(jīng)過(guò)過(guò)濾器時(shí)诽偷,我們可以通過(guò)cbc字節(jié)翻轉(zhuǎn)攻擊來(lái)繞過(guò)。例如用戶(hù)輸入#號(hào)疯坤,我們先輸入a1报慕,然后在把1翻轉(zhuǎn)成#號(hào),這樣就繞過(guò)了過(guò)濾器压怠。

字節(jié)翻轉(zhuǎn):

剛剛講述了CBC解密的過(guò)程眠冈,核心在于我們控制上一組的密文去改變當(dāng)前組的明文。

也就是Plain2[0]=decrypt(Cipher2[0]) Xor Cipher1[0]

這時(shí)我們希望解密后Plian2[0]的值是'a'菌瘫,只需改變Cipher1[0]的值就可以了蜗顽。

那么具體改成什么呢?

推導(dǎo)過(guò)程:

設(shè) 要改變Cipher1[0]的值為x

則? 'a' ^ x = decrypt(cipher2[0])

而又因?yàn)椋篜lain2[0] ^ Cipher1[0]=decrypt(cipher2[0])

把decrypt(cipher2[0]) 代入第一個(gè)式子得

'a' ^ x = Plain2[0] ^ Cipher1[0]

解得x= Plain2[0] ^ Cipher1[0] ^ 'a'

x是我們要賦值的雨让,也就是Cipher1[0] 雇盖,所以最后寫(xiě)出的語(yǔ)句為:

Cipher1[0]=Plain2[0] ^ Cipher1[0] ^ 'a'

Plain2[0]是原明文組2的第一個(gè)字節(jié)(已知),Cipher1[0]是第一組密文的第一個(gè)字節(jié)(已知)

此時(shí)再把Cipher1和Cipher2連接起來(lái)生成Ciphertext宫患,把C刊懈,就會(huì)成功變成我們想要的明文这弧。

修復(fù)IV:

當(dāng)我們破壞掉密文的第一組時(shí),同樣明文的第一組在解密的時(shí)候就并不是原來(lái)的明文了虚汛,這個(gè)時(shí)候我們需要修復(fù)初始向量IV匾浪,給它一個(gè)新的值,

使NewIv ^ NewCipher1 = Plain1(原)

推導(dǎo)過(guò)程:

Plain1(損壞) ^ iv = decrypt(newCipher1)

Newiv=Plain1(原) ^ decrypt(newCipher1) (目的是要給Newiv賦值)

把第一個(gè)式子代入到第二個(gè)式子中得到:(此時(shí)Plain(原) 已知卷哩,Plain1(損壞)已知)

Newiv=Plain1(原) ^ Plain1(損壞) ^ iv

有了Newiv和翻轉(zhuǎn)好的Ciphertext蛋辈,這時(shí)網(wǎng)站后端解密后的明文就是我們構(gòu)造好的明文了。

0x4:EXP腳本:

下面是本人使用PHP編寫(xiě)的字節(jié)翻轉(zhuǎn)腳本:

<meta charset="utf-8">

<form action='' method="POST">

<input type="text" name='id' value='' required="true">輸入你的明文

<br/>

<input type="text" name='cp' value='' required="true">輸入你的ciphertext

<br/>

<input type="text" name='ks' value='' required="true">輸入你想改變的字符所在的塊數(shù)(大于1)

<br/>

<input type="text" name='wz' value='' required="true">輸入字符在其塊中的位置(從零開(kāi)始)

<br/>

<input type="text" name='ys' value='' required="true">輸入原始字符

<br/>

<input type="text" name='tg' value='' required="true">輸入用于替換原字符的目標(biāo)字符

<br/>

<input type="submit" name='submit' value='獲得翻轉(zhuǎn)后的Ciphertext'>

</form>

<?php

if(isset($_POST['id']) && isset($_POST['cp']) ){

$plain=$_POST['id'];

echo "原始plain為:"."<br/>";

$row=ceil(strlen($plian)/16);

for($i=0;$i<$row;$i++){

? ? echo substr($plian,$i*16,16).'<br/>';

}

if(isset($_POST['ks']) && isset($_POST['wz']) && isset($_POST['tg'])? && isset($_POST['ys'])){

$wz=$_POST['wz'];

$value=intval(($_POST['ks'] -2))*16 + intval($wz);

$cipher=base64_decode(urldecode($_POST['cp']));

$cipher[$value]=chr(ord($cipher[$value]) ^ ord($_POST['ys']) ^ ord($_POST['tg']));

echo "翻轉(zhuǎn)后的cipher:";

echo urlencode(base64_encode($cipher));

}

}

修復(fù)iv的腳本:

<meta charset="utf-8">

<form action='' method="POST">

<input type="text" name='id' value='' required="true">輸入原明文組內(nèi)容(16個(gè)字節(jié))

<br/>

<input type="text" name='iv' value='' required="true">輸入iv

<br/>

<input type="text" name='lmmw' value='' required="true">輸入BASE64后的損壞明文組(BASE64前的長(zhǎng)度為16個(gè)字節(jié)的損壞組)

<br/>

<input type="submit" name='submit' value='獲取NEWiv'>

</form>

<?php

if(isset($_POST['id'])? && isset($_POST['iv']) && isset($_POST['lmmw'])){

$plain=$_POST['id'];

$iv=base64_decode(urldecode($_POST['iv']));

$row=ceil(strlen($plain)/16);

$lmmw=base64_decode($_POST['lmmw']);

$newiv='';

for($i=0;$i<=15;$i++){

$newiv .= chr(ord(substr($plain,$i,1)) ^ ord($iv[$i]) ^ ord(substr($lmmw,$i,1)) );

}

echo "newiv為:".urlencode(base64_encode($newiv));

}

(為了方便做題将谊,輸入cipher和iv時(shí)請(qǐng)輸入經(jīng)過(guò)url編碼后的內(nèi)容冷溶,同樣程序輸出的內(nèi)容也是經(jīng)過(guò)url編碼的。)

小結(jié):初次寫(xiě)文尊浓,如有錯(cuò)誤麻煩指出逞频,感謝各位,多多擔(dān)待栋齿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載苗胀,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末瓦堵,一起剝皮案震驚了整個(gè)濱河市基协,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菇用,老刑警劉巖澜驮,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惋鸥,居然都是意外死亡杂穷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)卦绣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)亭畜,“玉大人,你說(shuō)我怎么就攤上這事迎卤。” “怎么了玷坠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵蜗搔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我八堡,道長(zhǎng)樟凄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任兄渺,我火速辦了婚禮缝龄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己叔壤,他們只是感情好瞎饲,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著炼绘,像睡著了一般嗅战。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俺亮,一...
    開(kāi)封第一講書(shū)人閱讀 52,337評(píng)論 1 310
  • 那天驮捍,我揣著相機(jī)與錄音,去河邊找鬼脚曾。 笑死东且,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的本讥。 我是一名探鬼主播珊泳,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼囤踩!你這毒婦竟也來(lái)了旨椒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤堵漱,失蹤者是張志新(化名)和其女友劉穎综慎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體勤庐,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡示惊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了愉镰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片米罚。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖丈探,靈堂內(nèi)的尸體忽然破棺而出录择,到底是詐尸還是另有隱情,我是刑警寧澤碗降,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布隘竭,位于F島的核電站,受9級(jí)特大地震影響讼渊,放射性物質(zhì)發(fā)生泄漏动看。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一爪幻、第九天 我趴在偏房一處隱蔽的房頂上張望菱皆。 院中可真熱鬧须误,春花似錦、人聲如沸仇轻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拯田。三九已至历造,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間船庇,已是汗流浹背吭产。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸭轮,地道東北人臣淤。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像窃爷,于是被迫代替她去往敵國(guó)和親邑蒋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容