不安全的直接物件引用 (Insecure Direct Object References, IDOR) 是最常見也最容易被忽略的存取控制漏洞之一。它發生在當應用程式允許使用者透過一個可預測的識別碼(如使用者 ID、訂單編號)直接存取資料,卻沒有在後端驗證該使用者是否真的有權限存取該筆資料時。
什麼是 IDOR 漏洞?
IDOR 的核心問題是「有驗證身份,但未檢查權限」。應用程式確認了你是合法的登入使用者(Authentication),但當你請求特定資料時,它卻沒有檢查這筆資料是不是屬於你的(Authorization)。
攻擊者可以透過修改 URL 或 API 請求中的 ID 參數,輕易地存取到其他使用者的資料。
攻擊原理與範例
情境:查看別人的訂單
- 正常操作:小明登入購物網站後,點擊「我的訂單」來查看自己的購買紀錄。他看到瀏覽器的網址列顯示為:
1
https://example.com/orders?order_id=1001
- 發現漏洞:小明注意到 URL 中有一個
order_id=1001
的參數。他好奇地猜想,如果把1001
改成1002
會發生什麼事? - 發動攻擊:他將網址修改為
https://example.com/orders?order_id=1002
並按下 Enter。 - 攻擊成功:由於後端伺服器在收到請求時,只檢查了小明是否為登入使用者,卻沒有檢查「訂單編號 1002」是否真的屬於小明。結果,伺服器直接回傳了另一位使用者「小華」的訂單詳細資料,IDOR 漏洞就此發生。
同樣的攻擊也可能發生在 API 請求上,例如 GET /api/users/123/profile
,攻擊者只需將 123
改成其他數字,就能窺探其他使用者的個人資料。
風險與影響
- 大規模資料洩漏:攻擊者可以透過撰寫腳本,自動化地遍歷所有可能的 ID,大量竊取所有使用者的個人資料、訂單、訊息等。
- 資料竄改與刪除:如果
PUT
或DELETE
等修改操作的端點也存在同樣的漏洞,攻擊者甚至可以修改或刪除其他使用者的資料。 - 權限提升:在某些情況下,存取其他使用者的資料可能間接導致權限提升。
防禦與預防措施
防禦 IDOR 的唯一方法是:在伺服器端對每一次資料存取請求,都進行嚴格的權限檢查。
1. 在後端實作存取控制檢查
- 對於任何需要存取特定物件的請求,後端邏輯必須同時驗證兩件事:
- 使用者是誰?(從 Session 中取得當前使用者 ID)
- 他請求的物件是否屬於他?
- 在資料庫查詢中加入權限判斷,是最好的實作方式。
2. 避免使用可直接猜測的 ID
- 盡量避免在 URL 中使用連續的、可被輕易猜測的數字 ID(如 1, 2, 3…)。
- 可以改用不可預測的通用唯一辨識碼 (UUID) 或經過加密/雜湊的 ID 來代替。雖然這不能完全取代權限檢查,但能大幅增加攻擊者猜測的難度。
程式碼範例 (Django)
錯誤的程式碼:
只用了 score_id
來查詢,沒有檢查使用者身份。
1 | # 錯誤範例:任何登入使用者都能查詢 |
修正後的程式碼:
在查詢時,同時檢查 id
和 user
兩個欄位。
1 | # 正確範例:加入了使用者權限檢查 |
說些什麼吧!