Permissions#

概述#

網站上的使用者通常有不同等級的權限。例如:

  • 在內容管理系統中,管理員可以編輯網站內容,大多數使用者只能檢視和互動
  • 社群媒體網站有更複雜的權限網絡:使用者可以選擇只與朋友分享特定內容或鎖定個人資料
  • Webmail 網站中,每個使用者只應能存取自己的電子郵件

正確且一致地在整個網站中執行這些權限至關重要,否則使用者將失去對你的信任。

Facebook 在 2018 年 9 月遭受了一次嚴重的權限失敗,駭客利用影片上傳工具的漏洞產生存取 token,多達 5,000 萬個使用者帳號被入侵,個人資料被竊取。

Privilege Escalation(權限提升)#

安全專家將 privilege escalation 攻擊分為兩類:

Vertical Escalation(垂直提升)#

攻擊者取得比自己更高權限的帳號存取權。

  • 如果攻擊者能在伺服器上部署 web shell(一個可執行腳本,接受 HTTP 請求元素並在命令列上執行),其首要目標之一就是提升到 root privilege
  • Web shell 執行的命令通常以 web server 運行的作業系統帳號執行,通常有有限的網路和磁碟存取權
  • 駭客已找到許多在作業系統上進行垂直提升的方法,試圖取得 root 存取權來感染整台伺服器

Horizontal Escalation(水平提升)#

攻擊者存取具有類似權限的另一個帳號。

  • 常見的攻擊方式包括:猜測密碼、劫持 session、惡意製作 HTTP 請求資料
  • 2018 年 Facebook 駭客事件就是水平提升的例子,由一個 API 未正確驗證使用者權限就發放 access token 所導致

為了保護網站免受 escalation 攻擊,你需要為所有敏感資源安全地實作 access control。

Access Control(存取控制)#

存取控制策略應涵蓋三個關鍵面向:

  • Authentication(認證):當使用者返回網站時正確識別其身份
  • Authorization(授權):決定使用者在識別身份後應該和不應該執行哪些操作
  • Permission checking(權限檢查):在使用者嘗試執行操作的時間點評估授權

良好的存取控制策略包含三個階段:設計授權模型、實作存取控制、測試存取控制。此外還可以加上稽核軌跡並確保沒有遺漏常見的疏忽。

設計授權模型#

Access Control Lists (ACLs)#

存取控制清單 (ACLs) 是一種簡單的授權建模方式,為系統中每個物件附加一組權限清單,指定每個使用者或帳號可以對該物件執行的操作。

  • 典型範例:Linux 檔案系統,可以個別授予每個使用者對每個檔案和目錄的讀取、寫入或執行權限
  • 大多數 SQL 資料庫也實作了 ACL-based 授權

Whitelists and Blacklists#

  • Whitelist(白名單):描述可以存取特定資源的使用者或帳號,禁止所有其他使用者
  • Blacklist(黑名單):明確描述被禁止存取資源的使用者或帳號
  • 常見應用:垃圾郵件過濾器使用白名單和黑名單來區分電子郵件地址

Role-Based Access Control (RBAC)#

角色型存取控制 (RBAC) 可能是最全面的授權模型:

  • 授予使用者 roles(角色),或將使用者加入具有特定角色的 groups(群組)
  • 系統中的 policies(政策)定義每個角色如何與特定 subjects(主體/資源)互動
  • 範例:AWS IAM 系統和 Microsoft Active Directory

RBAC 強大但容易變得複雜。政策可能互相矛盾,使用者可能屬於多個群組且有重疊的關注點,有時很難看出系統為何做出特定的存取控制決定。

Ownership-Based Access Control#

在社群媒體時代,圍繞 ownership(所有權)概念組織存取控制規則變得很常見:

  • 每個使用者對自己上傳的照片或建立的貼文擁有完全控制權
  • 使用者本質上是自己內容的管理員:可以建立、上傳、刪除,並控制自己貼文、評論、照片和限時動態的可見性
  • 每種內容類型都有隱含的隱私等級

實作存取控制#

實作授權規則的方式有多種:

  • 使用 function 或 method decorators(為函式標記特定權限等級)
  • URL checking(例如為敏感路徑加上 /admin 前綴)
  • 在程式碼中插入 inline assertions
  • 將存取控制決策委託給專用的權限元件或內部 API
from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('content.can_publish')
def publish_post(request):
    # Publish a post to the front page.

無論使用哪種方法實作權限檢查,都要確保基於經過正確驗證的身份資料做出存取控制決策。不要依賴 HTTP 請求中除了 session cookie 以外的任何內容來推斷使用者身份和權限。惡意使用者可以篡改請求中的任何其他內容。

測試存取控制#

  • 確保測試程序真正嘗試找出存取控制方案中的漏洞——像攻擊者一樣對待它
  • 撰寫 unit tests,斷言誰可以存取特定資源,更重要的是,誰不應該能存取它們
  • 養成在新增功能時撰寫描述存取控制規則的新測試的習慣
  • 考慮聘請外部團隊進行 penetration testing(滲透測試)

加入 Audit Trails(稽核軌跡)#

Audit trails 是在使用者執行操作時記錄的 log 檔或資料庫條目:

  • 可以幫助診斷問題發生時的狀況
  • 在被駭客入侵時提供重要的證據

避免常見疏忽#

  • 不要假設未從其他地方連結的頁面就會被隱藏——駭客的爬蟲工具會發現它們
  • 駭客工具可以快速列舉包含不透明 ID 的私有 URL(如 http://example.com/item?id=423242
  • 依賴攻擊者無法猜到 URL 稱為 security through obscurity(模糊安全),這不是可靠的防護

對於設計為在特定時間才可存取的 embargo 資源要特別注意。金融報告網站經常因為存取邏輯有漏洞而被罰款。確保你的存取控制規則考慮到時間限制需求。

Directory Traversal(目錄遍歷)#

如果網站的 URL 包含描述檔案路徑的參數,攻擊者可以使用 directory traversal 來繞過存取控制規則。

Filepath 與 Relative Filepath#

  • Filepath(檔案路徑):描述檔案在檔案系統中的位置,例如 /tmp/logs/web.log
  • Relative filepath(相對路徑):以 . 開頭,表示當前目錄;使用 .. 語法引用父目錄
  • 例如 ../../etc/passwd 表示往上兩層目錄,然後找到 etc 目錄中的 passwd 檔案

Directory Traversal 攻擊的解剖#

假設你有一個網站讓使用者下載 PDF 檔案,URL 中包含檔名參數:

foodle.com/menus?menu=arachnaburger.pdf

Figure 11-1: 允許檔案下載的網站

如果檔名參數沒有被安全地處理,攻擊者可以替換為相對路徑:

foodle.com/menus?menu=../../../../etc/passwd

這讓攻擊者能讀取 Linux 系統上的使用者帳號資訊,暴露敏感的系統資訊。

Figure 11-2: 利用目錄遍歷攻擊存取敏感檔案

緩解措施#

緩解 1:信任你的 Web Server#

  • 熟悉你的 web server 如何解析靜態內容 URL
  • 盡量使用 web server 內建的 URL 解析邏輯,而非自己撰寫
  • Web server 的靜態檔案託管功能通常經過充分測試,能防禦 directory traversal 攻擊

緩解 2:使用 Hosting Service#

  • 如果提供不屬於程式碼一部分的檔案(如使用者上傳的檔案),強烈考慮將它們託管在 CDN、雲端儲存或 CMS 中
  • 這些服務不僅能緩解檔案上傳漏洞,也能透過安全的 URL 或不透明的檔案識別碼來防禦 directory traversal

緩解 3:使用間接檔案參照#

  • 為每個檔案指定一個 opaque ID(不透明識別碼),對應到檔案路徑
  • 所有 URL 透過該 ID 參照檔案
  • 需要維護一個將檔案 ID 對應到路徑的註冊表(例如在資料庫中)

緩解 4:清理檔案參照#

如果必須在 URL 中使用直接檔案參照:

  • 最安全的方式是禁止任何包含路徑分隔字元(包括 encoded 分隔字元)的檔案參照
  • 注意 Windows 和 Unix 系統使用不同的路徑分隔符號(\/
  • 可以使用 regular expression 驗證檔名
  • 盡可能使用第三方函式庫來清理檔案名稱

相對路徑的上層目錄語法可以用多種方式編碼(如 ../..\%2e%2e%2f%252e%252e%252f 等),駭客持續研究新的和隱蔽的路徑名稱編碼方式。

總結#

  • 網站使用者通常有不同等級的權限,你需要實作在使用者嘗試存取資源時評估的 access control 規則
  • Access control 規則需要被清楚記錄、全面實作、並積極測試
  • 開發時程應包含足夠的時間讓團隊評估所有新程式碼變更的安全影響
  • 透過檔名參照的靜態資源容易受到 directory traversal 攻擊
  • 可以透過使用 web server 現有的靜態檔案服務方式、安全的第三方系統、間接參照或清理 HTTP 參數來防禦