各框架對策
Ruby on Rails 的資安對策 — Strong Parameters、授權、gem CVE 的守法
Rails 備有安全的預設,但事故來自維運:Strong Parameters 放得太寬(Mass Assignment)、授權作得太薄(驗證≠授權),以及 gem 的已知 CVE。收緊 permit、把授權寫明確、監控 gem 的 CVE。以防禦視角講解,不含攻擊步驟。
對象:正在維運 Ruby on Rails 應用程式的人。這裡不談攻擊步驟,只講如何讓安全的預設持續生效,同時補起維運所開的破口。想看全貌,請參閱 各框架資安對策的入口。
三大陷阱(一旦離開預設就開)
Rails 的預設很出色,但下面這三點是要開發者刻意去守的領域。
① Mass Assignment
permit 放得太寬,is_admin 等被未預期地覆寫。
② 授權太薄
有驗證卻沒有擁有者範圍。換個 ID 就看到他人的資料(IDOR)。
③ gem 的已知 CVE
放任相依 gem 的漏洞。以實際執行版本判定,迅速修補。
此外,也要留意**where 的字串串接造成的 SQLi**、把使用者輸入交給危險的動態方法(send/constantize),以及 credentials/secret_key_base 的外洩。
補起來的方法(3 步驟)
把 Strong Parameters 保持最小
is_admin 這類權限欄位絕不從使用者輸入賦值。丟掉「為了方便就放寬」的作法。把授權寫明確
current_user 限定資源範圍,並用 Pundit / CanCanCan 把政策寫明確。每次讀取/更新/刪除都確認擁有者(→ IDOR 是什麼)。監控 gem(相依套件)的 CVE 並迅速修補
where 使用佔位符,絕不用字串串接。常見(危險)
- Strong Parameters 放得太寬(Mass Assignment)
- 不寫授權——「已登入=可檢視」
- 放任 gem 的已知 CVE 不修補
where("... #{params}")字串串接
正確
- permit 保持最小
- 明確的授權(current_user/Pundit)
- gem CVE 監控+迅速修補
where使用佔位符
本站的觀點:即使有慣例守著,授權與相依套件仍在你身上
Rails 良好的預設消去了許多風險,但授權——誰可以做什麼——以及相依套件的新鮮度,是框架無法自動替你守的兩件事。我們反覆看到的事故,與其說是精巧的攻擊,不如說是「有驗證卻沒有擁有者檢查」那一型。所以防禦的重心是:收緊 Strong Parameters、把授權寫明確、對 gem 監控 CVE。這三點雖不起眼,卻能擋下 Rails 實務中大半的事故。
接下來讀
- 入口:各框架資安對策(入口) · Laravel 資安對策(同為 MVC、授權的型態相近)
- 實務:漏洞應變實務手冊 · 監控相依套件的 CVE
- 名詞:IDOR 是什麼 · SQL 注入是什麼
FAQ
QRuby on Rails 是安全的框架嗎?
Rails 奉行『慣例優於設定』,內建許多安全的預設——CSRF 保護、Strong Parameters、基於 ORM 的 SQL 防護都是標準配備。用得正確它是很穩固的框架,但一旦跨出預設或省略必要的作工,就會開出破口。Strong Parameters 放得太寬、授權不足、放任 gem(相依套件)的 CVE,與其說是 Rails 特有的問題,不如說是反覆發生的維運問題。
Q使用 Strong Parameters 要注意什麼?
Strong Parameters 是明確允許(permit)你接受哪些欄位的機制,用來防止 Mass Assignment(把未預期的欄位一次性批次賦值)。危險的是為了方便而放得太寬。把允許的欄位收到最小限度,像 is_admin 這類權限欄位絕對不要讓它從使用者輸入被賦值。
Q『只要登入就看得到』為什麼危險?
那是有驗證卻沒有授權的狀態。Rails 提供登入(驗證)的機制,但那筆資料是否真的屬於該使用者,是應用程式特有的授權,得由你自己寫。若省略用 current_user 限定資源範圍、或用 Pundit/CanCanCan 把政策寫明確,那麼把 URL 裡的 ID 換掉,就可能看到別人的資料(IDOR)。