こんにちは。哥倫比亞大學博士班、研究系統安全的 Koukyosyumei。
這幾天,我看到與資安事件相關的新聞變多了。看到這類新聞時,很多人或許都會想:「我的 Web 服務沒問題吧?」
談到對 Web 應用程式的攻擊,腦中可能會浮現技術高超的駭客,使用複雜程式入侵,或運用社交工程的畫面。不過在實際的資安檢測與漏洞賞金中,往往也會從更簡單的地方開始調查。
例如:
.env 或 .git/config乍看之下都是很單純的操作,但光是這些,就有可能發現重大漏洞。
當然,Web 應用程式的漏洞不只這些。XSS、SQL Injection、SSRF、授權不足、商業邏輯問題等,都是攻擊者會關注的重點。
本文將從「攻擊者會檢查 Web 應用程式的哪些地方」這個角度出發,介紹一份初學者也能輕鬆在自己的服務上實踐的資安檢查清單。
我盡量整理成即使沒有太多專業知識也能執行的形式,並附上具體的確認方式與發現問題時的處理方法。
另外,本文介紹的主要是用來找出 Web 應用程式本身漏洞的方法。像 MFA、備份、日誌監控等營運面資安措施也很重要,但這次不會涵蓋。
注意:以下測試僅限於你自己擁有的 Web 服務,或已明確取得測試許可的環境。請盡可能使用本機環境或 staging 環境,並搭配測試帳號與測試資料。
攻擊者在檢視 Web 應用程式時,最先做的事情之一就是偵察與資訊蒐集(Reconnaissance)。他們會調查有哪些 API、使用了哪些框架、有沒有洩漏內部資訊等。
例如,Web 伺服器設定錯誤時,開發時使用的設定檔可能會直接被公開。請在自己的 Web 服務中確認以下 URL:
https://example.com/.env
https://example.com/.git/config
https://example.com/backup.zip
https://example.com/.env.bak
.env 可能包含資料庫密碼或 API 金鑰,.git 可能包含原始碼歷史。
不過,光是回傳 HTTP 200,並不代表檔案真的被公開。有些 SPA 會對不存在的 URL 回傳同一份 HTML,因此也要確認回應內容。
如果你有把程式碼公開在 GitHub,也要注意。很好用的工具是 OSS 的 Gitleaks,它可以從 Git 的 commit 歷史中偵測 API 金鑰、密碼等機密資訊。
在 macOS 上可以這樣安裝:
brew install gitleaks
把自己的儲存庫 clone 下來後,執行以下指令:
gitleaks git . --redact
不只目前的程式碼,連過去的 commit 也都會納入檢查。若偵測到機密資訊,不只是從 Git 中刪除字串而已,還要讓可能外洩的金鑰失效並重新發行。
接著,打開 Chrome 的開發者工具,查看 Network 與 Sources 分頁。你可以觀察 Web 服務呼叫了哪些 API,以及傳送了哪些 JavaScript。
例如,可能會發現:
.js.map)這些內容被公開,並不代表一定立刻形成漏洞,但仍值得確認是否含有不該公開的資訊。
檢查清單
.env、.git、備份等沒有被意外公開Web 應用程式中有很多接收外部資料的地方,例如搜尋欄、登入表單、留言、檔案上傳等。攻擊者會試著透過這些輸入,讓原本應該只是資料的字串,被當成程式或指令來解讀。
這類攻擊中最有名的之一就是 XSS(Cross-Site Scripting),也就是讓 Web 頁面執行不該執行的腳本。
例如,假設有一個可以發表留言的 Web 服務。正常情況下,輸入的字串應該會以文字顯示。但如果 HTML 的處理方式不當,輸入內容可能會被當成 HTML 解析。
先在自己的測試環境的搜尋欄或留言欄輸入以下字串:
<b>security-test</b>
在輸入的位置或其他頁面上,這段文字會原樣顯示嗎?還是會意外被當成粗體 HTML?
如果被當成 HTML 解析,就有可能進一步導致 XSS,需要再深入確認。不過,像 Markdown 編輯器這類功能,本來就可能有意地渲染 HTML。HTML 被解析本身,不一定就代表 XSS。更精確地說,重點是:使用者可控制的字串,是否會導致非預期的 JavaScript 執行。
檢查清單
innerHTML 等位置基本對策是,依照輸出位置的上下文,做適當的 escape 或 sanitize,例如 HTML、JavaScript、URL 各自都要採用對應的處理方式。
參考:OWASP Cross Site Scripting Prevention Cheat Sheet
SQL Injection 是指使用者輸入影響了 SQL 語句結構的漏洞。
例如,假設有一個搜尋使用者名稱的功能:
SELECT * FROM users WHERE name = 'alice';
如果這段 SQL 是用字串串接組出來的,會怎樣呢?
query = "SELECT * FROM users WHERE name = '" + name + "'"
就可能依照 name 的內容產生非預期的 SQL。
在你的服務中,可以先在搜尋欄或篩選條件輸入單引號(')等特殊字元,確認是否會出現異常錯誤。
不過,沒有錯誤並不代表不存在 SQL Injection。更重要的是確認實作是否使用參數化查詢。例如在 Python 裡,可以這樣寫:
cursor.execute(
"SELECT * FROM users WHERE name = ?",
(name,)
)
透過分離 SQL 結構與輸入值,可以避免使用者輸入被當成 SQL 語法解析。
檢查清單
NoSQL 資料庫也可能有把外部輸入當成查詢運算子解讀的問題,因此同樣要注意。
參考:OWASP SQL Injection Prevention Cheat Sheet
圖片轉換、PDF 產生、檔案壓縮等功能,常會從後端呼叫外部指令。例如,把檔名用字串串接組成 shell 指令的做法,就可能成為 Command Injection 的原因。
攻擊者會確認,能否透過修改檔名或參數,讓系統執行不該執行的指令。
例如,假設 Web 應用程式在轉換圖片時,會用 Python 執行外部指令:
import os
filename = request.args["filename"]
os.system(f"convert {filename} output.png")
原本可能預期輸入像 image.jpg 這樣的檔名,但如果攻擊者把檔名指定為 image.jpg; touch /tmp/injection.txt,; 可能會被 shell 當作指令分隔符,進而執行無關的 touch 指令。
檢查清單
shell=True如果可以,最好不要經過 shell,而是直接使用函式庫 API。
Web 應用程式安全中特別重要的,還有存取控制與商業邏輯的驗證。
即使沒有輸入 XSS 或 SQL Injection 那類特殊字串,只要稍微改一下正常的 HTTP request,也可能找到重大問題。
例如,登入使用者可以透過以下 API 取得自己的個人資料:
GET /api/users/123
這裡的 123 是自己的使用者 ID。
攻擊者會嘗試把這個 ID 改成別人的,確認是否也能取得資料:
GET /api/users/124
如果能取得其他使用者的非公開資訊,就可能存在 IDOR(Insecure Direct Object Reference)之類的授權缺陷。
實際確認方式
在自己的測試環境中,建立兩個使用者:Alice 和 Bob。
更新與刪除 API 也同樣測試一次。
特別是 SaaS 服務中,不能存取其他組織或 tenant 的資料也很重要。
檢查清單
接著,來看 API 接收的 JSON。例如,使用者個人資料更新 API 可能會收到如下 request:
{
"display_name": "Alice"
}
如果伺服器端把客戶端傳來的 JSON 直接反映到使用者模型上,會怎樣呢?
{
"display_name": "Alice",
"role": "admin"
}
原本不該變更的 role 可能也被寫入。這就是 Mass Assignment 的典型問題。
檢查清單
role、is_admin、owner_id 等欄位實際確認時,可以在測試環境加入意料之外的欄位,確認它是否會寫入資料庫。
到目前為止,多半是在談單一 API 的問題。但即使每個 API 單獨看都沒問題,把它們組合起來後,仍可能出現漏洞。
例如考慮電商網站的優惠券流程:
但如果處理順序或競態條件有問題,就可能讓同一張優惠券被重複使用。攻擊者會特別注意這種「原本不該發生的操作順序」。
檢查清單
這類 bug 通常不容易被單純的弱點掃描器發現,所以特別值得花時間調查。
接著要確認的是,攻擊者是否能透過 Web 應用程式存取內部網路或檔案系統等。
近年的 Web 服務常見這種功能:使用者輸入 URL,伺服器去存取該 URL。
例如:
如果這類功能沒有妥善限制 URL,攻擊者可能讓伺服器對不該接觸的目標送出 request。這就是 SSRF(Server-Side Request Forgery)。
例如,假設有個 Web 應用程式會從使用者指定的 URL 下載圖片:
import requests
url = request.args["url"]
response = requests.get(url)
正常預期會輸入像 https://example.com/image.png 這樣的 URL。但如果攻擊者指定 http://127.0.0.1:8080/admin,就可能讀到執行 Web 應用程式的伺服器資訊。
實際測試 SSRF 時,如果你的服務有輸入 URL 的功能,可以準備一台測試用 HTTP 伺服器,確認對該 URL 的存取會如何處理。例如,在本機測試環境中確認不允許的內部目標 URL 是否會被拒絕。
檢查清單
參考:OWASP SSRF Prevention Cheat Sheet
檔案上傳與下載功能,也是攻擊者會特別關注的地方。
例如:
GET /download?file=report.pdf
如果這個 API 直接把 request 的 file 參數當成檔案路徑來用,會怎樣呢?
只要稍微設計輸入,就可能存取到原本不公開的檔案。這就是 Path Traversal 的典型問題。
另外,也可能有圖片上傳功能其實接受了任意檔案,甚至把上傳檔案放到伺服器上可執行的位置。
檢查清單
避免直接從外部輸入組出檔案路徑,或改用 file ID 來安全管理,會是有效的做法。
就算自己寫的程式沒有漏洞,依賴函式庫也可能有問題。先確認目前使用的函式庫是否存在已知漏洞。
Node.js:
npm audit
Python:
pip-audit
Rust:
cargo audit
也可以使用 GitHub Dependabot,持續接收依賴關係漏洞的通知。
檢查清單
到目前為止介紹的,主要是長期以來已知的漏洞。不過,現代 Web 服務會結合 CDN、OAuth、GraphQL、WebSocket、生成式 AI 等多種技術,這些架構也會帶來特有的攻擊。
如果使用 Google 登入等 OAuth/OIDC,就需要確認認證流程本身是否設計正確。
例如,如果登入完成後的重新導向目的地可以任意指定,或認證回應與原始登入請求沒有正確關聯,就可能引發問題。
檢查清單
state 等機制正確驗證請求關聯nonce 等項目如果有使用 CDN 或 reverse proxy,也要注意快取設定。
Web Cache Poisoning 是指攻擊者影響會被快取的回應,讓其他使用者收到不該看到的內容。
Web Cache Deception 則是把原本不該快取的個人化回應,意外存進共享快取。
檢查清單
在測試環境中,確認使用者 A 的非公開回應不會被回傳給使用者 B。
即使不是 REST API,存取控制的驗證也很重要。例如 GraphQL 可以透過單一端點取得很多種類的資料,因此每個欄位與物件都需要適當授權。
WebSocket 也是如此,即使在連線時已認證,也可能沒有對每則訊息或每個操作做權限檢查。
檢查清單
到這裡,我們介紹了在檢視 Web 應用程式時,最常被注意到的幾個重點。最後整理成檢查清單。
.env、.git、備份等沒有公開當然,確認這些內容不代表就能保證 Web 應用程式一定安全。不過,理解攻擊者會如何檢查 Web 應用程式,並且自己也用相同視角來檢查,正是提升資安的第一步。
另外,測試不應只做一次,而是要隨著新功能加入與程式碼變更持續進行。
上面介紹的檢查中,有些可以比較簡單地手動確認。不過,當 Web 應用程式變得更複雜時,要手動檢查所有 API、畫面與使用者權限組合會非常困難,也需要專業知識。
這時,安全測試自動化就很有幫助。例如,OWASP ZAP 與 Burp Suite 等工具,都是業界常用的方案。
另外,近年也有讓 AI agent 操作 Web 應用程式,協助發現漏洞的方法。
最後,容我介紹一下我正在開發的 OSS h5i。h5i 是一個給 AI agent 使用的工具,用來提升 Web 應用程式的安全性。
它可以讓 AI agent 操作瀏覽器,也可以記錄、修改並重新送出 HTTP request。例如,可把以下檢查交給 AI agent 來做:
h5i 本身是免費的 OSS,除非你使用外部 AI 模型,否則不會產生軟體使用費。如果有興趣,歡迎試試看。只要安裝 h5i 的 binary,並請 Claude Code 或 Codex 等工具下達「使用 h5i 監査這個 Web 應用程式」這類指令,就能執行較完整的攻擊測試。你也可以透過 h5i ui 這個指令查看直觀的儀表板。

h5i 不只用來找漏洞,也提供一套框架,讓你在開發 Web 應用程式時,同時證明原本就沒有某些漏洞。
一般的資安測試,是透過實際送出 request 或修改輸入,來找出漏洞存在的證據。
相對地,形式驗證的目標是,以數學方式證明「某一類漏洞不會發生」。例如,對於多組織共用的 Web 應用程式,可以證明「組織 A 的使用者無法存取組織 B 的非公開資料」這類性質。
h5i 正在開發一套機制,結合 Rust 的 Web 應用程式框架與名為 Lean 4 的定理證明助理,來驗證這類性質。
當然,證明也有前提條件與適用範圍,並不代表整個 Web 應用程式會無條件變安全。即便如此,我仍認為,把「攻擊來找漏洞」與「證明沒有漏洞」結合起來,能幫助打造更可靠的 Web 服務。
原文出處:https://qiita.com/Koukyosyumei/items/8aaa44ff15a3b404fd8b