用 Ruby on Rails 開發要注意的安全問題

這是第 24 屆駭客年會 (24C3) 上的一段 session,這一篇只是幫投影片作一些 brief..

前幾天看到一篇文章,裡面有提到在駭客年會上有個議程談論了 Ruby on Rails 的安全問題,我讀了一遍投影片,做出了以下的心得整理:

  • 避免別人一下就拆穿你伺服器的架構

    (這是我的心得)用 open source 的 framework 是兩面刃,你可以從程式碼中學到一些設計理念,覺得它不夠好的地方行有餘力還可以自行修改,不過,若是這個 framework 有一些漏洞,那有心人士一樣可以參考程式碼來進行攻擊,所以要嘛就勤奮地作 patch,不然就是要學會一點隱匿方法。

    投影片中提到,由於 Rails 提供了「漂亮的 URL」,像是 /project/show/12, /user/new 之類的,一下就讓人家猜出應該是用 Ruby on Rails 開發的,就像過去看到 http://xxxxx/yyyyy.do 也會猜測應該就是 Struts。如果你不想在網址上就被人家猜出來是用 RoR 的話,就認真改一下 url.conf 吧。

    再來就是 Rails project 的 public 目錄下有太多的範本,如 400.html500.html ,如果看到這樣的畫面:

    404

    很難說這不是 Rails web 吧 XD!

    再來就是,很多人的 Rails web 都會用 FastCGI 或是 Mongrel 當作 application server ,一次開很多個 AS,前端再用個 reverse proxy 之類的東西來作 load balance。不過投影片的作者提到,http request 時,server 端的回應會有 Server 的欄位,這時候就會說出你用了 mod_fastcgi 還是 Mongrel,甚至連版本資訊都有,比方說我們來試驗一下最近爆紅的 VeryXD

    ...
    Connected to g.veryxd.net.
    Escape character is '^]'.
    GET / HTTP/1.0
    Host: g.veryxd.net

    HTTP/1.1 200 OK
    Date: Fri, 11 Jan 2008 01:00:50 GMT
    Server: Mongrel 1.1.3
    Status: 200 OK
    ...

    所以我們知道了 VeryXD 是用 Mongrel 1.1.3 的版本來架設的。如果要避免被人家知道 Server 資訊的話,可以在 httpd.conf 之類裡去把 Server 欄位給 unset 掉。

    再來就是很多人在部署(deploy) Rails web 時,多半會使用 Capistrano 之類的工具,或是自己手動用版本控制工具(如:svn),這樣都會在 server 上留下 .svn/ 的目錄,要是有心人士去 access 這些目錄,你的 web 就被看光光啦!所以可以在 .htaccess 或其它存取控制的設定中,把 .svn/ 這個目錄給 deny 掉。

  • Cookie Session storage

    這個部份其實是告訴你,Rails 預設處理 session 的方式沒有很安全,所以重要的資訊千萬不可以放在 session 裡面,也因為大家都可以從 Rails source 中看出 session 是怎麼算出來的,而且 Rails 2.0 預設又是把 session 存在 cookie 裡面,有心的人就可以偽裝 session data 來進行攻擊。

    所以,要嘛就在 application.rb 設一個強度較強的 secret_key,不然就是每個一段時間就 invalidate session 資料,再不然就是使用別的方式來處理 session。

  • Cross-Site Scripting(XSS)

    這個應該已經是老梗了,不過講者還是提醒大家要記得用 h() 來過濾掉使用者輸入的 HTML code。如果你容易忘掉使用 h() 的話,那就為你的 Rails web 安裝一個 safe_erb 的 plugin 吧!它會在你沒有把 HTML 內容 escape 掉時丟出 exception。

    如果你非得讓使用者輸入一些格式化的內容(比方說文字編輯),那就使用 sanitize() 來作黑名單或白名單吧

  • Session Fixation

    這裡是要提醒你,當使用者登入或登出時,別忘了使用 reset_session 以避免有不同的使用者用到了相同的 session id。

  • Cross-Site Request Forgery (CSRF)

    這個攻擊主要是偽造 request 來進行攻擊,不過從 Rails 2.0 開始增加了 protect_from_forgery 的選項,也就是會針對每個 request 作 auth_token 的檢查,只有依循「正常管道」的 request 才會被接受處理。不過這個防護只保護 POST request,所以你得自己確保 GET request 不會有威脅。(可以用 request.post? 來檢查)

  • SQL injection, JavaScript hijacking

    都很老梗,不用多介紹了。

  • Mass Assignment

    這部份是說,Rails 裡用 ActiveRecord 的 instance 來表示一筆資料庫 record,而對這個 obj 成員變數作 assignment 就相當於去改變這個 record 的值,不過這些成員變數預設都是 public accessible 的,如果裡面有一些重要的欄位,可能會不小心被人家修改到。如:你提供了一個 /user/update 的 action,然後被攻擊者偷帶一些參數試圖修改,這就不太妙了。

    所以講者希望在使用 AR 時,能利用 attr_protected 來對成員變數的存取控制做一些管理。

  • 另外講者還有提到 DoS (Denial of Service) 攻擊的問題,不過這個與 Rails 本身不太有關係,所以留給大家自己去看囉 :p
  • vargo

    good suggestion… 😀

  • Really good! 🙂