webshell检测-日志分析

一直认为日志分析的最终奥义是取证与预测——讲述完整的已发生、正在发生的、将来会发生的攻击故事(何时.何地.何人.何事.何故)。
而本文之所以讲如何识别webshell,就是想从确定的攻击事件来回溯已发生的攻击事件,被植入的webshell毫无疑问就属于确定的攻击事件,只要曾经被传入过,就有很高的概率一直被黑
 
webshell检测不是新鲜事,主流有杀毒软件与入侵检测系统两种做法,而这两种方法除了技术上的缺陷外(后文会讲),更多时候,由于无法拿到完整的文件样本(webshell查杀工具部署成本比较高,有系统兼容问题,有性能问题),或无法拿到完整的流量信息(流量镜像的部署成本也非常高),而采用成本较低的日志分析方法。
本文重点讲webshell检测的日志分析方法,包括模型是如何建立与实现的,最后会简单的提一下传统的检测方法与之对比。

一、分析

总的思路:先找到异常日志,再找到攻击日志,整个过程分为两个步骤:webshell提取 + webshell确认
(p.s就像我在

web日志异常检测实践之长度异常模型 与理工渣眼中的HMM及安全应用

介绍的,先发现未知,然后从未知中确认已知)

1、webshell提取

根据安全经验,我们可以给出以下假设

(1)webshell 的访问特征(主要特征)

1)少量的IP对其发起访问
2)总的访问次数
3)该页面属于孤立页面
注意红色标记的词汇都是抽象的形容词,我们需要将这些特征量化,比如说少量,多少算少量?什么是孤立页面?
接下来常见的描述性统计方法上场,我们来统计
1)单个URL每天的总访问分布
2)单个URL的独立访问IP数目分布
3)单个URL的入度、出度分布 (我们可以将网站的访问路径当成一个有向图)
下面,小小科普一下有向图的基本概念
1
节点vertices(node):1,2,3,4,5,6,7,8 相当于访问日志中的url
边edge:1->2 1->3 4->1 5->1 6->5 7->7 相当于从A url跳转到B url
入度in-degree 
出度out-degree
节点1的入度为2, 出度为2
节点2、节点3的入度为1,出度为0
节点4、节点6的入度为0,出度为1 ,属于悬挂节点(pendant vertex),比较特殊,例如404跳转到首页会产生这样的节点
节点5的入度为1,出度为1
节点7的入度为1,出度为1,但自己指向自己,属于自回路,大多数有验证的webshell都属于这种
节点8的入度为0,出度为0,属于孤立节点(isolated vertex)
 
而节点7、8就属于webshell访问特征中的(3)该页面属于孤立页面
(p.s. 使用基于图的异常检测方法Graph-based Anomaly Detection, 在安全检测方法中占据非常非常非常非常重要的位置,例如检测受蠕虫感染的机器等)
补充20151103:对于出度入度>1的webshell也是存在的,什么是孤立,与其他页面的交互度为多少算孤立,都是相对的。
当webshell采用<a href>标签列出当前目录下的文件的时候,就会产生与其他页面的交互。当需要多个脚本协同作用的webshell也会产生交互。
当然不是所有的孤立页面都是webshell,以下情况也会造成孤立页面
(1)隐藏管理后台等正常孤立页面(多半是过期遗忘的,或者没有做访问控制权限的)的访问
(补充20151103:有人质疑过,后台为啥会孤立,登进去后不就跳转到其他页面了吗?如果只是打开页面,不做登陆操作呢?)
(2)扫描器行为,常见漏洞扫描,PoC扫描,Webshell扫描(日志中经常可以看到常见webshell路径加一句话payload的扫描)——这是最主要的干扰数据,需要剔除
对于情况(1)采用白名单的方式,对于情况(2)扫描器识别
(p.s. 爬虫技术、指纹识别技术、扫描器识别(广义的可衍生到人机识别)可以称为web安全技术的三驾马车,总也绕不过去)
补充20151103:模型运行了1个多月后,发现孤立页面的情况真是五花八门,一些站点放了个“安全”检测工具,“上传压缩密码重置”便捷工具都不带删的。
(2)webshell 的path特征(辅助特征)
除了weshell特有的访问特征,我们也可以用path特征来辅助提取
我们来看一批真实的webshell
2
会发现不同手段植入的webshell路径各有特征,例如上传的webshell,如果上传组件有保护措施的(

文件上传漏洞防御——图片写马的剔除

)会进行文件名重写(示例中的32位的十六进制的名字),并在路径中还有日期特征,这类webshell还极易出现在静态资源目录(图片,样式、配置、)下。
补充20151103:批量写马的时候,特别是利用漏洞进行的批量写马,会用脚本来自动生成文件名,然后放在特定的目录下,对path的相似性分析会发现这个规律。
(文本相似性也是数据分析的基本技能)

(3)webshell的时间特征(辅助特征)

将新增的页面视为异常页面,但这种方案的缺陷非常明显
(1)会漏掉已存在页面写马的情况
(2)会误判正常的站点更新
于是将该特征当做辅助特征,用来还原webshell植入的过程,如果接入了例如WAF这种防御产品,还可以探究是不是绕过了防御
补充20151103: 文件的时间属性也是可以修改的

(4)webshell Payload特征(辅助特征)

WAF、IDS等基于流量的安全检测防御工具,会把网络通信中的payload特征(特别是攻击特征)当成主要的检测手段
3

图片参考 《closing the door on webshell》-by Anuj Soni

下面列举一些实际发现的payload(做脱敏处理后的)




但在日志分析中只能当成辅助特征,有两个原因:
a. 日志字段不全的问题,无法使用payload
b. 攻击者很多时候只是在做webshell存活性探测,不会产生攻击特征,或者将会攻击payload进行加密处理来绕过特征检测
如下例wso 2.5.1 的payload为a=RC
4
但也不要轻视了这种直观的特征,常规webshell是占较大比例的,并且在webshell特别是只有回显信息无GUI的小马而言,确认上也能起到不容忽视的作用。

2、webshell确认

想想砖家们们如何确认一个页面是不是webshell的,打开ta,看看页面长啥样,也就是请求回放。在进行请求回放的时候,有两类问题需要考虑
(1)回放是否会造成破坏性操作,例如造成站点压力,(好心办坏事的例子也是有的,例如网站速度监测应用,cc防御应用就会把带宽小性能小的站点打趴),还有删除文件、重置账户、系统重装(e.g. /setup-config.php)等操作,这也是为啥不直接回放每条访问日志的原因之一(当然整体日志量的大小也是原因之一)
(2)回放是否侵犯用户隐私,严格的日志存储规定不能存储cookie,post等会涉及用户敏感数据的字段,或必须做脱敏处理再存储,然后由用户授权再查看,当然不存储的更重要的原因是存储资源的巨大耗费。
(p.s.有时候我会想如何防止安全人员监守自盗呢,做扫描器(漏洞识别)的,特别是全网性质的,有自己的社工库,有自己的弱点地图等,扯远了)
对于情况(1)采用限速,加上回放内容过滤,cookie认证信息消除,威胁操作过滤,对于情况(2)有点微妙
回放的问题解决了,接下来就是根据回放的响应页面判断是否是webshell了。我们先看看响应页面的类型
(1)响应页面不为空(对URL发起GET请求后,为一个有内容的页面)
实例1 webshell登陆口

<pre align=center><form method=post>Password: <input type=password name=pass><input type=submit value=‘>>’></form></pre>

登陆框非常非常见(登陆框集锦
webshell检测-数据分析 - 碳基体 - 碳基体
实例2 上传文件型webshell

实例3 不需要认证的野马

401
实例4 wso webshell
(2)响应页面为空
对URL发起GET请求后,响应为空白页面,带payload回放(脱敏处理后的)
检测方案如下图所示,用到了两个特征

(5)webshell 行为特征 

抽象webshell形成攻击的关键路径,将其抽象为数学描述的策略库,来提取异常

(6)webshell 网页特征:内容/结构/视觉签名 

(更多内容可从网页相似性开始了解)

 402

本人的webshell样本库: https://github.com/tanjiti/webshellSample
回顾一下,我们是根据特征来检测webshell,已提到的特征有
(1)webshell 访问特征(主要特征) ——webshell提取阶段
(2)webshell path特征(辅助特征)——webshell提取阶段
(3)webshell 时间特征(辅助特征)——webshell提取阶段
(4)webshell Payload特征(辅助特征)——webshell提取阶段
(5) webshell 行为特征 ——webshell提取阶段
(6)webshell Reponse网页特征(内容特征/结构特征/视觉特征) ——webshell确认

最后还有一个特征——(7)webshell 攻击关联特征

  “如果发现一个站点植入webshell,那远远不只一个站点被植入”
“如果发现一个站点被植入一个webshell,那远远不只一个webshell被植入”
搜索的优势在这个时候就可以发挥了,用确认webshell的访问者特征(IP/UA/Cookie),Payload特征,时间特征进行关联搜索,像这次xcode事件,360在构建了基础数据后(这里引用我非常崇拜的楚安一段话“永远记得,数据基础设施不是采一堆垃圾进来存下就完了,这背后是完善的数据生命周期解决方案。采集,etl,数据质量,快捷的数据交互这些才是最重要的。)利用搜索将数据关联起来,按时间线进行还原,讲述了个有意思的故事。
补充20151103:讲到搜索,有两个难点:
(1)如何将结果按时间线与行为关联展示
(2)基础数据设施建设的如何,比如说使用elasticsearch,保留多久的数据量,索引如何建立,集群的负载均衡等
(说到基础数据设施建设,超级心塞,先是hadoop碎片化导致的数据传输坑,然后再是日志字段飘逸变更的坑,还有不可解释靠重启解决了的集群莫名挂掉的坑,所幸身边有不少朋友提供帮助,特别感谢hadoop小王子

二、实现

1. 数据获取

数据源:web访问日志
获取方式:如果存储在hdfs里,采用distcp的方式拷贝到模型计算集群上
p.s. 光数据的获取,就遇到了很多坑,不同版本的hadoop之间的数据传输(hadoop碎片化的问题,也是工程师文化导向的产物之一,都爱用开源的东西去组装一套单独的完整的系统,当然也因此培养出了不少全栈工程师)

2.feature提取

http_host
root_domain
url
path
query 查询字符串
referer
ip
timestamp
http_response_code
http_method
request_body 请求体 非必要字段
cookie 非必要字段
user_agent

3.预处理

在统计之前我们需要对数据做预处理
预处理1:按小时切割日志(切割主要是为了避免日志量大的情况下计算时间过长)
预处理2: 提取响应码为2xx,3xx的日志
预处理3: 特征规范化处理,非常重要,如果不做预处理,将会形成一个超级大的有向图,mapreduce这种批处理会处理不过来
Host规范化: 将*.xxx.com或.xxx.com 变成 www.xxx.com
Path规范化:归并多个/,替换\为/
referer规范化
(1)将相对地址还原为绝对地址,e.g. /a.php => www.xxx.com/a.php
(2)将host部分非本域(不在根域名内)、空字段、不符合referer规范的referer字段皆设置为空
(3)去除query部分

4.模型建立

1)webshell提取(全自动)
第一步:建立(path,referer)有向图,提取孤立页面(入度为0,出度为0 )与自回路页面( 入度为1,出度为1,自己指向自己)webshell 的访问特征
第二步:去除不符合规范的path( 是否符合(?:https?://)?[-./\\w]+)
第三步:去除静态path(例如jpeg,jpg,gif,png,bmp,css,js,xls,xlsx,doc,xml,wav,tar.gz,zip,swf,mp3,ico,pidf,torrent)
第四步:去除白名单path (例如主页index.php,index.asp,index.aspx,index.ashx,index.html)
第五步:去除非webshell后缀的path (例如asp,aspx,php,jsp,py,cgi,pl,java,sh,war,cfm,phtml)
第六步:去除扫描器造成的path(按扫描器IP信誉库(云扫描器IP信誉库与时效性扫描器IP信誉库)与扫描器行为(可以简单的按ip+host聚类,将单位时间内请求数超过M,独立路径数超过N的请求视为扫描器)来去除)
第七步:去除响应码非200的path
第八步:按path特征定义webshell的可信度,符合特征的标记为1(例如常见的上传文件目录,随机文件名)webshell 的path特征
第九步:按webshell payload特征定义webshell的可信度,符合特征的标记为1,等同于WAF中的webshell检测规则(但要更宽松些,因为不怕误报),如果日志中有WAF检测结果标记字段,可以直接用该字段来标记webshell可信度 (例如envlpass=) webshell Payload特征
第十步:去除独立IP访问数与path访问请求总数超过阈值的path
2)webshell确认
第一步:对webshell 提取的path进行GET回放(限速),若有参数,带参数回放
这里需要考虑两种badcase:
(1)对脚本语言,设置不带参数隐藏为不存在或者发生跳转的webshell
(2)对非脚本语言,不带参数回放,由于Null异常直接500异常
第二步:去除响应码非200的path
补充:修改为保留401的请求,避免漏掉通过http basic认证的webshell
第三步:去除404重写path
方法一:随机生成2个文件名,回放,看response body的大小是否一样,若一样,则存在重写
方法二:神奇的fuzz hashing又要发挥作用了,可以对重写的response content求fuzz hashing值,设置相似度阈值,在阈值范围内的判定为404,例下图所示,将安全狗重写页面剔出
403
5
第四步:对空白响应页面,进行带payload的回放(限速与脱敏)
第五步:对响应页面计算fuzz hashing值,并做聚类处理
第六步:读取weshell fuzz hashing特征值库,将相似度在阈值范围内的path判定为webshell webshell Reponse网页相似性特征
第五步:网页信息提取,分为静态提取,动态提取,提取title,表单,Link,Image信息(全自动)
第六步:抽象webshell行为的关键路径,制定策略,基于策略库进行webshell异常提取
第七步:基于webshell样本签名(网页的内容/结构、视觉)的自动化攻击确认,与人工干涉的对属于异常但不符合样本签名的攻击确认补漏
第八步:提取确认webshell的访问者特征(IP/UA/Cookie),Payload特征,时间特征,关联搜索,将搜索结果按时间排序,还原事件 webshell 攻击关联特征

5. 模型评估

一般会用召回率,准确率来评估。但如何确认所有的webshell已检出呢,我采用在自己站点植入webshell,然后看是否能全部检出,但这种方式有明显问题——站点的访问流量非常态的,待解决。

三、模型缺陷

模型待改善的地方
问题一:referer伪造
问题二:图片webshell(因为静态文件的放行)
问题三:已有文件植入后门(因为不孤立了)
问题四:URL回放时的响应问题(例如读取注册表的小马,响应时间会超过默认的120s)
问题五: URL重写导致的伪静态放行
问题六:多个脚本相互交互的webshell(破坏了孤立性 )
问题七:网页信息动态提取时JS解析错误(无法正确提取表单来确认webshell输入点)

四、其他检测方法

上文介绍了如何通过web日志分析来查找webshell,现在来回顾一下传统的webshell检测产品
(p.s.从商品化的检测技术中总能获得不少检测灵感,他们的方法虽然土但有效)
 
WAF/IDS/IPS:检测HTTP请求是否符合webshell通信特征(被动检测)
漏洞扫描器:扫描是否存在已知后门植入漏洞,例如常见webshell路径,菜刀连接(主动检测)
后门检测查杀工具:检查文件系统中是否存在webshell恶意文件
目录监控工具:文件完整性监控、关注文件的修改时间、所有者,权限(增加的webshell文件,被植入webshell的已存在文件时间都会发生变化)
SIEM日志分析(取证)工具:检查是否有webshell的访问事件 (现有的一般是基于特征与简单关联,非常少的用到机器学习方法)
而这些产品用到的技术划分为静态检测方法与动态检测方法,其实也是反病毒领域采用的方法。

1. 静态检测 

(1) 文件内容检测,检测是否包含webshell特征,例如webshell常用函数
缺点: webshell 花式混淆绕过
6

花式混淆参见:

http://weibo.com/p/1001603888457062702792
http://pastebin.com/raw.php?i=ctswucid
检测方法参见:
(2)文件内容检测,检测是否加密(混淆处理)
吸取上面的经验,增加了通过检测是否加密来判断webshell(1,2,3,4都是)
1、重合指数(Index of Coincidence):本质是概率,简单的说,有意义的词汇重合指数高,被加密或混淆的字符串的重合指数低
2、信息熵(Entropy):本质还是概率,简单的说,有意义的词汇熵值小,被加密或混淆的字符串的熵值大
3、最长单词(LongestWord):比较粗暴的假设,字符串越长被加密或混淆的可能性越大
4、压缩(Compression):非常有趣的想法,尽然能想到利用压缩的原理来描述混淆或加密字符串与常规字符串的区别
5、签名(Signature):特征匹配,属于传统方法
检测方法参见:
NeoPi方法的国人介绍:
http://www.freebuf.com/articles/web/23358.html
http://www.freebuf.com/articles/4240.html
缺点:
第一篇文章下的吐槽能说明一些问题,第二篇文章正好证明了这个问题
数据分析方法特别是机器学习,更多的时候考虑的是大数据量下的概率指向,对特殊情况的覆盖率低,但优势也是很明显的,只是不能单独使用。
(3)文件Hash检测,创建webshell样本hashing库,将待检测文件与之对比,在阈值范围内的判定为可疑文件
ssdeep检测webshell (fuzzy hashing检测)
 
(4)文件完整性检测
文件的创建时间(新增文件(新增webshell),修改时间(原有文件注入webshell)),文件权限,所有者
缺点:更新频繁的站点无法运维

2. 动态检测

沙箱技术,根据动态语言沙箱运行时的行为特征来判断
缺点:
加密文件无法执行,写的很挫(本身有语法错误)的文件无法执行,
检测产品参加:

五、结语

这篇文章写了快半个月了,本人是个收集狂魔,喜欢收集资料,也喜欢收集方法,收集了需要验证,因此花了不少时间,但这个过程还是蛮有趣的,玩过界(汇集不同领域的特长)的感觉真好。同时欢迎交流,把我骂成狗也没得关系
[via@碳基体]