前⾔
webshell免杀已经是⼀个⽼⽣⻓谈的话题了,现在的各种waf都已经可以识别常⻅webshell及其各种变形,也出现了基于沙箱技术和机器学习的waf。webshell的免杀⼀直在⼀个对抗的过沉中,今天新出的⼀个免杀webshell,可能明天就加⼊了waf的规则库中,所以我们需要尽可能多的掌握webshell免杀技巧并且⾃⼰去写⼀些webshell。能够免杀的webshell尽可能的⼩范围使⽤,⼤量使⽤必然会被waf识别并加⼊查杀规则库。
前期准备
本次测试过程中使⽤了常⻅的两个免费waf:安全狗和D盾。综合测试的结果是D盾的免杀能⼒更强,所以能过D盾webshell基本都可以过安全狗。webshell即使可以逃过D盾的查杀,也⽆法进⾏系统的命令执⾏,因为D盾还有⼀层防⽕墙。如何绕过D盾防⽕墙和360等杀毒软件还需继续学习。
webshell原理
根据功能的差别可以将webshell分为⼀句话⽊⻢,⼩⻢和⼤⻢。对于这些⻢的查杀原理基本是⼀样的,只不过代码 越多暴露的特性就会越多,⾃然就越容易被查杀。本次研究⼀句话⽊⻢的免杀,重点介绍⼀句话⽊⻢的原理。 ⼀句话⽊⻢是最简单的webshell,它的实现也相当容易,最简单的⼀句话⽊⻢如下:
@eval($_REQUEST['x']); |
或者:
assert($_REQUEST['x']); |
assert
可以换成system
等可以执⾏系统命令的PHP函数。
毫⽆疑问,这中简单原始的webshell肯定会被免杀:
eval和assert
关于eval函数
eval 是⼀个语⾔构造器⽽不是⼀个函数,不能被 可变函数 调⽤ 可变函数:通过⼀个变量,获取其对应的变量值,然后通过给该值增加⼀个括号(),让系统认为该值是⼀个函数,从⽽当做函数来执⾏
通俗的说⽐如你<?php $a=eval;$a()?>
这样是不⾏的.也造就了⽤eval
的话达不到assert
的灵活,但是在php7.1以上assert
已经不能使用了。
关于assert函数
assert()回调函数在构建⾃动测试套件的时候尤其有⽤,因为它们允许你简易地捕获传⼊断⾔的代码,并包含断⾔的位置信息。 当信息能够被其他⽅法捕获,使⽤断⾔可以让它更快更⽅便!
免杀⽅法
函数替换
例如将$_POST
替换为$_REQUEST
虽然D盾还是检测出来为后⻔,但是级别已经降低了为4级,可⻅D盾对POST
更为敏感,这⾥显然不能免杀,但是可以作为⼀种思路来配合后续的其它⽅法免杀。
字符串变形
php造作字符串的函数有:
ucwords() //函数把字符串中每个单词的⾸字符转换为⼤写。 |
通过字符串函数对关键字assert
和$_POST
进⾏变形,如:
|
D盾检测出为1级,其实1级D盾就不会拦截,可以达到免杀效果:
经过测试,D盾只要遇到这种疑似变量就会报危险,如下图,即使这个变量是⼀个⽆害的字符串,所以在这个问题 上⽆需深究。
⾃定义函数绕过
|
利⽤数组免杀
|
还可以给数组加点料:
|
除此外还可以使⽤多维数组:
|
利⽤回调函数免杀
常⽤的php回调函数有:
call_user_func_array() |
注意常⽤的回调函数⼤部分都已经加⼊了免杀套餐,所以我们需要尽可能的去寻找⽐较⽣僻的回调函数。
例如:
|
回调函数配合⽅法或类
例如回调函数配合⽅法:
|
使⽤特殊字符
特殊字符有:\\n
,\\r
,\\t
等。
|
经测试特殊字符的免杀性不强,勉强可以使⽤。
利⽤POST包获取关键字
|
也可以使⽤⾃定义的加密⽅式,post包传⼊参数再由webshell解密,此种⽅式现有的waf查杀能⼒基本为0.
⽆字符特征⻢
利⽤异或或者编码等⽅式构造⽆字符的webshell,例如:
|
异或绕过
github上有个项⽬可以使⽤python⽣成异或免杀的webshell,不过其特征已被捕获,现在已经⽆法过D盾了。github地址
不过可以使⽤下⾯这篇⽂章的思路来进⾏修改重新免杀:随机异或⽆限免杀D盾之再免杀
举个例⼦:
|
或者:
|
PHP7.1之后免杀困境
php7.1之后我们已经不能使⽤强⼤的assert
函数了,waf只要把函数封死就可以有效的阻⽌webshell免杀,⽽eval
并没有assert
那么灵活。后期⼤家可能更加倾向使⽤⼤⻢。