1. 程式人生 > >Bugku CTF 程式碼審計 writeup(未完待續)

Bugku CTF 程式碼審計 writeup(未完待續)

Bugku CTF 程式碼審計 writeup

0x01extract變數覆蓋

這裡寫圖片描述
extract()函式功能:從陣列中將變數匯入到當前的符號表。使用陣列鍵名作為變數名,使用陣列鍵值作為變數值。
extract(array,extract_rules,prefix)
題中給出extract($_GET),相當於:
$shiyan = $_GET[‘shiyan’]
$flag = $_GET[‘flag’]。
另外,isset()函式判斷$shiyan變數是否設定,
這裡寫圖片描述
像這樣,即使變數為空,isset()函式也為true。
payload:?shiyan=&flag=
或者利用php://偽協議:payload:?shiyan=&flag=php://input

0x02strcmp比較字串

這裡寫圖片描述
strcmp(str1, str2)比較兩個字串大小,若是非字串(例如陣列)比較,則會出錯。在5.3之前的php中,顯示了報錯的警告資訊後,將return 0。
payload:?a[]=1

0x03urldecode二次編碼繞過

這裡寫圖片描述
eregi()在一個字串中搜索指定的模式的字串,搜尋不區分大小的正則匹配。
urldecode()解碼以編碼的URL字串,但是$_GET[]會將引數解碼一次。
這裡寫圖片描述
若本題將“hackerDJ”進行兩次URL編碼,在eregi()中比較”hackerDJ”與$_GET[id]是否相同,$_GET會解碼一次,從二次URL編碼變成一次URL編碼;urldecode()會將$

_GET[id]從二次URL編碼變成一次URL編碼,賦值給$_GET[id],當$_GET[id]與“hackerDJ”比較時,$_GET[id]再從一次URL編碼解碼,最後比較相等得到flag。
將“hackerDJ”進行兩次URL編碼。
payload:?id=%25%36%38%25%36%31%25%36%33%25%36%62%25%36%35%25%37%32%25%34%34%25%34%61

0x04md5()函式

這裡寫圖片描述
md5()計算字串的MD5雜湊值。
md5()函式不能處理陣列,使用陣列繞過,md5(array)會返回null。
payload1:?username[]=1&password=2

0x05陣列返回NULL繞過

這裡寫圖片描述
strpos(string, find[, start])查詢字串在另一字串中第一次出現的位置。
ereg()正則匹配,需使password中只含有英文字母和數字,又因為strpos()需要匹配“–”才能得到flag,可以使用陣列繞過ereg()和strpos()。
ereg()只能處理字元,而password是陣列,所以返回的是null,三個等號的時候不會進行型別轉換。所以null!==false。
strpos()的引數同樣不能夠是陣列,所以返回的依舊是null,null!==false也是正確。
payload:?password[]=1
思路二:ereg()可以進行%00截斷,繞過正則匹配。
payload:?password=1%00--

0x06弱型別整數大小比較繞過

這裡寫圖片描述
is_numeric(var)檢測變數是否為數字或數字字串,是則返回true,否則返回false。
is_numeric()對於空字元%00,無論%00放在前面還是後面都可以判斷為非數值,而空格%20只能放在數值後面,實質上都是弱型別轉換。
payload1:?password=1337%00
payload2:?password=1337%20
payload3:?password=1337a

0x07sha()函式比較繞過

這裡寫圖片描述
同md5()一樣,sha1()函式也無法處理陣列,因此可以構造陣列繞過。
payload:?name[]=1&password=2

0x08md5加密相等繞過

這裡寫圖片描述
md5生成的以“0e”開頭的雜湊值都解釋為0,所以PHP在判斷時會認為相同。
payload:?a=240610708

0x09十六進位制與數字比較

這裡寫圖片描述
ord()返回字串中首個字元的ASCII值。
題目中會要求輸入的password中不能有0~9數字,並且還需要判斷$number==$_GET[password]。所以將$number=3735929054轉換為16進位制“deadc0de”,再在前面加上0x表示16進位制。
payload:?password=0xdeadc0de

0x10ereg正則%00截斷

這裡寫圖片描述
題目通過ereg()函式判斷password中是否只含有字母或數字,進而限制password長度小於8,並且值小於9999999;在此前提下用strpos()函式搜尋password中是否含有“-”,若是則輸出flag。
解法一,利用陣列繞過strpos()函式。
payload:?password[]=9999999999
解法二,利用ereg()%00截斷漏洞,在用科學記數法來構造1e9滿足strlen($_GET[‘password’]) < 8 && $_GET[‘password’]> 9999999這個條件,再加上“-”來滿足strpos()的條件。
payload:?password=1e9%00*-*

0x11strpos陣列繞過

這裡寫圖片描述
構造陣列繞過,並且值含有數字。
payload:?ctf[]=1

0x12數字驗證正則繞過

這裡寫圖片描述
直接POST一個password就可以,並且小於12個字元。
payload: POST:password=1