良好的习惯是人生产生复利的有力助手
最近一段时间,看了很多认知方面的书,对我的改变还是很大的。
之前看待事物总是看其一角,做技术也是囿于一面,思维不是很开阔,经过不断地看书,思考,认知慢慢有了 改变,获益良多。
作为技术人员,我的建议是不要总是看技术书籍或者一心研究技术,多看看哲学,认知,效率,商业方面的书籍,可以让你看到人生多种可能性,同时反哺技术上的视野和思考模式。
现在遇到技术项目,尽量不再立即着眼于解决它,而是选择如何看待它,比如会问自己一些问题:
。。。。。。
前面只是一些自己的感悟,如果对大家有启发,有帮助的话,那就最好不过了。言归正传,在上一篇文章中,讲解了webshell如何绕过RASP的方法论,并根据方法论设计了 webshell。
虽然有一些绕过方法,但RASP依然是webshell检测中最强的存在,如果再和HIDS联动,那些绕过方法在数据捕获层面都会失效,纵深防御不是说说而已。
今天说的承接上文,依然是webshell的绕过,不过不叫绕过,叫免杀。对付的不再是RASP(实时检测手段),而是其它离线的检测手段,目的是以攻促防。
这次讲的内容主要是方法论,我给的是思考方法,而不会直接给一个通杀的webshell,因为没有意义。如果你还在追求这种浮躁的方式,只能说还是没脱离“脚本小子”的范畴。
检测方案的边界
在绕过任何一个检测引擎之前,思考是很关键的,尤其是新手。新手特别喜欢的干的是 找一大批样本上传,看看能不能命中一个,这其实对你是没有任何提高的。首先要做的是思考,下面我画了一张思维导图,理了理思路。
思考过程分为了四个部分,层层递进,应用在其他方案绕过上,也是可以的,接下来我会根据这四个部分进行解释。
知己知彼
任何一个检测引擎的大部分检测手段,都是已知的,就算有创新,那毕竟是很少的一部分,因此首要的入手点是熟悉已知的主流检测方案,对已知的检测方案至少有一个原理性的了解。在之前长亭的《Webshell检测能力进化笔记》 一文中,简要概括了主流的检测手段及缺陷:
1.基于正则文本特征检测
初期对付webshell基本上都是这种方案,根据已知webshell使用的函数和参数,使用正则表达式制定相应的黑规则。
但是正则文法表达能力不足,加上webshell语法灵活,很容易通过混淆绕过这种方式。
2.基于统计特征的文本检测
之后为了对付混淆,人们把视野放到了统计学上,通过统计文本熵,字符串长度,特殊符号个数,重合指数,压缩比等信息制定告警阈值,在对付混淆上有一定的威力。之后随着机器学习的兴起,阈值设置就交给了算法。
但是这种方式着眼于全局,无法顾及局部细节,将混淆的恶意代码插入到正常文件中,基本上就失效了。
3.基于AST的语法特征检测
为了弥补统计特征的不足,进一步深化,进行语法检测,关注于每个函数和参数,这种方式精确,误报较少。但是对于PHP这种动态特性很多的语言,检测就比较吃力,AST是无法了解语义的。
4.动/静态符号执行
其实本质上是数据流分析, 如果用户可控的外部变量进入特殊的函数,那么我们就可以判定这个样本的危险系数很高。举例:
php
$func = $_REQUEST[i];
$arr = array('test'=>1,$_REQUEST[j]=>2);
uasort($arr,$func);
对数据流进行跟踪分析的话,就会得出如下有向图,这种检测方法覆盖率高,误报少。
数据流分析分为静态和动态两种,静态分析通过语法树遍历的方式,对数据流进行跟踪,如果做的好的话,可以对混淆的变量和函数进行还原。动态分析不用做变量还原,但难度更高,不过基本原理是一致的。
5.机器学习/深度学习
这个不是很主流,也算一种辅助手段,特征主要来源于opcode序列和文本分词,遇到问题和2类似。
6.沙箱
沙箱在这方面检测就比较鸡肋了,输入参数未知,沙箱是很难发现威胁的,只是作为一个补充。
这几种检测方案都属于离线检测方式,除了他们自身解决方案的缺陷外,还有一个本质的缺陷就是信息不完备,我们给webshell传参,它是无法得知的。正是因为这个原因,以上检测方案的效果,从原理上是弱于RASP的。(RASP的性能如果做的很高就好了,就不需要其他的了)
在了解主流的检测方案后,并不急于设计免杀webshell绕过引擎,你需要了解你的对手,这个时候需要进入探测阶段,是非常重要的一环。我一般从五个方面着手,包括覆盖率,误报率,容忍度,验证已知手段,猜测未知手段。
我一般会准备一些常见的webshell,但是种类必须不同,测试一下引擎的覆盖率。
接着制造一些有敏感函数,但是无恶意功能的样本,测试一下引擎的误报率。例如:
eval("echo 2323;")
最后,找一些正常样本,然后不断添加敏感函数和参数,测试一下引擎的容忍度。
已知手段主要分为两大类,静态和动态,每种方式又包含很多小类,如何验证具体手段属于静态或者动态中的哪一个?
选择一个普通的webshell,不要一直换,然后对这个webshell的函数名,参数名进行逐步隐藏,一一验证已知的手段。
<?php echo shell_exec($_GET[‘cmd‘]);?>
既然是猜测,那就看造化了,还是建议不要一直换webshell,只会让你混乱,而是逐步变形,有创新手法也不会离开静态和动态的圈子。
通过上面的手段,对引擎有了个基本的了解,下面要积累自己的力量,磨刀霍霍了。
这时候要去涨涨经验了,看看其他人是如何绕过各种检测引擎的,他们对付的是哪种检测手段,需要大家自己总结。我给大家准备了一下资料,足够大家学习一波了。
https://xz.aliyun.com/t/7151 https://xz.aliyun.com/t/3959 https://klionsec.github.io/2017/10/11/bypasswaf-for-webshell/ https://blkstone.github.io/2016/07/21/php-webshell/ https://www.cnblogs.com/littlehann/p/3522990.html
只是看文章还是不够,去github上找一下大家贡献的webshell,看看他们的免杀有什么可取之处。
php手册是最权威的php资料,中文版网址:https://www.php.net/manual/zh/。
php的语法灵活,内置函数丰富,大家通过php手册可以随时查询自己想要的功能。
1、http://www.d99net.net/down/WebShellKill_V2.0.9.zip
2、百度WEBDIR+
https://scanner.baidu.com/
3、河马
https://www.shellpub.com/
4、Web Shell Detector
https://github.com/emposha/PHP-Shell-Detector
5、CloudWalker(牧云)
https://webshellchop.chaitin.cn/
https://github.com/chaitin/cloudwalker
6、深度学习模型检测PHP Webshell
http://webshell.cdxy.me/
对引擎也熟悉了,对免杀的知识也有了积累,下面就可以根据缺陷和问题进行降维打击了。一般情况下,很多人绕不过的时候,有时候会问能不能给点思路,引擎把XXX给封锁了,遇到XXX就会告警。
其实你发现的问题就是解决问题的方向。
举个例子:
<?php
system("ls");
样本中出现system就会报警,那你要做的就是根据你发现的问题,将system隐藏掉。可以变量替换,可以字符串拼接,旋转加解密。
<?php
$a='sys'."tem"
$a("ls");
这时候还报警的话,那就可能会有静态变量还原,动态分析的可能。这个时候再变化,自己写函数生成 system,同时需要外部变量的参与才行。
<?php
a='sys'._GET[i];
$a("ls");
就这样按照发现的问题,结合现有手段,一步一步变换。
感谢青藤团队邀请,欢迎大家来对抗。同时,我们洋葱团队开发的WebShell检测引擎下个月也会进行众测,以攻促防,欢迎大家参与。