上次我們談過 XSS 的資安議題,現在我們再來看一下網站可能還會有什麼資安隱憂的問題吧

Cross-site scripting - XSS 跨站腳本攻擊

中文叫跨網站攻擊,攻擊者把程式注入到某個地方(可能是網頁上或是資料庫裡面)讓其他使用者打開網頁時,執行這段程式。
因為是執行腳本語言,所以你想像到的任何事情,幾乎都可能會發生。
例如:使用者資訊, cookie, sessionID, 攝像頭……。

操作手法

腳本語言的斷詞斷句

1
https://placeimgxxx.com/320/320/any" onerror="alert('xss injection')

預防方式

沒有 100%預防的最佳解,但是至少常見的資安議題要做到確實的預防

OWASP

OWASP 有列出幾個常見的手段,同時也有提供 JAVA 一些轉譯的範例,都列在這裡了

消毒器(Sanitizer)

透過消毒可以盡可能的排除讓比較敏感或是可能影響腳本語言執行與預期不同結果的問題發生。
我們可以用別人設計好的套件來使用,或是自己設計一個 escapeHTML 來過濾敏感字元。
消毒盡量從源頭開始做起,否則後面真的儲存到資料庫後,會變得很麻煩。

  1. 特殊字元

如果沒有做消毒就把資料直接放到 HTML 上,可能會發生各種狀況:

1
2
3
4
5
6
<div>
執行結果:">
<script>
alert("XSS");
</script>
</div>

所以我們會先把敏感字源過濾掉,再放到 HTML 上:

1
2
3
4
5
6
&	&amp;
< &lt;
> &gt;
" &quot;
' &#x27;
/ &#x2F;
  1. 前綴語法

javascript:也是敏感語法

1
<a href="javascript:alert(&#x27;XSS&#x27;)">redirect</a>

避免使用有資安隱憂的功能

使用特殊語法需要多注意:.innerHTML、.outerHTML、document.write
Vue/React 需多注意:dangerouslyInnerSetHTML, v-html

以 React 的 dangerouslySetInnerHTML 來說
因為在 React 無法使用 innerHTML,主要是為了開發者寫出有資安隱憂的程式,因為只要是注入 script 都是不安全的行為。
因此提供 dangerouslySetInnerHTML 給開發者使用

套用 coding style 規範

有些 coding style 會提供 XSS 隱憂的檢查,不過這些只能防範較明顯的問題
只要是從資料庫取出來或是輸入的欄位,都需要特別注意

Cross Site Request Forgery - CSRF 跨站請求偽造

有些人會把 XSS 和 CSRF 搞混,沒關係,我教你怎麼區分,把開頭的 CS 都去掉

XSS -> Scripting
CSRF -> Request Forgery

這樣看就不會搞混了,一個是腳本語言,一個是請求偽造。
因為是請求偽造,所以被視為送出非預期的請求

原理

這個攻擊手法的出現主要是因為 Cookie 基於某些規範而無法取得,但是我們可以用一些手段騙取對方來讓本人直接做動作。

  1. Session cookie 時效性
    他會在 Session 區間內持有,直到瀏覽器關閉
  2. Permanent cookie 長久性
    可以設定到期日或是有效期間

範例:
res.setHeader(‘Set-Cookie’, [‘mycookie=222’, ‘test=3333; expires=Sat, 21 Jul 2018 00:00:00 GMT;’]);

mycookie 為 session cookie,不同瀏覽器的到期日會不同
test 為 Permanent cookie

情境

假設有一個人登入一個社群網站:www.example.com
可以透過這個請求刪除文章:www.example.com/post/delete/:id

使用者登入會設置以下 cookie
res.setHeader(‘Set-Cookie’, [‘user=user123; expires=Sat, 21 Jul 2018 00:00:00 GMT;’]);

然後使用者無意間造訪了這個網站:

1
2
<p>CSRF攻擊的網站:</p>
<img src="http://www.example.com/post/delete/87343" />

因為是把請求放到 img,所以造訪就算是執行這段請求了
在這整個攻擊的過程中,攻擊者只是做鋪路(設陷阱)的動作,完全沒有參與攻擊過程
這完全都是受害者無意間讓自己陷入危機所做的操作

預防方式

  1. 驗證碼
    這也是為什麼很多網站會做二次確認的彈出視窗或是驗證碼,主要是為了驗證這是本人的行為。
    不過儘管有這個功能,也還是不夠嚴謹。

  2. Referer 檢查
    在 http 的 header 上有 Referer,檢查這個來源是否合法

1
2
3
4
if (req.headers.referer !== "http://www.example2.com/") {
// 不明的請求
return;
}
  1. 加入 token 驗證
    如果我們可以製造一個外人無法掌握的隨機參數,那麼就可以預防 SCRF 了。
    當我們發送 http request 的時候,將 隨機產生的 token 夾帶在上面,並且在 server 進行二次驗證 token
    這樣就可以避免無意間使用到不明請求的狀況了。

  2. 不要去來歷不明的網站
    乖小孩還是不要亂跑比較好