Ruby on Rails Security 最佳實務

這是我 2/26 在中研院 OSSF 工作坊和 3/23 在 Ruby Tuesday 所演講的題目之一。

Ruby on Rails 要談的 Security 網站安全,主要在 Web application layer 的範圍(這也是最容易被攻擊的部分),像是 XSS、CSRF、Session Hijacking 跟 Fixation、SQL Injection 等等都是所有 Web 應用程式必須處理的問題。也有一些是 Rails 為了程式方便性而製造出來的問題,像是 Mass assignment、Unscoped finds、Controller Exposing methods 等等。

會講的內容看投影片就可以了,這裡我想特別提一下我的開場跟一個觀念:

我的開場引用了 PHP Security Guide: Overview 介紹什麼是 Security,我很喜歡:

  1. 安全性是相對的,不是一個功能。碰過太多客戶要求 “網站要絕對安全,不能被 HACK”,這實在太強人所難了。安全性就跟溫度一樣,相對熱、相對冷。安全性也是相對安全、相對不安全的,而不是像功能說有或沒有。
  2. 承上,要越安全,就給花越多成本去做。不過呢,不需要多花什麼錢,就可以很簡單做到足夠地安全。如果要非常非常安全,就會非常非常貴了。所以請考量你的預算。
  3. 必須要與使用性(usability)做平衡。很多時候,安全性跟使用性會是衝突的,想要越多安全性,就給犧牲掉一些使用上的方便性。
  4. 安全性必須是網站程式設計過程中的一部分,而不是最後才加上去。

而想提的寫程式觀念是我看 Security on Rails 一書裡面介紹的 Fail Close,底下第一段是用 Fail open 觀念寫的程式,第二段是用 Fail close。


# fail open way, it’s bad
def show
  @invoice = Invoice.find(params[:id])
  unless @user.validate_code( @invoice.code )
    redirect_to :action => 'not_authorized'
  end
end


# fail close way
def show
  @invoice = Invoice.find(params[:id])
  if @user.validate_code( @invoice.code )
    redirect_to :action => 'authorized
  else
    redirect_to :action => 'not_authorized'
   end
end

其中的端倪就是,在撰寫驗證安全性程式碼的時候,請用 Fail close 的觀念:”如果條件成功,才允許進行,不然就不允許”。而不是 Fail open:”如果條件不成功,才不允許,不然就允許。”。這個簡單的撰碼觀念,可以減少我們寫出漏洞程式碼的機會。

參與討論

2 則留言

  1. Fail close 的部份令人有點困惑。如果正面表列的數量很多,用 Fail close 似乎整個 code 就不簡潔了(也可能遺漏)?

  2. 如果是遺漏了正面表列的條件,那就是有人沒辦法執行而已(一個不影響安全性的bug)。但是如果是負面表列遺漏了,那….. 就是一個安全大漏洞啦。

發佈留言

發表迴響