BugkuCTF –WEB-備份是個好習慣(備份原始碼洩露+md5漏洞)
先開啟題目看一下
題目剛開始給了一串md5值
嘗試先去解密一下
空密碼??題目名字叫做備份是個好習慣。掃一下網站目錄,瞅瞅有沒有備份的檔案啥的
發現了一個.bak檔案,估計是index.php備份的原始碼,下載下來看一下
附上有關備份檔案的知識:備份檔案一般在後綴名後新增.bak或者.swp
<?php /** * Created by PhpStorm. * User: Norse * Date: 2017/8/6 * Time: 20:22 */ include_once "flag.php"; ini_set("display_errors", 0); $str = strstr($_SERVER['REQUEST_URI'], '?');//將url中?(包含?)後邊的字串賦值給變數str $str = substr($str,1);//從第一個字元開始,後邊的字串賦值給變數str $str = str_replace('key','',$str);//使用空字串替換$str中的key parse_str($str); echo md5($key1); echo md5($key2); if(md5($key1) == md5($key2) && $key1 !== $key2){ echo $flag."取得flag"; } ?>
1.strstr() 返回關鍵字之後的字串一直到末尾。
strstr(string,search,before_search) string(必須)被搜尋的字串,search(必須)關鍵字,beore_search(可選)預設為"false"的布林值,如果設定為"ture",它將返回search引數第一次出現之前的字串部分
<?php
echo strstr("I love Shanghai!","I");
?>
I love Shanghai!
2.substr(string,start,length),返回string中從第start個字元開始之後的字串。(length選填)如果有length則為start之後length長度的字串
3.str_replace() 函式以其他字元替換字串中的一些字元(區分大小寫)。
str_replace(find,replace,string,count) 在(string)中查詢(find),並使用(replace)進行替代 count 替換次數(預設1次)4.parse_str() 函式把查詢字串解析到變數中 parse_str(string,array) 如果未設定 array 引數,則由該函式設定的變數將覆蓋已存在的同名變數
get到index.php的原始碼了,接下來就是對程式碼進行審計
原來輸出這麼一長串md5是兩個key的md5接起來的。。
接下來就是想辦法滿足if(md5($key1) == md5($key2) && $key1 !== $key2)
這個條件的意思是,如果兩個值加密後的md5值一樣,且他們未加密的值不一樣則輸出flag
方法一
md5()函式無法處理陣列,如果傳入的為陣列,會返回NULL,所以兩個陣列經過加密後得到的都是NULL,也就是相等的。
$str = str_replace('key','',$str);這句把key置為空;看到md5()函式,可分別賦值240610708和QNKCDZO。嘗試後沒變化,想到key被置空了,可以用kkeyey替換key。所以構造?kkeyey1=240610708&kkeyey2=QNKCDZO 得到flag
240610708 和 QNKCDZO md5值型別相似,但並不相同,在“==”相等操作符的運算下,結果返回了true。這是個經典的漏洞,只需要找到md5值為0exxx(xxx全為數字,共30位),這裡我提供4個都可以通過的值:240610708、QNKCDZO、aabg7XSs、aabC9RqS
<?php
echo md5(aabC9RqS);
//0e462097431906509019562988736854
echo md5(QNKCDZO);
//0e830400451993494058024219903391
echo md5(aabg7XSs);
//0e087386482136013740957780965295
echo md5(aabC9RqS);
//0e041022518165728065344349536299
?>
擴充套件小知識:
先註冊密碼為240610708的使用者A。
然後用密碼QNKCDZO嘗試登入使用者A。
倘若成功登入,則證明此網站採用了不完備的加密體制md5一次加密。
先註冊密碼為0E33455555的使用者A。
然後用密碼0E234230570345嘗試登入使用者A。
倘若成功登入,則證明此網站採用了明文進行儲存密碼!
方法二
string md5 ( string $str [, bool $raw_output = false ] )
md5()中需要傳入的是一個string型別的引數,當我們傳遞一個array時,它是不會報錯的,函式無法求出array的MD5值,這樣導致任意兩個array的MD5值都相等,從而繞過輸入數值的判斷,在ctf程式碼審計中經常遇見。
md5無法處理陣列,如果md5()傳入了陣列,則會顯示為空,所以構造?kkeyey1=240610708&kkeyey2=QNKCDZO
flag就直接爆出來了
參考:
https://www.jianshu.com/p/d433d9f89102
http://www.w3school.com.cn/php/index.asp