Try   HackMD

網頁安全(Network Security)

何謂CORS?

何謂CSRF(Cross Site Request Forgery)?

我們知道大部分的網站應用都是採用cookie或session的方式進行登入驗證,當通過登入驗證之後,網站就會給你一個通行證存在cookie或seesion中,代表之後的動作中都不需要重複驗證身分了。這當然是一個好事,沒有人能接受做每一件事都要再輸入一次帳號密碼,但CSRF的攻擊正是鑽了這個機制的漏洞來達到攻擊的目的!

實際舉例

我們可以想像cookies就像是每個人身上的筆記本,當你在A銀行登入之後,A銀行在你的筆記本上蓋了個印章,有這個印章之後,接下來三個小時內你的所有動作都不需要重複驗證身分。但你在這三小時內又跑去逛了其他網頁,很不巧的就逛到了駭客B架設的惡意網頁,這個惡意網頁偷偷複製了你的cookie筆記本的印章,跑去打A銀行的轉帳API,請A銀行把你的存款匯10萬元到駭客B自己的帳戶,由於A銀行認印章不認人,所以就接受了這筆匯款請求。

如何防範?

普遍防禦CSRF的方法有兩種:

檢查referer欄位

這個方法很簡單,既然攻擊是來自於非銀行網站,那我就確認需求的來源就行了,而http協定中就有一個referer欄位記錄著這個請求是從哪個網站發出來的,只要不是銀行網站發出來的請求,網站這邊一律不接受!
依照這樣的方式,我們可以用快速且低成本的方式來防範CSRF,只是有個問題,就是駭客能否偽造這個referer欄位呢? 如果他也可以偽裝成銀行來源,那用戶就還是會被攻擊。顯然這種方法只能初步防禦CSRF,碰到進階一點的攻擊手法就會再度被破解。

加入驗證token

CSRF的核心概念,就是銀行不知道發出請求的人是不是攻擊者,那按照這個思路,只要使用者能提出一個唯一且保密的序號,攻擊者拿不到這個序號,自然就不能偽裝成使用者,而這個序號,就是我們稱的CSRF Token,這個Token是由銀行server產生,並且加密存在session中的,其他人無法仿造,只有透過server給使用者,並在一定時間內刷新。當使用者想做任何交易的時候,銀行server就會請使用者提供CSRF Token,如果不能提供,就代表這次的請求就是攻擊者,那銀行server就不予理會。

結論

CSRF在前幾年都算是非常熱門的攻擊手法, 在OWASP攻擊排名中屢屢上榜,但也因為比較熱門的關係,在諸多開發框架中都已經內建了CSRF的防禦機制,所以慢慢的這種攻擊就有比較退燒的趨勢,但在設計網頁功能時仍需確定設計時有開啟CSRF防護,不然因為一時大意被攻擊可就得不償失了。

XSS?

XSS攻擊通常指的是通過利用網頁開發時留下的漏洞,通過巧妙的方法注入惡意指令代碼到網頁,使用戶載入並執行攻擊者惡意製造的網頁程式。這些惡意網頁程式通常是JavaScript,但實際上也可以包括JavaVBScriptActiveXFlash或者甚至是普通的HTML。攻擊成功後,攻擊者可能得到更高的權限(如執行一些操作)、私密網頁內容、對談cookie等各種內容。

過濾特殊字元

避免XSS的方法之一主要是將使用者所提供的內容進行過濾,許多語言都有提供對HTML的過濾:

使用HTTP頭指定類型

很多時候可以使用HTTP頭指定內容的類型,使得輸出的內容避免被作為HTML解析。如在PHP語言中使用以下代碼:

<?php
   header('Content-Type: text/javascript; charset=utf-8');
?>

即可強行指定輸出內容為文字/JavaScript指令碼(順便指定了內容編碼),而非可以引發攻擊的HTML。

Reference:
https://hitcon.org/2015/CMT/download/day1-a-r4.pdf

SQL Injection?

是發生於應用程式之資料庫層的安全漏洞。簡而言之,是在輸入的字串之中夾帶SQL指令,在設計不良的程式當中忽略了檢查,那麼這些夾帶進去的指令就會被資料庫伺服器誤認為是正常的SQL指令而執行,因此遭到破壞或是入侵

一個有會員登入功能的網站,都會需要輸入帳號與密碼來進行驗證

而後端程式,如 PHP 就必需支援相關的登入檢查,判定 User 輸入的帳號、密碼是否正確,來確定登入是否成功 ,PHP 執行的 SQL 語法如下,這是一個簡單的 SQL 語法,主要功能是從 members 這個資料表中,取出符合 User 所輸入帳號與密碼的會員資料。

select * from members where account=$name and password='$password'

但若是駭客輸入有特殊字元的帳號:「 '' or 1=1 /* 」,密碼:「任意值」

這時SQL語法就會變成:

select * from members where _account="" or 1=1 /*_' and password=''

因為「/*」在 MySQL 語法中代表註解的意思,所以「/*」後面的字串通通沒有執行,而這句判斷式「1=1」永遠成立,駭客就能登入此網站成功。

Reference:
https://zh.wikipedia.org/zh-tw/SQL資料隱碼攻擊
https://www.puritys.me/docs-blog/article-11-SQL-Injection-常見的駭客攻擊方式.html