针对哥斯拉的一些检测思路

近日,网上发布了一款名为“哥斯拉”的webshell管理工具。与冰蝎类似,哥斯拉也采用了加密流量通信来躲避WAF等安全设备的检测,另外该工具自带了一些插件模块,实现了写内存webshell、与Meterpreter联动、bypass open_basedir等功能。由于哥斯拉实现了众多强大的功能,加之近日网上发布的冰蝎3.0 bug众多,预计在未来一段时间,哥斯拉可能会广受攻击方青睐。

无论是冰蝎还是哥斯拉,可以看到未来的攻击工具可能发展的方向都是利用动态加密流量来躲避传统的安全防护设备基于流量特征的检测,这对攻击的检测带来了很大的挑战。对哥斯拉这个工具还是蛮感兴趣的,顺手分析了哥斯拉的特征,对检测思路做了一个简单总结。

0x1 静态特征

对于静态特征的检测主要针对于webshell上传阶段。对于静态特征的识别应该是最简单的检测方法,只需要把哥斯拉的webshell提取相应的特征然后进行检测即可。当时这种检测方法往往只适合用于直接的文件上传漏洞检测,而当攻击者使用诸如反序列化漏洞或者命令执行等漏洞写入webshell,则可以实现在通讯流量中不直接传递webshell原始内容写入webshell。另外,如果不是用哥斯拉默认生成的webshell,对webshell进行改造同样可以绕过静态特征的匹配。

哥斯拉默认的webshell生成支持JAVA、C#以及PHP三种类型,其中JAVA支持生成jsp以及jspx两种后缀webshell,C#支持aspx、asmx、ashx后缀,PHP就支持php后缀webshell(PHP环境可能支持解析很多后缀类型的文件,如php3、php5、phtml、pht,但是语法都是兼容的)。

先看JAVA的,主要原理和冰蝎的差不多。关键在于加密、类加载和反射,可以提取关键操作的代码作为静态检测的特征,如:
AES加/解密:javax.crypto.Cipher.getInstance(“AES”)
类加载:ClassLoader
反射:Class.forName

C#的webshell核心在于使用Assembly来动态解析执行已编译的DLL二进制文件,以及流量加密。使用Assembly的特征为System.Reflection.Assembly,实现加/解密:System.Security.Cryptography.RijndaelManaged()

PHP没有沿用AES加密的流量,而是通过异或实现自定义的加密,并且直接使用eval函数进行代码执行。

0x2 通讯流量特征

和冰蝎类似,哥斯拉为加密的通讯流量,因此通过流量进行检测会有很大的难度,由于WAF等流量检测型安全设备无法对加密的流量进行解密,因此只能采用一些比较宽泛的匹配规则进行检测,这算是比较粗暴的方法,粗暴的检测方法必然也会带来一定的误报,特别是一些客户自身应用本身就采用自定义加密流量进行通讯时会可能导致大量的误报。对于这种的情况,可以在WAF调试及日常的安全运营工作中提前识别这些较为特殊的应用误报并剔除掉对应的检测规则,减少误报。但这样也必然会带来一定的漏报风险。

除了采用宽泛的检测规则之外,作者在编写工具时有意或者无意引入一些其他特征也可以作为辅助的检测特征,并且基于这些特征的匹配能够实现比较高的检出率和较低的误报率。比如,之前对于冰蝎的检测主要是基于在密钥协商阶段以及请求头部产生的特征。分析发现哥斯拉的作者在编写工具的时候也引入了一些特征,可以基于这些特征提高检出率。

1.User-Agent (弱特征)
哥斯拉客户端使用JAVA语言编写,在默认的情况下,如果不修改User-Agent,User-Agent会类似于Java/1.8.0_121(具体什么版本取决于JDK环境版本)。但是哥斯拉支持自定义HTTP头部,这个默认特征是可以很容易去除的。

2.Accept(弱特征)
Accept为text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
对这个默认特征应该很熟悉了,之前冰蝎也出现过同样的Accept。为什么会这么巧合出现两个工具都会出现这个特征呢,其实这个也是JDK引入的一个特征,并不是作者自定义的Accept(参考:https://bugs.openjdk.java.net/browse/JDK-8177439)。同样的这个默认特征也可以通过自定义头部去除,只能作为默认情况下的辅助检测特征。

3.Cookie (强特征)
哥斯拉的作者应该还没有意识到,在请求包的Cookie中有一个非常致命的特征,最后的分号。标准的HTTP请求中最后一个Cookie的值是不应该出现;的,这个可以作为现阶段的一个辅助识别特征。后面如果作者意识到这个问题的话应该会发布新版本修复这个问题。

4.请求体特征 (较强特征)
因为无法准确识别加密的请求体,所以只能采用比较宽泛的匹配条件去匹配请求体特征,宽泛的匹配思路其实就是基于区别大部分正常的数据包,加密数据包自身体现的特征。这种宽泛的匹配在一些情况下可能会带来误报,因此有时候难以作为一种非常有效的检测手法。

哥斯拉支持对加密的数据进行base64编码以及原始的加密raw两种形式的通讯数据,对于请求体的检测也要考虑两种情况。

首先看一下base64编码的数据包,对于这种数据包唯一的识别方法就是识别流量中的base64编码。当然不能仅仅去识别数据包中存在base64编码就拦截,因为很多应用正常的参数也会采用base64编码加密。哥斯拉在进行初始化时会产生一个比较大的数据包,后面进行命令执行等操作时产生的base64数据包会比较比较小。在长度上做一个匹配条件在一定程度上也可以降低误报率。


对于原始加密raw请求体,没想到比较好的方法,目前只想到到了匹配较多的不可见字符的思路。同样的,这种检测方法也会产生误报,像一些对传输安全要求比较高的金融机构,不少应用也会实现一些加密的通讯流量。需要注意的是,在匹配不可见字符时,需要排除文件上传,也就是multipart/form-data数据包,因为文件上传的流量也会包含大量的不可见字符。

5.响应体特征 (强特征)
和请求体一样,请求响应体也分两个格式,base64编码的和原始加密raw数据。如果请求体采用base64编码,响应体返回的也是base64编码的数据。在使用base64编码时,响应体会出现一个很明显的固定特征。这个特征是客户端和服务端编写的时候引入的。

从代码可以看到会把一个32位的md5字符串按照一半拆分,分别放在base64编码的数据的前后两部分。整个响应包的结构体征为:md5前十六位+base64+md5后十六位。

从响应数据包可以明显看到这个特征,检测时匹配这个特征可以达到比较高的检出率,同时也只可以结合前面的一些弱特征进行检查,进一步提高检出率。因为md5的字符集范围在只落在0123456789ABCDEF范围内,因此很容易去匹配,正则匹配类似于(?i:[0-9A-F]{16})[\w+/]{4,}=?=?(?i:[0-9A-F]{16})。需要注意的是md5需要同时匹配字母大小写两种情况,因为在JAVA版webshell响应中为大写字母,在PHP版中为小写字母。

编写对应检测规则,在ModSecurity上测试成功拦截。

但是比较遗憾的是对于原始加密数据的raw形式响应包并没有比较好的检测思路,只能和请求体检测一样,匹配不可见字符。