AntSword流量分析
蚁剑中默认的编码模块有:base64.js、chr.js、chr16.js、rot13.js。这里分析一下常用的base64模块为例,查看编码器 randomID 随机生成一个随机数,需要执行的代码在 data['_'] 当中,下面Buffer.from(data['_']).toString('base64'); 就是将 data['_'] 中的内容进行base64编码,其中可以看到 data[pwd], 此函数的作用是作为参数传递的,所以这里在流量当中是明文传输。
从上图可以看到 _0x81bf9df1758a97 这个参数是base64加密的,但是aaa这个参数并不是加密的,但是这种加密也是非常容器被waf探测到,其他的编码器也是相同的道理,其中有url编码,生成随机字符串为变量名称,chr编码,16进制编码。
蚁剑内置了一个编码器模块,有一个RSA模块,使用了RSA非对称加密进行传输,新建编码器 -> RSA配置 -> 点击生成公私钥,然后将生成好的shell放到目标机器点击连接查看流量,可以直接使用公钥进行解密,但是这种需要目标机器安装OpenSsh扩展库才可以。
蚁剑修改了编码器也会有一个明显的特征就是在执行命令,文件操作等地方会有0x开头的参数,这是写死在蚁剑源码当中的跟编码器无关。
冰蝎2.0流量分析
代码分析:
以php版本的webshell为例分析,查看冰蝎的webshell代码,先会对 Get 传入的pass这个参数进行检查,如果存在的话会以时间的方式生成长度16的随机key,然后存入到session当中,再往后判断是否开启了openssl这个扩展,开启的情况就会开启AES进行解密,得到中间结果字符串 assert|eval("phpinfo();") 此数据是由冰蝎加载器发出的,已经定义好的,服务端利用explode函数将拆分为一个字符串数据,然后以可变函数方式调用索引为0的数组元素,参数为索引为1的数组元素,即为 assert("eval("phpinfo;")")。没有开启的情况,进行异或处理然后通过base64加密。这就是同时在早期有一定的免杀效果,但是这个函数现在已经被标注为危险函数。
流量分析:
使用Wireshark 查看连接webshell的流量进行分析,查看会发送俩次Get请求,分为俩次Get的握手请求,第一次请求服务端产生密钥写入session,session和当前会话绑定。不同的客户端的密钥也是不同的,第二次请求是为了获取key。此时的 99030fc0bb93de17就为解密代码的key。
post的数据可以利用上面的Key进行解密获得代码,可以自己写代码也可以使用在线网站进行解密,在线网站只有在这个网站解密成功,http://tools.bugscaner.com/cryptoaes/
解密后的内容会对代码再次进行了一次base64的编码。
左边是没有开启OpenSsl扩展的响应,右面是开启OpenSsl扩展的,对响应进行AES的解密 (下图2) ,base64解码后的内容:{"status":"success","msg":"1a6ed26a-009d-4127-a6fb-1fd4e90c84fa"}
现在很多厂商已经对返回的内容进行匹配。所以这种动态加密的方式会在冰蝎3取消。
冰蝎3.0流量分析
代码分析:
同样这里以php分析为例,查看shell代码,对密码进行了md5的加密,少了一个响应随机生成16位字符key的功能,改了一个ui的框架,界面由swt改为javafx。
流量分析:
分析流量发现相比2.0少了动态密钥的获取的请求,aes密钥变为 md5("pass")[0:16] 意思就是为32位md5的前16位。全程不再交互密钥生成。一共就俩次请求,第一次请求为判断是否可以建立连接,少了俩次get获取冰蝎动态密钥的行为,第二次发送phpinfo等代码执行,获取网站的信息。
解密第一次发送的数据查看,这里有一个参数为 $content 这个变量名称和里面的内容为随机生成的, 目的是为了绕过 $Content-Length ,这个已经在冰蝎2.0中已经被加入了Waf的检测规则当中,所以在冰蝎3.0当中用数据填充的方式绕过。
由此可以看出冰蝎2.0和3.0的区别主要在于取消动态密钥获取,目前很多waf等设备都做了冰蝎2.0的流量特征分析。所以3.0取消了动态密钥获取。
哥斯拉流量分析
这里首先查看一下PHP的加密器 PHP_XOR_BASE64 的代码 ,其中 $E 为异或的加密或解密, $F=O(E(O($_POST[$P]),$T)); 主要用于解密代码, 解密流程为:接受代码 -> Base64编码 -> E函数进行异或加密 -> 再Base64编码, Q(E(@run($F),$T)); 为加密代码,加密流程为:E函数进行异或加密 -> Base64编码。最后密码和后面的字符串进行md5加密,其中 $T 为密钥的md5值的前16位,以16位字符分割为2份分别输出在加密内容的首部和尾部。
点击哥斯拉的测试连接功能发现一共发送了三次包,第一段为加密的php代码,非常的长,第一个包的响应为空。
将 $V、密码 $P、Key $T 复制出来,还有base64解密的函数 E、异或的函数 O,单独摘出来,然后使用$F=O(E(O($_POST[$P]),$T)) 进行解密。
解密后的代码一共300多行,包含各种功能,如获取服务器基本信息、文件上传、命令执行、数据库操作等功能的函数。
第二个请求响应AWEzAAN/WFI3XHNGaGBQWDEHPwY4fSQAM2AIDw==,解密后为 methodName=dGVzdA== ,后面的 dGVzdA==为test的base64编码,用来测试shell的连通性,成功会向客户端返回OK。
注:响应解密的时候需要将前16位和后16位删除。
第三个请求是为了获取环境变量。
第二种加密Raw和Base64加密的区别:
Raw : Raw是将加密后的数据直接发送或者输出
Base64 : Base64是将加密后的数据再进行Base64编码
哥斯拉的jsp的加密和PHP的加密不同,Jsp的加密主要为Base64+AES,AES的key是将生成shell时的 key 的md5 32 位前36位进行切割。
这里为响应的代码,影响为密码的md5的首尾,和PHP的加密器的响应器的内容相同,修改响应的代码,如下图2中的黄线内容,直接响应base64的内容。
流量同样是三次请求,第一次请求为空,第二次响应为methodName=dGVzdA==,dGVzdA== 为OK,第三次为网站的环境变量。
加密流程:
AntSword:
requests |
response |
base64等方式 |
明文 |
冰蝎2.0:
requests |
response |
开启Openssl扩展-动态密钥aes加密 |
aes加密+base64 |
未开启Openssl扩展-异或 |
异或+base64 |
冰蝎3.0:
requests |
response |
开启Openssl扩展-静态密钥aes加密 |
aes加密+base64 |
未开启Openssl扩展-异或 |
异或+base64 |
哥斯拉:
requests |
response |
php的为base64+异或+base64 |
异或+base64+脏字符 |
jsp的为Base64+AES |
aes+base64+脏字符 |