National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 72 24°C PM2.5 13
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 10

存取控制

不安全的直接物件參照與伺服器端權限檢查
Interaction 30 minute(s)

Learning Objectives

  • 區分認證與授權,並區分水平與垂直權限問題
  • 在模擬網站上觀察不安全的直接物件參照,以擁有者檢查修補,並確認本人仍可讀取
  • 說明隱藏按鈕與難以猜測的識別碼為何不能取代伺服器端的權限檢查
  • 以裝飾器與預設拒絕集中管理權限檢查

認證與授權的差別

學生登入成績查詢系統後,網址列顯示 /grades/102。把網址改成 /grades/103,頁面顯示的可能是另一位學生的成績。系統已經確認了這位使用者是誰,卻沒有確認他能不能讀這筆資料。

這裡涉及兩個不同的問題:

  • 認證(authentication):確認使用者是誰,第 5 課的主題
  • 授權(authorization):確認這位使用者可以對這項資源做什麼,也稱為存取控制(access control)

通過認證不代表通過授權。OWASP Top 10:2025 將存取控制失效(Broken Access Control)列為第一名(A01:2025)。權限問題通常分成兩類:

類型 意義 例子
水平權限 相同角色的使用者,存取到彼此的資料 學生甲讀到學生乙的成績
垂直權限 使用者執行較高角色才能做的操作 學生開啟管理頁面、修改成績

上面的情形稱為不安全的直接物件參照(insecure direct object reference,IDOR):程式直接以使用者提供的識別碼取用資料,沒有檢查這筆資料是否屬於他。

互動練習:不安全的直接物件參照

本區塊為模擬環境。 網站是真的 Flask,只在你的瀏覽器內執行,不連線到任何外部系統,帳號與成績皆為虛構。未經授權嘗試讀取真實系統的資料可能觸犯法律(第 1 課)。

修補時在 grade_detail() 查到資料之後加入擁有者檢查。回應 403 或 404 都可以接受。RFC 9110 允許伺服器以 404 回應,避免透露該筆資料是否存在;403 則能讓使用者知道是權限問題。

if row['owner_id'] != session['user_id']:
    abort(404)

識別碼與擁有者檢查

將流水號換成 UUID 這類難以猜測的識別碼,可以提高列舉的難度,OWASP 將它視為縱深防禦。它不能取代權限檢查:識別碼可能透過網址分享、瀏覽紀錄、日誌或其他 API 回應外流,一旦外流,沒有檢查的程式依然會回傳資料。OWASP 的 IDOR 指引明確指出,即使識別碼複雜,存取控制檢查仍然不可少。

較穩健的寫法是讓查詢本身包含擁有者條件:

row = db.execute('SELECT * FROM grades WHERE id = ? AND owner_id = ?',
                 (grade_id, session['user_id'])).fetchone()

要特別注意 session['user_id'] 的來源。使用者身分應該取自伺服器確認過的工作階段,不可以取自用戶端送來的參數,例如隱藏欄位的 user_id 或查詢字串。用戶端送來的任何內容都可以被修改。

隱藏按鈕與伺服器端檢查

開發者常以「一般使用者看不到連結」處理管理功能,頁面上的連結只顯示給管理員。隱藏連結改善的是介面,不是權限:路由依然存在,任何人輸入網址就能開啟,這稱為強制瀏覽(forced browsing)。

權限檢查必須在伺服器端進行,而且每個端點都要檢查。常見的遺漏是保護了顯示頁面的 GET,卻忘記處理資料的 POST。OWASP 將「POST、PUT、DELETE 缺少存取控制」列為這個類別的常見問題。

重複寫檢查容易遺漏,所以應該集中到一處,以裝飾器(decorator)套用:

@app.route('/admin')
@admin_required
def admin():
    ...

角色與權限要在每次請求時依伺服器端的資料判斷。Flask 預設的 session 存在瀏覽器,放在裡面的角色是登入當下的值,使用者被降級後,舊 Cookie 不會自動改變(第 6 課)。

介面仍然應該依權限顯示按鈕,避免誤導使用者,只是這項做法不能當作權限控制。

互動練習:垂直權限與集中檢查

本區塊為模擬環境。 網站是真的 Flask,只在你的瀏覽器內執行,不連線到任何外部系統,帳號與成績皆為虛構。未經授權嘗試讀取真實系統的資料可能觸犯法律(第 1 課)。

程式已備妥 admin_required 裝飾器,但還沒有使用。把 @admin_required 加到 @app.route 的下一行,兩個管理路由都要加。

本練習同時提供 API 工具,可以不經過頁面表單直接送出請求,代表使用者略過介面的情形。

預設拒絕

裝飾器仍然依賴開發者記得加上去。新增路由時若遺漏,這個路由就對所有人開放。預設拒絕(deny by default)反過來設計:除了明確列出的公開路由,其他路由一律需要登入。OWASP 建議除了公開資源之外都預設拒絕,並在整個應用程式重複使用同一套機制。

Flask 可以用 before_request 實作:

PUBLIC_ENDPOINTS = {'index', 'login'}

@app.before_request
def require_login():
    if request.endpoint not in PUBLIC_ENDPOINTS and 'user_id' not in session:
        abort(401)

Flask 的靜態檔案也是一個端點(static)。登入頁需要的 CSS 與 JavaScript 若放在這裡,要把它加進清單,並確認這個目錄沒有不該公開的檔案。

這段程式只確認「已登入」,屬於第一層。下方練習的 /export 加上登入檢查之後,一般學生登入仍然讀得到所有人的成績,還需要 @admin_required 這類角色檢查;每筆資料是否屬於這位使用者,也要在各自的檢查中處理。存取控制的測試也應該納入單元測試與整合測試,檢查項目包括其他使用者、一般角色與未登入三種情況。

互動練習:預設拒絕

本區塊為模擬環境。 網站是真的 Flask,只在你的瀏覽器內執行,不連線到任何外部系統,帳號與成績皆為虛構。未經授權嘗試讀取真實系統的資料可能觸犯法律(第 1 課)。

路由 /export 是開發者忘記加上檢查的新功能。路由 /lab-probe 由唯讀的 lab_probe.py 提供,它沒有任何檢查,只有全域的規則擋得住。

重點整理

  • 認證確認使用者是誰,授權確認他能做什麼;通過認證不代表通過授權
  • OWASP Top 10:2025 將存取控制失效列為第一名
  • IDOR 是直接以使用者提供的識別碼取用資料而沒有檢查擁有者;修補方式是在伺服器端檢查,或把擁有者條件放進查詢
  • UUID 可以增加列舉的難度,但不能取代權限檢查
  • 隱藏按鈕只改善介面。權限檢查必須在伺服器端,GET 與 POST 等每個端點都要檢查
  • 使用者身分取自伺服器確認過的工作階段,不取自用戶端的參數
  • 以裝飾器集中檢查,以預設拒絕防止遺漏,並將存取控制納入自動測試
  • 只在自己擁有或獲得明確授權的系統上進行測試

下一課討論檔案上傳與路徑穿越。

小測驗

1.

學生登入後把網址的 /grades/102 改成 /grades/103,讀到另一位學生的成績。這屬於哪一種問題?

2.

開發者把成績紀錄的識別碼從流水號改成 UUID,但沒有加入擁有者檢查。這樣的修改如何評價?

3.

一般使用者的頁面上沒有「成績管理」連結,後端路由沒有檢查角色。下列敘述何者正確?

4.

開發者保護了 GET /admin,但處理更新的 POST /admin/grade 沒有檢查。會有什麼後果?

5.

為了判斷使用者身分,下列哪一個來源最適當?

6.

「預設拒絕」與「逐一在路由加上檢查」相比,主要的好處是什麼?

第 1 次作答
這一課完成了!
Next lesson:檔案上傳與路徑穿越
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。