跳至主要內容
>_ITDITD網站資安平台

各框架對策

Ruby on Rails 的資安對策 — 正式環境強化實務參考

Ruby on Rails 的正式環境強化參考:優先度清單,加上秘密與 credentials、設定、gem CVE、Strong Parameters、授權、注入與 SSRF。以防禦視角撰寫,不含攻擊步驟。

發布於 2026-07-02 更新於 2026-07-02 閱讀時間 3 分鐘

對象:正在維運 Ruby on Rails 應用程式的人。這裡不談攻擊步驟——這是用來強化的可實作參考:依優先度排序的清單、各領域指引與自我檢查。想看跨框架的全貌,請參閱 各框架資安對策的入口

依優先度排序的強化清單

由上往下逐項處理這張表。P0 是前提,P1 是最頻繁的事故來源,P2 是持續性的維運衛生。

P0 ── 前提(先做這個)

秘密與 credentials 管理/正式環境設定(不外露例外、force_ssl)/迅速修補 gem CVE

P1 ── 最主要的事故來源

Strong Parameters/Mass Assignment 控制/授權(擁有者範圍)

P2 ── 維運衛生

注入與危險方法/工作階段、CSRF/SSRF、上傳

從地基往上強化:P0(前提)→ P1(最主要的事故來源)→ P2(維運衛生)。
優先度對策具體(Rails)
P0秘密與 credentials加密 credentials+分離的 master key。別 commit master keysecret_key_base 外洩時輪替
P0正式環境設定不外露例外細節;config.force_ssl;用 filter_parameters 讓秘密不進入日誌
P0gem(相依套件)CVE以 bundler-audit / osv-scanner 監控;以實際執行版本判定,迅速修補
P1Strong Parameterspermit 保持最小。別用 permit!。絕不賦值權限欄位
P1明確的授權以 Pundit / CanCanCan+authorizecurrent_user 限定範圍確認擁有者
P2注入/危險方法where 用綁定。別把輸入交給 send/constantize。別載入不可信的 YAML/Marshal
P2工作階段/CSRFprotect_from_forgery(預設)、cookie secure/httponly/samesite、登入時重新產生
P2SSRF/上傳伺服器端取得採允許清單+阻擋內部 IP。驗證上傳,存到 public/ 之外

1. 秘密與 credentials(P0)

  • 使用 Rails 的加密 credentials,並別把 master(解密)key commit 進 repo(改用環境變數等注入)。
  • secret_key_base 是簽章/加密 cookie 與工作階段的基礎。外洩就立即輪替(注意這會使既有的簽章/加密失效)。
  • 別把 .env、傾印檔或備份放在公開目錄(→ 別把秘密放在公開目錄)。

2. 正式環境設定(P0)

  • 在正式環境別外露例外細節(別啟用 consider_all_requests_local 等)——減少內部結構的揭露。
  • config.force_ssl 強制 HTTPS 並把 cookie 標記為 secure。別在正式環境啟用 web console 這類開發工具。
  • filter_parameters 讓密碼等內容不進入日誌。

3. gem(相依套件)CVE(P0)

  • bundler-audit 或 osv-scanner 以機器監控 gem 的 CVE,以實際執行的版本(Gemfile.lock)判定,迅速修補(→ 監控相依套件的 CVE · 漏洞應變實務手冊)。
  • Rails 與 Ruby 保持在受支援的版本,別放任 EOL 版本。

4. Strong Parameters 與 Mass Assignment(P1)

  • permit 欄位保持最小,避免 permit!(全允許)。
  • **絕不從使用者輸入賦值像 is_admin 這類權限欄位。**丟掉「為了方便就放寬」。

5. 授權(P1——最主要的來源)

常見(危險)

  • 不寫授權——「已登入=可檢視/更新」
  • 路由模型綁定取到別的使用者的 ID
  • 依賴隱藏的路由/難以猜測的 ID
  • 有些 action 忘了寫 authorize

正確

  • Pundit / CanCanCan 把政策寫明確+每個 action 都 authorize
  • 連讀取也用 current_user 限定為擁有者範圍
  • 每一條讀取/更新/刪除路徑上驗證
  • 授權是明確地寫出來,而非交給預設

參閱 IDOR 是什麼。驗證與授權是兩回事;在貼近資料的地方授權。

6. 注入與危險的動態方法(P2)

  • SQL:在 where 以佔位符綁定;絕不用字串串接組查詢(避免 where("... #{params}"))(→ SQL 注入是什麼)。
  • 危險的動態方法別把使用者輸入交給 send/public_send/constantize。若非用不可,就以允許清單嚴格限制。
  • 還原序列化:避免載入不可信的 YAML/Marshal(在特定條件下可能導致程式碼執行)。

7. 工作階段、cookie、CSRF(P2)

  • 別全域停用 CSRF 保護(protect_from_forgery;善用表單 token(→ CSRF 是什麼)。
  • 在 cookie/工作階段設 secure/httponly/samesite,並在登入時重新產生工作階段。

8. SSRF、上傳、標頭(P2)

  • 伺服器端取得使用者提供的 URL 時,應把目標限制為允許清單阻擋觸及內部 IP/中繼資料(→ SSRF 是什麼)。
  • 驗證上傳(類型/大小)、存到 public/ 之外,並不授予執行權限。
  • 加上安全標頭(用 安全標頭檢測 檢查自己的網站)。

檢驗:你的 Rails 真的強化了嗎?

做完不是終點——檢查過才算完成。以下是針對你自己環境的防禦性自我檢查。

1

秘密沒有外露/被 commit

確認 master.key 不在 repo 裡,且 .env/傾印檔無法用 URL 取得。
2

正式環境不外露例外細節

故意觸發錯誤,確認詳細例外不會對外顯示,且 HTTPS 被強制。
3

授權有效

在測試環境中,請求別的使用者的資源 ID,確認它被拒絕(讀取/更新/刪除)。
4

相依套件與標頭

確認 bundler-audit/osv 為乾淨,且透過 標頭檢測 確認有 HTTPS/HSTS。

本站的觀點:即使有慣例守著,授權與相依套件仍在你身上

Rails 良好的預設消去了許多風險,但授權——誰可以做什麼——以及相依套件的新鮮度,是應用程式與維運特有的,框架無法自動替你守。我們反覆看到的事故,與其說是精巧的攻擊,不如說是「有驗證卻沒有擁有者檢查」那一型。所以防禦的重心,是把上面那張表由上往下逐一處理——收緊 Strong Parameters、把授權寫明確、對 gem 監控 CVE。

接下來讀

FAQ

Q要保護 Rails,第一步該做什麼?
A

三個 P0 項目:(1) 安全地處理秘密(把加密的 credentials 與 master key 分開,別把 master key commit 進去;secret_key_base 是簽章/加密 cookie 的基礎,外洩時要輪替);(2) 收緊正式環境設定(不外露例外細節;force_ssl);(3) 用機器監控 gem(相依套件)的 CVE 並迅速修補,以實際執行的版本判定。接著再進到 Strong Parameters 與授權。

Q使用 Strong Parameters 要注意什麼?
A

明確允許(permit)你接受哪些欄位,以防止 Mass Assignment(把未預期的欄位一次性批次賦值)。危險的是為了方便而放得太寬,以及用 permit! 允許一切。把允許的欄位收到最小限度,像 is_admin 這類權限欄位絕對不要讓它從使用者輸入被賦值。

Q要如何安全地實作授權?
A

在登入(驗證)之上,實作一個確認目標真的屬於該使用者的擁有者檢查。用 Pundit/CanCanCan 把政策寫明確,在每個 action 都執行 authorize,並用 current_user 限定資源範圍。別依賴隱藏的路由或難以猜測的 ID——在每一條讀取/更新/刪除的路徑上都明確驗證。

Qgem(相依套件)的漏洞要如何管理?
A

用 bundler-audit 或 osv-scanner 以機器監控已知 CVE 並迅速修補,以實際執行的版本判定(依 Gemfile.lock 的實際版本判斷)。把 Rails 與 Ruby 保持在受支援的版本,別放任 EOL 版本。相依套件的新鮮度,比起精巧的攻擊,是更貼近現實的事故分水嶺。

Q危險的動態方法有哪些?
A

把使用者輸入交給 send / public_send / constantize,可能導致未預期的方法呼叫或類別解析。同樣地,透過 Marshal 或不可信的 YAML 載入(還原物件),在特定條件下可能導致程式碼執行。別把使用者來源的資料交給這些方法;若非用不可,就以允許清單嚴格限制。