1. 程式人生 > >BugkuCTF –WEB-備份是個好習慣(備份原始碼洩露+md5漏洞)

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)

這個條件了,就可以獲得flag了

這個條件的意思是,如果兩個值加密後的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