一直认为日志分析的最终奥义是取证与预测——讲述完整的已发生、正在发生的、将来会发生的攻击故事(何时.何地.何人.何事.何故)。 SUPort=43958&SUUser=LocalAdministrator&SUPass=xxx&SUCommand=net user spider spider %2Fadd %26 net localgroup administrators spider %2Fadd&user=spider&password=spider&part=C%3A%5C%5C whirlwind=%40eval%01%28base64_decode%28%24_POST%5Bz0%5D%29%29%3B&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoJEQ9PSIiKSREPWRpcm5hbWUoJF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdKTskUj0ieyREfVx0IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWiIpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJcdCI7JHU9KGZ1bmN0aW9uX2V4aXN0cygncG9zaXhfZ2V0ZWdpZCcpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6Jyc7JHVzcj0oJHUpPyR1WyduYW1lJ106QGdldF9jdXJyZW50X3VzZXIoKTskUi49cGhwX3VuYW1lKCk7JFIuPSIoeyR1c3J9KSI7cHJpbnQgJFI7O2VjaG8oInw8LSIpO2RpZSgpOw%3D%3
n3b31d1=cGhwaW5mbygpOw== getpwd=admin&go=edit&godir=%2Fhtdocs%2Fbbs%2Fconfig%2F&govar=config_global.php senv=eval(\'Ex\'%26cHr(101)%26\'cute(\'\'Server.ScriptTimeout%3D3600:On Error Resume Next:Function bd%28byVal s%29%3AFor i%3D1 To Len%28s%29 Step 2%3Ac%3DMid%28s%2Ci%2C2%29%3AIf IsNumeric%28Mid%28s%2Ci%2C1%29%29 Then%3AExecute%28%22%22%22%22bd%3Dbd%26chr%28%26H%22%22%22%22%26c%26%22%22%22%22%29%22%22%22%22%29%3AElse%3AExecute%28%22%22%22%22bd%3Dbd%26chr%28%26H%22%22%22%22%26c%26Mid%28s%2Ci%2B2%2C2%29%26%22%22%22%22%29%22%22%22%22%29%3Ai%3Di%2B2%3AEnd If%22%22%26chr%2810%29%26%22%22Next%3AEnd Function:Response.Write(\'\'\'\'->|\'\'\'\'):Ex\'%26cHr(101)%26\'cute(\'\'\'\'On Error Resume Next:\'\'\'\'%26bd(\'\'\'\'526573706F6E73652E5772697465282268616F72656E2229\'\'\'\')):Response.Write(\'\'\'\'|<-\'\'\'\'):Response.End\'\')\')'
但在日志分析中只能当成辅助特征,有两个原因: a. 日志字段不全的问题,无法使用payload b. 攻击者很多时候只是在做webshell存活性探测,不会产生攻击特征,或者将会攻击payload进行加密处理来绕过特征检测 如下例wso 2.5.1 的payload为a=RC ![]() 但也不要轻视了这种直观的特征,常规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登陆口 align=center> method=post>Password: type=password name=pass> type=submit value='>>'> 登陆框非常非常见(登陆框集锦) ![]() 实例2 上传文件型webshell <form action='?cmd=up' method='post' enctype='multipart/form-data' name='form1'>
<input type='file' name='file' size='17' class='Input'>
<input type='submit' name='Submit' value='提交' class='Input'>
</form>
实例3 不需要认证的野马 ![]() 实例4 wso webshell a:4:{s:5:'uname';s:81:'Linux li676-178 3.19.1-x86_64-linode53 #1 SMP Tue Mar 10 15:30:28 EDT 2015 x86_64';s:11:'php_version';s:5:'5.6.9';s:11:'wso_version';s:5:'2.5.1';s:8:'safemode';b:0;} (2)响应页面为空 对URL发起GET请求后,响应为空白页面,带payload回放(脱敏处理后的) 检测方案如下图所示,用到了两个特征 (5)webshell 行为特征 抽象webshell形成攻击的关键路径,将其抽象为数学描述的策略库,来提取异常 (6)webshell 网页特征:内容/结构/视觉签名 (更多内容可从网页相似性开始了解) ![]() 本人的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回放(限速),若有参数,带参数回放 (p.s.有些小狡猾的webshell不带参数回放会显示页面不存在) 第二步:去除响应码非200的path 补充:修改为保留401的请求,避免漏掉通过http basic认证的webshell 第三步:去除404重写path 方法一:随机生成2个文件名,回放,看response body的大小是否一样,若一样,则存在重写 方法二:神奇的fuzz hashing又要发挥作用了,可以对重写的response content求fuzz hashing值,设置相似度阈值,在阈值范围内的判定为404,例下图所示,将安全狗重写页面剔出 ![]()
![]() 第四步:对空白响应页面,进行带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(因为静态文件的放行) 问题三:已有文件植入后门(因为不孤立了) 四、其他检测方法 上文介绍了如何通过web日志分析来查找webshell,现在来回顾一下传统的webshell检测产品 (p.s.从商品化的检测技术中总能获得不少检测灵感,他们的方法虽然土但有效) WAF/IDS/IPS:检测HTTP请求是否符合webshell通信特征(被动检测) 漏洞扫描器:扫描是否存在已知后门植入漏洞,例如常见webshell路径,菜刀连接(主动检测) 后门检测查杀工具:检查文件系统中是否存在webshell恶意文件 目录监控工具:文件完整性监控、关注文件的修改时间、所有者,权限(增加的webshell文件,被植入webshell的已存在文件时间都会发生变化) SIEM日志分析(取证)工具:检查是否有webshell的访问事件 (现有的一般是基于特征与简单关联,非常少的用到机器学习方法) 而这些产品用到的技术划分为静态检测方法与动态检测方法,其实也是反病毒领域采用的方法。 1. 静态检测 (1) 文件内容检测,检测是否包含webshell特征,例如webshell常用函数 缺点: webshell 花式混淆绕过 ![]() 花式混淆参见: http://www.bitsCN.com/Article/201509/443305.html 检测方法参见: PHP Shell Detector (2)文件内容检测,检测是否加密(混淆处理) 吸取上面的经验,增加了通过检测是否加密来判断webshell(1,2,3,4都是) 1、重合指数(Index of Coincidence):本质是概率,简单的说,有意义的词汇重合指数高,被加密或混淆的字符串的重合指数低 2、信息熵(Entropy):本质还是概率,简单的说,有意义的词汇熵值小,被加密或混淆的字符串的熵值大 3、最长单词(LongestWord):比较粗暴的假设,字符串越长被加密或混淆的可能性越大 4、压缩(Compression):非常有趣的想法,尽然能想到利用压缩的原理来描述混淆或加密字符串与常规字符串的区别 5、签名(Signature):特征匹配,属于传统方法 检测方法参见: NeoPi方法 缺点: 第一篇文章下的吐槽能说明一些问题,第二篇文章正好证明了这个问题 数据分析方法特别是机器学习,更多的时候考虑的是大数据量下的概率指向,对特殊情况的覆盖率低,但优势也是很明显的,只是不能单独使用。 (3)文件Hash检测,创建webshell样本hashing库,将待检测文件与之对比,在阈值范围内的判定为可疑文件 ssdeep检测webshell (fuzzy hashing检测) (4)文件完整性检测 文件的创建时间(新增文件(新增webshell),修改时间(原有文件注入webshell)),文件权限,所有者 缺点:更新频繁的站点无法运维 2. 动态检测 沙箱技术,根据动态语言沙箱运行时的行为特征来判断 缺点: 加密文件无法执行,写的很挫(本身有语法错误)的文件无法执行 检测产品参加: 百度的webshell检测服务 webdir 五、结语 这篇文章写了快半个月了,本人是个收集狂魔,喜欢收集资料,也喜欢收集方法,收集了需要验证,因此花了不少时间,但这个过程还是蛮有趣的,玩过界(汇集不同领域的特长)的感觉真好。同时欢迎交流,把我骂成狗也没得关系 后记: 结果真的被人骂了,但骂的原因不是预料的文章写的渣,技术方案存在问题,而是涉及抄袭的人身攻击,本人除了写技术博客,写读书笔记,推送我发现的好资料,并未混进安全圈内过,会议不曾参加,聚会更是没有,着实封闭,也不能自证,于是只能忍了。 |
|