> ## 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.

# 讓 AI 打一間不存在的銀行：最難的不是找漏洞
- URL: https://taiwanding.com/rang-ai-da-yi-jian-bu-cun-zai-de-yin-xing-zui-nan-de-bu-shi-zhao-lou-dong/
- Published: 2026-11-10T08:31:06.000Z
- Updated: 2026-11-10T08:32:33.000Z
- Author: Kevin Chen
- Tags: AI, #vulnmachines, octorig

八面旗標到手時，照理說這篇文章應該結束了，

但我反而開始不放心，

AI 說它拿到了管理員 Cookie，可是前面的 HTTP 回應明明顯示 Session Cookie 有 `HttpOnly`，這兩件事真的能同時成立嗎？

那一刻我發現，這次實驗真正想研究的，不是 HumanBank 有多少洞，而是：

**當 AI 說「我找到漏洞了」，我們該怎麼判斷它說的是事實、推論，還是把兩者混在一起了？**

> 聲明：本文記錄的是在自行部署、授權使用的 OctoRig HumanBank 教學靶場中進行的研究，所有發現僅限該實驗環境，不代表任何真實金融機構有相同問題，為了保留大家自己練習的空間，本文不提供完整攻擊 Payload 與 CTF 旗標。

## 前言

[OctoRig](https://github.com/CommonHuman-Lab/OctoRig?ref=taiwanding.com) 是一個開源資安靶場，裡面有一套模擬網路銀行的系統，叫 HumanBank。

功能很完整：登入、註冊、帳戶管理、轉帳、交易驗證碼（TAN）、管理介面、API。

原本只是想跟 AI 一起打一台靶機，但打之前我冒出一個疑問：

如果 AI 已經能自己用工具、分析程式、發 HTTP 請求、完成漏洞利用，那我還要做什麼？

難道只剩下打「繼續」、「再找找看」、「深挖一點」？

所以這次我不只打銀行，也觀察 AI 怎麼研究一個陌生系統。

## Step 1：環境，localhost 不等於 localhost

還沒開始打就先卡關。

1. **Docker 網段衝突**：HumanBank 的網段跟我機器上既有的容器網路撞到，起不來。調整網路配置後，網站回 HTTP 200。
2. **AI Agent 連不上**：我這邊瀏覽器開得好好的，另一個 AI Agent 卻回報連線失敗。
3. **原因**：它跑工具的沙箱有自己的 `127.0.0.1`。

我盯著那個連線失敗看了一陣子才想通。

我跟它講的是同一個位址，指的卻是兩台不同的機器。對 AI 來說，localhost 不一定是我電腦上的 localhost。

換到正確的執行環境後，就連上了。

這只是環境問題，不算研究成果。但如果當下 AI 直接回報「目標無回應，無法測試」，而我也照單全收，這個靶場就會被記成「打不進去」。

重點：**測試失敗，不等於安全控制成功。**

網路不通、環境不同、權限不足、資料不存在、工具本身壞了，都會讓測試失敗。沒搞清楚原因就寫「無法利用」，那是誤判。

## Step 2：拿旗，AI 的效率

環境正常後，AI 的速度就出來了。

1. **登入頁 SQL Injection**：可以取得管理員工作階段。
2. **功能層級授權缺失**：一般使用者可以存取管理 API。
3. **物件層級授權缺失**：帳戶與工單沒有驗證所有權。
4. **更多 SQL Injection 入口**：搜尋與交易篩選各有一個。
5. **其他**：儲存型 XSS、憑證重用線索、幾個設計問題。

很快它就回報：八面旗標到手。

如果只是解題，這樣就夠了。

但拿到旗標，不代表它真的理解自己打穿了什麼。

## Step 3：追證據，XSS 與 HttpOnly 的矛盾

回到開頭那個不對勁的地方。

AI 的報告寫著「竊取管理員 Cookie」，語氣很肯定，格式也漂亮。

如果我沒有剛好記得前面那個回應標頭，大概就直接收下了。

但 Session Cookie 設了 `HttpOnly`，JavaScript 照理說用 `document.cookie` 讀不到它。

報告說偷到了，標頭說偷不到。一定有一邊寫錯。

我要求 AI 重新審查證據，結果是：

1. **還有另一個 Cookie**：系統除了 Session Cookie，另有一個沒設 `HttpOnly` 的 `hb_admin_token`。
2. **XSS 確實能執行**：JavaScript 可以在管理員瀏覽器裡跑。
3. **`hb_admin_token` 可被 JavaScript 讀取**：但這次沒有實際讀取或外送。
4. **它能不能用於授權、是否等同 Session**：未驗證。

所以正確的寫法不是「竊取管理員 Cookie」，而是「XSS 可在管理員瀏覽器執行，且存在一個 JavaScript 讀得到的 Token，其授權效力未驗證」。

句子變長了，也沒那麼帥，但這才是我們手上證據撐得起來的說法。

重點：**「JavaScript 能執行」、「某個 Token 讀得到」、「已完成帳戶接管」是三件不同的事。**

AI 不被追問，很容易把它們寫成同一件事。

## Step 4：交易與 TAN，負一美分

後面有一個發現我特別喜歡。

HumanBank 的轉帳功能接受負數金額。

1. **測試方式**：用兩個自己建立的帳戶，金額只填 `-$0.01`。
2. **結果**：伺服器收下了，帳務方向直接反轉。
3. **收尾**：驗證完成後，用反向交易把餘額調回來。

看到餘額往反方向跳了一美分的時候，我是真的笑出來。

沒有引號、沒有編碼、沒有任何看起來像攻擊的東西。就一個減號。

人會覺得「轉帳金額當然不能是負的」，但對程式來說，`-0.01` 就是一個合法的數值，系統沒有明確規定金額必須大於零，它就照原本的加減運算跑下去，「我轉給你」就變成「你轉給我」。

把幾個漏洞放在一起看：

1. **SQL Injection**：使用者輸入改變了資料庫查詢的語意。
2. **IDOR**：使用者指定的資源 ID 越過了所有權檢查。
3. **負數轉帳**：使用者提供的數值改變了資金流向。

技術根因不一樣，問題是同一個。

重點：**系統沒有在正確的位置，區分「使用者可以提供的資料」與「只有伺服器才有權決定的事」。**

安全不是把所有輸入都當成危險，而是搞清楚哪些輸入不該有決策權。

同一條交易流程上還有 TAN，也就是交易驗證碼，這邊的結果剛好相反，是沒打穿的：

1. **有綁定使用者與指定位置**：這個控制正常。
2. **用過就消耗**：這個也正常。
3. **金額與收款方**：在可觀察到的 TAN 驗證階段，系統沒有比對這兩項。

第 3 點算不算漏洞？要看 TAN 承諾的是什麼。

- 如果它只是一次性身分驗證碼，目的就只是證明「你持有正確的驗證資訊」。
- 如果銀行宣稱它是用來授權某一筆交易，授權內容就應該包含金額與收款方。

兩種設計的安全保證完全不同，而且我們沒有證實 TAN 能重放完成交易，也沒有確認任何未授權扣款。

所以報告把它列為「需要釐清安全語意的設計問題」，沒有寫成高風險漏洞。

知道哪些控制有效、它們原本承諾保護什麼，跟知道哪些攻擊成功一樣重要。

## Step 5：人怎麼監督 AI

研究做到後面，我發現 AI 最大的問題不是找不到漏洞，而是很容易在兩個極端之間跳。

1. **太早放棄**：丟幾個 Payload 沒結果，就說目前沒找到漏洞。
2. **無限延伸**：找到一個問題後，開始找更多漏洞、更多旗標、更多端點，甚至直接去翻原始碼裡的答案。

它一直在做事，但工作量變多，不代表我們對系統的理解也跟著變多。

有一次，它想用已經發現的路徑穿越去讀容器內的 SSH 私鑰，被執行環境的安全機制擋下來。

後來改讀非敏感的 `/etc/passwd`，成功確認任意檔案讀取。

到這裡證據就夠了，沒必要為了讓報告看起來更厲害，再去拿私鑰。

重點：**AI 最需要的不是無限執行能力，而是知道何時該驗證、何時該轉向、何時該停止。**

以前 AI 說沒找到，我就回「繼續深挖」，現在我改問這四個問題：

1. **AI 說沒找到漏洞時：「你沒找到，是因為已經驗證安全控制有效，還是因為你還沒想到其他假設？」**
2. **AI 說找到漏洞時：「你觀察到的到底是什麼？哪些是事實，哪些只是推論？」**
3. **AI 想繼續測試時：「下一個實驗能讓我們多知道什麼？」**
4. **AI 說研究完成時：「你停下來，是因為重要假設已經充分驗證，還是因為剩下的實驗風險與成本不合理？」**

這些問題不需要我比 AI 更熟每一個框架、每一種 Payload，但它們會逼研究過程變得可解釋、可驗證、可以被質疑。

分工大概是這樣：

1. **AI**：提出假設、操作工具、執行實驗、整理觀察結果。
2. **人**：決定研究問題、檢查證據、挑戰推論、判斷研究的價值與風險。

這不代表人可以不懂技術，Step 3 那個矛盾，就是因為知道 `HttpOnly` 在做什麼才抓得到。

## Step 6：成果與限制

HumanBank 最後整理出十多個根因或安全設計問題：

- SQL Injection
- 功能與物件授權缺失
- 接受未簽章 JWT
- 重設密碼憑證洩漏
- 儲存型 XSS
- 路徑穿越
- 轉帳金額與限額驗證問題

報告沒有把每一項都寫成嚴重漏洞，限制照實保留：

1. **`alg:none` JWT**：確實被接受，但只驗證了使用自己身分 Claim 的情況，沒有證明能冒用管理員。
2. **登出後 Session 仍有效**：先前複製的 Cookie 還能用，但攻擊者得先拿到 Cookie，不能當成獨立的帳戶接管入口。
3. **憑證重用**：某個使用者能登入 HumanBank，不等於推測中的跨系統攻擊鏈已經完整成立。

另外有兩條線我們選擇不跨：

1. **不對非自有帳戶執行會改變狀態的操作**：研究過程讀取過其他帳戶與工單，但沒有動它們的資料或餘額。
2. **不做併發壓力測試**：避免產生實際的帳務副作用。

還有一個小細節。兩個測試帳戶的餘額恢復了，但交易歷史、測試工單、重設紀錄都還在，所以紀錄上寫的是「餘額已恢復」，不是「環境完全還原」。

這些對 CTF 分數沒幫助，卻是嚴謹研究不能少的部分。

旗標只存在這台靶機，今天學會的 Payload，明天換個框架、資料庫或驗證方式就可能失效，能帶走的是這幾個問題：

1. 這個操作的身分是誰決定的？
2. 伺服器是不是只驗證「已登入」，卻沒驗證資源所有權？
3. 這個驗證碼證明的是身分，還是授權了具體交易？
4. 輸入是零、負數、空值或超出範圍時，業務規則還成立嗎？
5. 我看到的成功，是 HTTP 回應成功，還是後端狀態真的被改變？

銀行、電商、企業管理系統都用得上，OAuth、AI Agent、MCP 這些新架構也一樣。

## 結語

AI 讓「執行」變得便宜，但不會讓判斷自動變正確。

以後不缺能發幾千個 HTTP 請求的 Agent，也不缺能快速產出報告的模型。

真正稀缺的能力，仍然是把一個漂亮的結果拆開來問：它證明了什麼？沒有證明什麼？下一個實驗值不值得做？

當 AI 能回答清楚「憑什麼」與「為什麼停」，旗標才會變成知識，而不只是輸出。

Happy Hunting！