先附上大神的原文鏈接:https://www.freebuf.com/articles/we/186298.html
故事源於一道CTF賽題:
這里的webshell過濾十分嚴格,采用不含f,l,a,g……並且繞過php內置函數。
注意:
PHP7前是不允許用($a)();這樣的方法來執行動態函數的,但PHP7中增加了對此的支持。所以,我們可以通過('phpinfo')();來執行函數。(PHP7版本適用)執行:
echo urlencode(~'phpinfo');//結果:%8F%97%8F%96%91%99%90
~為取反符號,對phpinfo取反是不可顯的,故進行url編碼。
pyload:
(~%8F%97%8F%96%91%99%90)();
PHP5版本無數字字母的webshell:
上述payload對於php5版本無效。
需要用到兩個Linux Shell的知識:
1.shell下可以利用.來執行任意腳本
2.Linux文件名支持用glob通配符代替
.file執行文件是不需要具有x權限的,我們可以將文件傳到/tmp的文件夾下,使用.來執行,使用通配符來代替文件名
如下是大佬的一舉例(其中運用到了許多Linux的glob的繞過):
/tmp/phpXXXXXX就可以表示為/*/?????????或/???/?????????。
但我們嘗試執行. /???/?????????,卻得到如下錯誤:
這是因為,能夠匹配上/???/?????????這個通配符的文件有很多,我們可以列出來:
可見,我們要執行的/tmp/phpcjggLC排在倒數第二位。然而,在執行第一個匹配上的文件(即/bin/run-parts)的時候就已經出現了錯誤,導致整個流程停止,根本不會執行到我們上傳的文件。
其中,glob支持用[^x]的方法來構造“這個位置不是字符x”。那么,我們用這個姿勢干掉/bin/run-parts:
排除了第4個字符是-的文件,同樣我們可以排除包含.的文件:
現在就剩最后三個文件了。但我們要執行的文件仍然排在最后,但我發現這三個文件名中都不包含特殊字符,那么這個方法似乎行不通了。
繼續閱讀glob的幫助,我發現另一個有趣的用法:
就跟正則表達式類似,glob支持利用[0-9]來表示一個范圍。
我們再來看看之前列出可能干擾我們的文件:
所有文件名都是小寫,只有PHP生成的臨時文件包含大寫字母。那么答案就呼之欲出了,我們只要找到一個可以表示“大寫字母”的glob通配符,就能精准找到我們要執行的文件。
翻開ascii碼表,可見大寫字母位於@與[之間:
那么,我們可以利用[@-[]來表示大寫字母: