不可忽視的前端安全問題——XSS攻擊

XSS是什麼

XSS是跨站腳本攻擊(Cross-Site Scripting)的簡稱。javascript

XSS是一種注入腳本式攻擊,攻擊者利用如提交表單、發佈評論等方式將事先準備好的惡意腳本注入到那些良性可信的網站中,當其餘用戶進入該網站後,腳本就在用戶不知情的狀況下偷偷地執行了,這樣的腳本可能會竊取用戶的信息、修改頁面內容、或者僞造用戶執行其餘操做等等,後果不可估量。php

XSS攻擊一般會發生在如下狀況下:
html

  • 向一個web app中輸入含有一些不良代碼的內容,一般是一段含有http請求的代碼
  • 這些內容包含在發給其餘用戶的動態內容之中,並且這些內容尚未通過校驗

發送到Web瀏覽器的惡意內容一般採用JavaScript代碼片斷的形式,但也可能包括HTML,Flash或瀏覽器可能執行的任何其餘類型的代碼。 基於XSS的攻擊方式幾乎是無限的。可是它們一般的方式是:前端

  • 向攻擊者發送包括諸如cookie或其餘會話信息的私有數據
  • 攻擊者篡改頁面的內容
  • 在用戶的機器上,以含有漏洞的網站爲幌子,執行其餘惡意操做

OWASP(Open Web Application Security Project)最新公佈的2017 10項最嚴重的 Web 應用程序安全風險中,XSS榜上有名。
java


而事實上,XSS在每次的TOP10評比中都會出現……
angularjs


XSS實例

想知道XSS是如何形成攻擊的?能夠看這個下面的文章,它介紹了一個XSS漏洞——XSS跨站腳本攻擊過程最簡單演示 - CSDN博客 案例中攻擊者利用XSS能夠獲取用戶的隱私信息。golang

XSS攻擊的分類

通常會把XSS分爲兩類——存儲型XSS(Stored XSS)和反射型XSS(Reflected XSS)web

不過還有一種鮮爲人知的類型——DOM-based XSS。數據庫


存儲型XSS是指那些將惡意腳本永久的保存在目標服務器上的攻擊方式,如存儲在數據庫、消息論壇、訪問日誌、評論內容扥等。express

反射型XSS是當用戶點擊一個惡意連接,或者提交一個表單,或者進入一個惡意網站時,注入腳本進入被攻擊者的網站。Web服務器將注入腳本,好比一個錯誤信息,搜索結果等 返回到用戶的瀏覽器上。瀏覽器會執行這段腳本,由於,它認爲這個響應來自可信任的服務器。一個危險的XSS案例--輕鬆拿到登陸用戶的cookie - CSDN博客,這個例子中,若是有人誘導你點擊了上面文章中寫到的連接,那麼你在站酷網站中的隱私信息就發送到了其餘服務器中了。


DOM-Based型XSS是指攻擊者利用原生JavaScript代碼篡改客戶端的DOM結構,致使用戶操做執行了「意外」的動做。

關於DOM-Based型XSS能夠看下面的例子

下面是一段網站的代碼,它提供一個下拉框讓你來選擇語言,並且還根據你URL上的default參數來進行默認語言的推薦。

Select your language:

<select><script>

document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");

document.write("<OPTION value=2>English</OPTION>");

</script></select>
…複製代碼

一般狀況下,這個頁面的地址會是下面的樣子:

http://www.some.site/page.html?default=French複製代碼

而DOM-Based型XSS會利用這個頁面DOM結構的漏洞,向受害者發送下面的連接

http://www.some.site/page.html?default=<script>alert(document.cookie)</script>複製代碼

當受害者點開這個連接時,就會將用戶的cookie所有alert出來了。


XSS的防範原則

關於XSS攻擊的防範,我在OWASP上給出防範方法進行了精簡,若是你有興趣的話,能夠去看詳細內容

原則0——永遠不要把不受信任的數據插入到本來容許JavaScript能夠放置的地方

就像下面的代碼中所示的那樣:

<script>...永遠不要把不受信任的數據放在這...</script>   直接放在script標籤內
 
 <!--...永遠不要把不受信任的數據放在這...-->             放在HTML註釋內
 
 <div ...永遠不要把不受信任的數據放在這...=test />       作爲一個屬性名
 
 <永遠不要把不受信任的數據放在這... href="/test" />   作爲一個標籤名
 
 <style>...永遠不要把不受信任的數據放在這...</style>   直接放在style標籤內複製代碼

原則1——在向元素中插入不受信任的HTML代碼以前必定要進行轉義

就像下面的代碼中所示的那樣:

<body>...將不受信任的數據轉義後再放在這...</body>
 
 <div>...將不受信任的數據轉義後再放在這...</div>
 
 any other normal HTML elements複製代碼

經常使用的轉義規則以下:

& --> &amp;
 < --> &lt;
 > --> &gt;
 " --> &quot; ' --> &#x27; / --> &#x2F;複製代碼

原則2——在向元素的屬性插入不受信任的HTML代碼以前必定要進行轉義

看下面的代碼:

<div attr=...將不受信任的數據轉義後再放在這...>content</div>  
在沒有加引號的屬性值內
 
 <div attr='...將不受信任的數據轉義後再放在這...'>content</div>
在加了單引號的屬性值內

<div attr="...將不受信任的數據轉義後再放在這...">content</div>
在加了雙引號的屬性值內複製代碼

原則3——在用不受信任的數據向JavaScript代碼賦值前,必定要進行轉義

看下面的代碼:

<script>alert('...將不受信任的數據轉義後再放在這...')</script>     
在一個字符串以內
 
 <script>x='...將不受信任的數據轉義後再放在這...'</script> 
在表達式的一側
 
 <div onmouseover="x='...將不受信任的數據轉義後再放在這...'"</div>  
在事件處理函數內複製代碼

須要注意的是,有一些JavaScript函數永遠沒法安全的使用不受信任的數據做爲輸入,好比下面的代碼:

<script>
 window.setInterval('即便你作了轉義,可是仍然可能被XSS攻擊');
 </script>複製代碼


原則3.1——在HTML的上下文中對JSON值進行轉義,並用JSON.parse()方法來讀取值

必定要確保http response中的頭部信息的content-type爲application/json,而不是text/html,由於那樣的話,極可能會被人利用進行XSS攻擊。


一個壞的案例:

HTTP/1.1 200
   Date: Wed, 06 Feb 2013 10:28:54 GMT
   Server: Microsoft-IIS/7.5....
   Content-Type: text/html; charset=utf-8 <-- bad
   ....
   Content-Length: 373
   Keep-Alive: timeout=5, max=100
   Connection: Keep-Alive
   {"Message":"No HTTP resource was found that matches the request URI 'dev.net.ie/api/pay/.html?HouseNumber=9&AddressLine =The+Gardens<script>alert(1)</script>&AddressLine2=foxlodge+woods&TownName=Meath'.","MessageDetail":"No type was found that matches the controller named 'pay'."}   <-- 這裏script標籤有可能會被執行複製代碼

一個好的案例:

HTTP/1.1 200
   Date: Wed, 06 Feb 2013 10:28:54 GMT
   Server: Microsoft-IIS/7.5....
   Content-Type: application/json; charset=utf-8 <--good
   .....
   .....複製代碼


原則4——在將不受信任的數據做爲CSS屬性插入到文檔以前必定要進行轉義

看下面的代碼

<style>selector { property : ...將不受信任的數據轉義後再放在這...; } </style> 
屬性值

 <style>selector { property : "...將不受信任的數據轉義後再放在這..."; } </style>
屬性值

 <span style="property : ...將不受信任的數據轉義後再放在這...">text</span> 
屬性值複製代碼

須要注意的是,仍是有一些CSS屬性值對於「不受信任的」數據是沒法確保萬無一失的——即便作了轉義,以下面的兩個CSS屬性:

{ background-url : "javascript:alert(1)"; }  
 { text-size: "expression(alert('XSS'))"; }   // only in IE複製代碼

你應該確保全部CSS屬性值引入的外部連接是由「http」開頭的,而不是「javascript」開頭的。


原則5——在向HTML的URL參數插入將不受信任的數據前,必定要將進行轉義

看下面的代碼

<a href="http://www.somesite.com?test=...將不受信任的數據轉義後再放在這...">link</a >複製代碼


加分原則1——對於cookie使用httpOnly標識

使用httpOnly標識後的cookie JavaScript是沒法獲取的,又因爲cookie是基於同源原則,因此必定程度上會防範那些利用客戶cookie的XSS攻擊。


加分原則2——在http header中使用Content Security Policy

利用http header中的屬性值Content-Security-Policy來防範XSS。HTTP 響應頭 Content-Security-Policy 容許站點管理者在指定的頁面控制用戶代理的資源。除了少數例外,這條政策將極大地指定服務源 以及腳本端點。


加分原則3——使用自動轉義模板系統

許多Web應用程序框架提供了自動的上下文轉義功能,如AngularJS嚴格的上下文轉義Go模板。 儘量使用這些技術。


加分原則4——在http header中使用X-XXS-Protection

HTTP X-XSS-Protection 響應頭是Internet Explorer,Chrome和Safari的一個功能,當檢測到跨站腳本攻擊 (XSS)時,瀏覽器將中止加載頁面。雖然這些保護在現代瀏覽器中基本上是沒必要要的,當網站實施一個強大的Content-Security-Policy來禁用內聯的JavaScript ('unsafe-inline')時, 他們仍然能夠爲尚不支持 CSP 的舊版瀏覽器的用戶提供保護。



總結

XSS攻擊的後果是不可估量的,而每每他又是容易被人忽視的。結合上面提到的幾點,檢查一下本身的Web App是否有上面的漏洞。

若是你堅持將全文都看完,你必定深愛着前端技術,那我以爲你有必要關注一下個人公衆號——較真的前端,在那裏會有更多的技術分享和前端乾貨等着你。


參考文章:
8大前端安全問題(上) - ThoughtWorks洞見 
Cross-site Scripting (XSS) 
XSS (Cross Site Scripting) Prevention Cheat Sheet
相關文章
相關標籤/搜索