一、流量分析
1.简单介绍
冰蝎是先请求服务端,服务端判断请求之后生成一个128位的随机数,并将这个128位的随机数写入到session里面,并将这个128位的随机数返回给客户端,但是客户端并不会使用这个key作为之后的通讯的key,而是会继续重复上面过程,不断获取key,直到满足特定条件之后,才会确定是最终的key。客户端会保存这个key和响应报文里面的set-cookie的值。这个key就是之后客户端和服务端进行通讯的密匙。2.冰蝎通信分析
第一阶段:
Attacker通过GET方法或者POST方法形如下图这样请求服务器密钥。服务器使用随机数MD5的高16位作为密钥,存储到会话的SESSIONID中,并返回密钥给attacker。密钥可通过wireshark抓包看到,见下图。在wireshark中即可捕获到冰蝎客户端与服务器通信的数据包。第二阶段:
1.客户端把待执行命令作为输入,利用AES算法或XOR运算进行加密,并发送至服务端;2.服务端接受密文后进行AES解密或者XOR运算解密,执行解密后的命令3.执行结果通过AES加密后返回给attacker流量分析过程:
1.追踪HTTP流即可看到冰蝎客户端与服务器的完整通信过程。3.当冰蝎第一次访问服务器webshell时,以GET方式提交随机数字,因此服务器将会生成16位的随机字符串,写入session后通过print函数将密钥返回客户端,冰蝎第二次访问服务器时以相同方式更新密钥。二、冰蝎流量解密
(一) 解密思路
在服务器开启 PHP OpenSSL 扩展脚本的情况下,冰蝎密文采用对称加密算法AES加密,加密后还会进行 base64 编码。在客户端发起密钥协商后,会返回16位明文随机密钥。(二) 工具
AES在线解码 (http://tools.bugscaner.com/cryptoaes/)BASE64在线解码(https://tool.oschina.net/encrypt?type=3)经过一次密钥产生与一次密钥更新后,双方开始以对称密钥进行加密通信,首先是冰蝎向服务器发送加密数据,而解密函数在webshell中:
(三)解密过程
从请求密钥的数据包中获取密钥:29ab481053a0ebeb(1)输入密钥和请求密文,解密后为 base64 编码;base64解码(3)输入密钥和返回密文,解密后为base64编码;base64解码【1】冰蝎将AES加密数据发送至服务器webshell;【2】webshell检测到没有以GET方式提交的pass参数的值,因此调用openssl扩展,结合冰蝎发送的数据和session中的密钥进行AES解密,得到解密后的载荷assert|eval(base64_decode('QGVy......;【3】以|为分隔符,将解密后的载荷分隔为两部分,将执行载荷的过程放入自定义类C的魔术函数__construct()中;【4】实例化自定义类,触发__construct()函数,执行eval(base64_decode('QGVy......;【5】执行时,首先进行base64解码,然后执行解码后的代码,代码中定义了result数组,result数组有两个键值对:'status':base64_encode("success")'msg':base64_encode("57178bd5-7c2a-4c58-a6e8-56e2a2cf6223")【6】然后从session中取得密钥,对result数组加密,将加密结果输出到客户端;(4)冰蝎收到加密数据后,在内部进行解密(解密代码与解密的过程在冰蝎内部完成,我们看不到)但是我们可以自行解密,查看服务器发送至冰蝎的真实数据:三、冰蝎特征检测
总结冰蝎在流量交互中的特征,这些特征可分为两类。一类是可绕过特征,这类特征攻击者可通过构造报文进行绕过,致使设备检测不到冰蝎 webshell 特征。另一类是非可绕过特征,攻击者在某些情景无法更改 HTTP 某些字段,致使有固定报文字段可供设备检测。使用单个特征误报较高,但多个特征配合使用可降低误报,推荐多个特征搭配使用,进一步提升特征检测的准确性。(一) 可绕过特征
1. Accept字段
Accept是HTTP协议常用的字段,但冰蝎默认 Accept 字段的值却很特殊,这个特征存在于冰蝎的任何一个通讯阶段。如下:Accept: text/html,image/gif, image/jpeg, *; q=.2, */*; q=.22. UserAgent字段
冰蝎内置了十余种 UserAgent ,每次连接 shell 会随机选择一个进行使用。如果发现历史流量中同一个源IP访问某个URL时,命中了以下列表中多个 UserAgent ,可基本确认为冰蝎特征。3. 长连接
冰蝎通讯默认使用长连接,避免了频繁的握手造成的资源开销。默认情况下,请求头和响应头里会带有 Connection。(二) 非可绕过特征
1. 密钥传递时URL参数
密钥传递时,URI只有一个参数,key-value型参数,只有一个参数。Key是黑客给shell设置的密码,一般为10位以下字母和数字,很少有人设置特殊字符做一句话密码的(少数情况我们不考虑)。而Value一般是2至3位随机纯数字。另外webshell的扩展名一般为可执行脚本,如下:\.(php|jsp|asp|aspx)\?(\w){1,10}=\d{2,3} HTTP/1.1
2. 加密时的URL参数
\.(php|jsp|asp|jspx|asa) HTTP/1.1
3. 传递的密钥
加密所用密钥是长度为16的随机字符串,小写字母+数字组成。密钥传递阶段,密钥存在于Response Body中。正则如下:4.加密数据上行
在加密通讯时,php/jsp shell 会提交base64编码后的请求数据。用如下正则便可以很好的匹配。数字20是指定的字符出现至少20个才会匹配。正则如下:\r\n\r\n[a-zA-Z\d\+\/]{20,}
5. 密数据下行
该特征同样存在于加密通讯时,在返回包中的数据是加密后的二进制数据。这里使用正则的“非”匹配二进制非常见字符。正则如下:” [^\w\s><=\-‘”\:\;\,\!\(\)\{\}][\w]{2}[^\w\s><=\-‘”\.\:\;\,\!\(\)\{\}][a-zA-Z\d]{2}”
四、冰蝎源码分析
主要过程就是获取key和保存cookie之后,获取服务端信息,执行命令,文件操作,数据库操作等都是使用这个key和cookie进行操作,对执行的代码动态生成class字节数组,然后使用key进行aes加密,再进行base64编码,并用post方式发送数据。接收服务端返回的数据时,先使用key进行解密,解密之后的数据一般是使用了base64编码,解码之后就可以获取服务端返回的明文数据。反编译Behinder.jar包,其核心代码在net.rebeyond.behinder包内1.上传原理
冰蝎的原理为上传一个class字节码,通过调用classloader的defineClass方法,将class字节码,转换为Class。实例化上传的这个类,通过equal方法传递PageContext。获取到PageContext,间接获取到Request、Response、Seesion等对象。如HttpServletRequest request=(HttpServletRequest) pageContext.getRequest()2.核心代码分析
其核心部分是协商密钥getKeyAndCookie客户端打开和服务端的连接之后,会先调用BasicInfoUtils类,在BasicInfoUtils类的getBasicInfo方法里,会调用ShellService的构造方法新建ShellService类。而在ShellService类里面的构造方法,会调用Utils的getKeyAndCookie方法。判断得到的密匙rawKey_1之后,进入循环调用getRawKey方法,并获取rawKey_2,并且将rawKey_1和rawKey_2进行异或操作(如果rawKey_1和rawKey_2两个值不相同,则异或结果为1。如果rawKey_1和rawKey_2两个值相同,异或结果为0。)。获取rawKey_2的方法和获取rawKey_1基本是一样的。在获取了cookie和key之后,BasicInfoUtil的getBasicInfo就会调用ShellService的getBasicInfo方法来获取放了木马的服务器的基本信息由于是jsp,获取对应的字节内容先AES加密,再base64编码返回下就是直接说的利用POST发送payload了然后返回执行结果,分析完毕3.代码包分类
Crypt.java和Decrypt.java 涉及到server端语言的加密解密Params.java 调用不同语言的payload,返回其字节序列如果攻击者发送的请求不是文本格式的源代码,而是编译之后的字节码(比如java环境下直接向服务器端发送class二进制文件),字节码是一堆二进制数据流,不存在参数;攻击者把二进制字节码进行加密,防御者看到的就是一堆加了密的二进制数据流;攻击者多次执行同样的操作,采用不同的密钥加密,即使是同样的payload,防御者看到的请求数据也不一样,这样防御者便无法通过流量分析来提取规则。要让服务端有动态地将字节流解析成Class,但Java并没有提供直接解析class字节数组的接口。不过classloader内部实现了一个protected的defineClass方法,可以将byte[]直接转换为Class。也定义了一个类t继承classloader,调用时返回父类的defineClass方法,就解决了protected的限制,返回解析后的Class。当然这里用反射机制来实现也是可以的。这样就可以直接动态解析并执行编译好的class字节流了,但这里就必须提到java的asm框架。ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。需要执行的命令是编码在class文件中的,因为class是已编译好的文件。但不能每次执行命令时都编译payload,那么就需要payload可以接收参数。为了参数被waf拦截,自然也是二进制流,所以使用ASM框架来动态修改class文件中的属性值。从上面的代码就可以看出,只需要向getParamedClass方法传递payload类名、参数列表即可获得经过参数化的payload class。而且.net,asp的实现都是类似的,只是细节上有所不同,而.net的实现是使用编译好的dll文件。在Crypt类中分别有对应的不同server端语言的加解密方法。继续看各自的加解密方法,这里以C#的为例。
接着看php和asp的加密方法,根据类型不同加密,进行不同的加密。在客户端集成了不同语言shell的管理,所以就复用了部分代码,下面php执行异或操作的操作就是直接调用asp的代码实现的。冰蝎在通信过程中使用AES加密,Java和.Net默认支持AES加密,php环境中需要开启openssl扩展,v2.0更新以后,PHP环境加密方式根据服务器端支持情况动态选择,不再依赖openssl,所以在上面代码中不支持AES的情况就直接调用asp的代码。五、冰蝎特征总结
检测请求方式:Request.method= GET检测请求资源:Request.url= /[\w.]*.[a-zA-Z]{3,4}\?\w{0,20}=\d{0,10}检测服务端响应(仅16位密钥):Response.body.startwith =\w{16}在实际检测中,需要注意如:shell的名字、后缀(可能利用解析漏洞等)、密码的长度等等,实际在目前的版本中都存在获取密钥这个请求。冰蝎检测的难点在于在通信过程中数据通过加密传输,难以提取特征,下面我们比较一下两个版本之间在连接过程中发起的GET请求。冰蝎2默认Accept字段的值很特殊,而且每个阶段都一样。Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
冰蝎内置了十余种 UserAgent ,每次连接 shell 会随机选择一个进行使用。但都是比较老的,容易被检测到,但是可以在burp中修改ua头。Content-Length: 16, 16就是冰蝎2连接的特征。https://xz.aliyun.com/t/7300https://zhuanlan.zhihu.com/p/571463343本文作者:pony686 , 来源:FreeBuf.COM
文章来源: http://mp.weixin.qq.com/s?__biz=MzIwMzIyMjYzNA==&mid=2247508021&idx=2&sn=069ed6411f92ed6b3f7a44642fdeee08&chksm=96d05b30a1a7d226a3ccc94633ae34f2a733d4886b172690dd0cfda1451c2621884d75c0326e#rd
如有侵权请联系:admin#unsafe.sh