目錄
1、web104
2、web105
3、web106
4、web107
5、web108
1、web104
需要傳入的 v1 和 v2 進行?sha1 加密后相等。
解法1:
這里都沒有判斷 v1 和 v2 是否相等,我們直接傳入同樣的內容加密后肯定也一樣。
?v2=1
post:?
v1=1
拿到 flag:ctfshow{bd4eea6b-872d-462c-b8f2-20f48d3ee652}?
解法2:
對于 php 強比較和弱比較:md5(),sha1() 函數無法處理數組,如果傳入的為數組,會返回 NULL ,兩個數組經過加密后得到的都是 NULL ,也就是相等的。
?v2[]=1
post:
v1[]=2
解法3:
對于某些特殊的字符串加密后得到的密文以 0e 開頭,PHP 會當作科學計數法來處理,也就是 0 的 n 次方,得到的值比較的時候都相同。
下面是常見的加密后密文以 0e 開頭的字符串:
md5:240610708:0e462097431906509019562988736854
QLTHNDT:0e405967825401955372549139051580
QNKCDZO:0e830400451993494058024219903391
PJNPDWY:0e291529052894702774557631701704
NWWKITQ:0e763082070976038347657360817689
NOOPCJF:0e818888003657176127862245791911
MMHUWUV:0e701732711630150438129209816536
MAUXXQC:0e478478466848439040434801845361sha1:10932435112: 0e07766915004133176347055865026311692244
aaroZmOk: 0e66507019969427134894567494305185566735
aaK1STfY: 0e76658526655756207688271159624026011393
aaO8zKZF: 0e89257456677279068558073954252716165668
aa3OFF9m: 0e36977786278517984959260394024281014729
0e1290633704: 0e19985187802402577070739524195726831799
?v2=aaroZmOk
?post:
v1=aa3OFF9m
2、web105
foreach 在?PHP 中用于遍歷數組或對象:
key 和 value 分別表示數組中的鍵和對應的值。
foreach ($array as $value) {// 對 $value 進行操作
}foreach ($array as $key => $value) {// 對 $key 和 $value 進行操作
}
一眼看到使用了兩個 $,直接將用戶輸入用作變量名,可能導致變量覆蓋問題。
$$key=$$value;
代碼中共有三個變量:$error,$flag,$suces
foreach($_GET as $key => $value){if($key==='error'){die("what are you doing?!");}
get 請求的 key(參數)不能是 error
foreach($_POST as $key => $value){if($value==='flag'){die("what are you doing?!");}
post 請求的 value(值)不能是 flag
(1)通過 die($error);? 輸出 flag,可以將 $error 覆蓋為 $flag,payload:
?suces=flag
? post: error=suces
get 傳入 suces=flag,請求參數不是 error,因此不會觸發第一個 die 函數;
接下來執行 $$key=$$value; 即 $suces=$flag,也就是將 $flag 的內容賦值給 $suces;
post 傳入 error=suces,value 是 suces,不是 flag,因此也不會觸發第二個 die 函數;
之后執行?$$key=$$value; 即 $error=$suces,也就是將 $suces 的內容賦值給 $error;
if(!($_POST['flag']==$flag)){die($error);
}
最后檢查是否 post 提交了 flag 并且內容就是 $flag,顯然是沒有的,前面還有一個 ! ,因此 if 語句成立,執行第三個 die 函數,輸出變量 $error 的內容,即我們 flag 的內容。
驗證:
拿到 flag:ctfshow{d346b9f7-d63f-492c-b573-c7ed4c7394e4}
其實這里的這個 $suces 只是一個中間者,我們只要不使用 error,其他任何的參數名都是可以的。
比如:
?1=flag
error=1
(2)通過 die($suces); 輸出 flag,將 $suces 覆蓋為 $flag,payload:
?suces=flag&flag=
或者?
?suces=flag
post:flag=
一來就先將 $flag 的內容賦給 $suces,之后將 $flag 賦為空(null),使得?$_POST['flag']==$flag 成立,執行?echo?"your?are?good".$flag."\n"; 和 die($suces); 進而輸出 $suces,即 flag 的內容。
3、web106
新增:
$v1!=$v2
采用數組繞過:
?v2[]=1
post:v1[]=2
拿到 flag:ctfshow{a0d7580e-60f6-4a19-bef2-af27d8c2d017}
4、web107
parse_str() 函數:把查詢字符串解析到變量中。
用法:parse_str(string,array)
參數 | 描述 |
---|---|
string | 必需。規定要解析的字符串。 |
array | 可選。規定存儲變量的數組名稱。該參數指示變量存儲到數組中。 |
關于題目代碼的詳細解釋:
parse_str($v1,$v2);
parse_str 函數將字符串 $v1 解析為變量并存儲到數組 $v2 中。
$v1 是一個包含查詢字符串的變量,例如:"flag=123&name=myon"。
解析后的結果將存儲在數組 $v2 中,例如:$v2 將包含 ['flag' => '123', 'name' => 'myon']。?
if($v2['flag']==md5($v3)){echo $flag;}
$v2['flag'] 是從解析后的數組 $v2 中獲取的 flag 參數值,檢查 $v2['flag'] 是否等于 md5($v3) 即 v3 經過 md5 加密后的值,等于則輸出 flag。
理解題目意思后,這里的 payload 就有很多,只要符合要求都可以:
?v3=123
post 傳入:
v1=flag=202cb962ac59075b964b07152d234b70
其中?202cb962ac59075b964b07152d234b70 是 123 的 md5 加密值:
拿到 flag:ctfshow{b91751db-f7b7-40ae-b920-fd2e3edc8964}
5、web108
代碼審計:?
ereg ("^[a-zA-Z]+$", $_GET['c'])
使用 ereg 函數檢查 $_GET['c'] 是否只包含大小寫字母,不滿足直接 die。
if(intval(strrev($_GET['c']))==0x36d){echo $flag;
}
通過 strrev 函數將 $_GET['c'] 反轉,使用 intval 將反轉后的字符串轉換為整數,檢查該整數是否等于十六進制的 0x36d(十進制的 877),如果相等,則輸出 $flag 的內容。
其中 ereg 函數存在 NULL 截斷漏洞,我們可以使用 %00 進行截斷,payload:
?c=a%00778
這樣正則就只會匹配 %00 之前的內容,即匹配到 a,符合要求,函數返回 true,if 語句不成立,跳過 die 函數,payload 經 strrev 函數反轉后變為?877%00a,因為是弱比較,會存在自動類型轉換,經過?intval 轉為整數 877,比較成立,輸出 flag。
拿到 flag:ctfshow{9fb901bb-8855-4a17-b4bc-a587d28a3f15}
為什么 %00 前面還要有一個 a,而不能是空的呢?
由于截斷前的內容為空,ereg 函數還是會返回 false,就像我們什么都沒有傳入一樣。