Leon's Blogging

Coding blogging for hackers.

常見的安全漏洞與攻擊

| Comments

這次來看一下目前常見的一些攻擊手段!

SQL Injection 注入攻擊

  • 發生在應用程式與資料庫之間的安全漏洞
  • 主要是透過輸入的字串中夾帶 SQL 語法,例如 drop table; 等等,如果程式並沒有針對這些去檢查的話,會被當成正常指令而去執行

Example

User.where("name = '#{params[:name]}'")

輸入

# 將後面的語法用 -- sql 的註解,註解掉
hi'; DROP TABLE users; --

就會變成

# 後面 drop 就會將 users 的 table 整個刪除
SELECT * FROM users WHERE name = 'hi'; DROP TABLE users; --’

原因在於,直接將 params[:name] 帶入語法裡,沒做任何檢查導致

User.where("name = '#{params[:name]}'")

解決方法,主要是要將特殊字元做處理,稱作 字元逸出 Escape Character

# 字元逸出 Escape Character
ActiveRecord::Base::connection.quote_string("hi'; DROP TABLE users; --")

# rails auto escape character
User.where("name = ?", params[:name])

XSS(Cross-Site Scripting) 跨站腳本攻擊

  • 網頁應用程式的安全漏洞
  • XSS 允許惡意使用者將程式碼注入到網頁上,讓其他使用者在瀏覽該網頁時自動觸發注入的程式碼
  • JavaScript 很常被用來進行 XSS 攻擊
  • 只要網站可以輸入資料,都要小心

Example

# 將此語法貼入在輸入欄位上,若是沒有特別處理,每次進來都會跳出 Hack you!
# 更嚴重會將敏感資料例如 cookie 內容傳給攻擊者
<script>alert("Hack you!");</script>

解決方法,也是要將特殊字元做處理,稱作 字元逸出 Escape Character

&lt;script&gt;alert(&quot;Hack you!&quot;);&lt;/script&gt;
# < 變成 &lt , " 變成 &quot;

在 rails 當中會造成 XSS 主要是使用了 html_safe raw,否則 rails 會自動做字元逸出,除非很確定資料是安全的(但千萬別相信外面的使用者)

"<p>safe</p>".html_safe
raw(comment)

但有時還是必須讓使用者輸入一些部分 html tag 之類的可以使用 sanitize

# sanitize 允許部分 HTML,rails 以建立一些白名單 tag
sanitize("<p>safe</p>")

查詢開放名單

ActionView::Base.sanitized_allowed_tags
 => #<Set: {"strong", "em", "b", "i", "p", "code", "pre", "tt", "samp", "kbd", "var", "sub", "sup", "dfn", "cite", "big", "small", "address", "hr", "br", "div", "span", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "li", "dl", "dt", "dd", "abbr", "acronym", "a", "img", "blockquote", "del", "ins"}>

 ActionView::Base.sanitized_allowed_attributes
 => #<Set: {"href", "src", "width", "height", "alt", "cite", "datetime", "title", "class", "name", "xml:lang", "abbr"}>

也可以自行新增白名單

# config/application.rb
config.action_view.sanitized_allowed_tags = ['strong', 'em', 'a']
config.action_view.sanitized_allowed_attributes = ['href', 'title']

另外特別提到,有時候會需要讓使用者輸入 js 語法,這時候可以用到,主要會將一些語法做跳脫

escape_javascript(js) 也能寫成 j(js)

# '\\'   => '\\\\'
# "</"   => '<\/'
# "\r\n" => '\n'
# "\n"   => '\n'
# "\r"   => '\n'
# '"'    => '\\"'
# "'"    => "\\'"

CSRF(Cross-site request forgery) 跨站偽造請求

  • 利用使用者身份驗證的一個安全漏洞
  • 攻擊者透過技術,利用別人的權限去執行網站上的操作,由於瀏覽器被認證過,被訪問的網站會認為是真正的使用者在操作。
  • 簡單的身份驗證只能確保請求發自某個使用者的瀏覽器,無法保證該請求發自使用者本身。

Example

GET 攻擊 - 當有權限的使用者讀到這個 img,自動會發送 get action 去執行

<img src="/posts/delete_all">

解決方式 - 將 route 改成用 POST,會修改或刪除到資料的,則要用POST、PATCH/PUT或DELETE

POST 攻擊

# 處理完請求的網頁伺服器會丟回應給 form,導致頁面跳轉,這樣會讓使用者察覺到自己觸發了 CSRF 陷阱,因此加上 <iframe> 作為 <form> 的 target ,將回應放入 <iframe> 隱藏起來,跳轉頁面就不會發生
<iframe style="display:none" name="csrf-frame"></iframe>

# 透過 form 發出 POST 請求
<form method='POST' action='http://localhost:3000/posts/delete_all' target="csrf-frame" id="csrf-form">
  <input type='submit' value='submit'>
</form>

# 讓使用者載入完網頁後自動觸發 submit ,但對某些瀏覽器無效
<script>document.getElementById("csrf-form").submit()</script>

解決方式 - 所有 POST 操作加上額外的驗證碼,確保使用者是透過含有驗證碼的網站表單發送請求,而不是不小心觸發了 CSRF 攻擊

Rails 內建表單 CSRF 防禦

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end

設定後表單會自帶 token,如果發過來的 POST 沒有帶此 token 就會跳出ActionController:InvalidAuthenticityToken 的錯誤訊息

<input type="hidden" name="authenticity_token" value="cuI+ljBAcBxcEkv4pbeqLTEnRUb9mUYMgfpkwOtoyiA=">

Rails 也內建了防禦來自其他網站的 AJAX 請求的機制

<%= csrf_meta_tags %>
# 在前端產生 csrf_token 的安全驗證碼供 JavaScript 取用。

Mass Assignment 大量賦值

  • Rails專屬,因為太方便而造成的安全性議題
  • 透過更改 html 上面的屬性,進而更改想要改變的欄位
# rails 後面直接接一個 hash 就可以做新增更新的動作
User.create( { name: "Leon", :comment => "hi" } )
User.update( { name: "Leon", :comment => "hi" } )

因此透過這個形式,將 html 上面的 name 改成 role,在帶 admin 的值過去

{ role: admin }

這樣就會被更新到

解決方法是,rails 內建 Strong Parameter

# 只允許 user 裡面的 name 和 comment parasm 其他都不接受,否則會跳出 Unpermitted parameter: role
params.require(:user).permit(:name, :comment)

DoS (Denial of Service)阻斷服務攻擊/DDoS (Distrubuted Denial of Service) 分散阻斷服務攻擊

  • DoS 透過發送大量請求讓伺服器處於忙碌甚至癱瘓的狀態,以至於無法服務正常的使用者
  • DDoS 以分散的方式從不同來源(Source)對一個伺服器進行 DoS 攻擊

Example

安裝 wrk 來模擬

brew install wrk
# 30秒內 12個thread 400 個 connect
wrk -t12 -c400 -d30s http://localhost:3000/

防禦 DoS / DDoS

  • DoS 並非因漏洞而產生,因此不好防禦
  • 辨識出對方進攻管道進行封鎖,如鎖對方 IP
  • DDoS 利用不同位置進行攻擊,來源 IP 不只有一個,很難判斷出攻擊者
  • 透過辨識短時間內,大量攻擊者,就直接鎖住 IP 來防禦(限制每個 IP 位置在一分鐘內不得送出超過 100 個請求 rack-attack gem)
  • 如果真面臨了大量 DDoS 攻擊,那就不是 Rails 應用層級可以解決的問題,必須購買專門的防火牆和硬體設備。

Comments