自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

防御XSS攻擊的七條原則

安全 應(yīng)用安全
本文將會(huì)著重介紹防御XSS攻擊的一些原則,需要讀者對(duì)于XSS有所了解,至少知道XSS漏洞的基本原理。

本文將會(huì)著重介紹防御XSS攻擊的一些原則,需要讀者對(duì)于XSS有所了解,至少知道XSS漏洞的基本原理,如果您對(duì)此不是特別清楚,請(qǐng)參考這兩篇文章:《Stored and Reflected XSS Attack》《DOM Based XSS

攻擊者可以利用XSS漏洞向用戶發(fā)送攻擊腳本,而用戶的瀏覽器因?yàn)闆](méi)有辦法知道這段腳本是不可信的,所以依然會(huì)執(zhí)行它。對(duì)于瀏覽器而言,它認(rèn)為這段腳本是來(lái)自可以信任的服務(wù)器的,所以腳本可以光明正大地訪問(wèn)Cookie,或者保存在瀏覽器里被當(dāng)前網(wǎng)站所用的敏感信息,甚至可以知道用戶電腦安裝了哪些軟件。這些腳本還可以改寫(xiě)HTML頁(yè)面,進(jìn)行釣魚(yú)攻擊。

雖然產(chǎn)生XSS漏洞的原因各種各樣,對(duì)于漏洞的利用也是花樣百出,但是如果我們遵循本文提到防御原則,我們依然可以做到防止XSS攻擊的發(fā)生。

有人可能會(huì)問(wèn),防御XSS的核心不就是在輸出不可信數(shù)據(jù)的時(shí)候進(jìn)行編碼,而現(xiàn)如今流行的Web框架(比如Rails)大多都在默認(rèn)情況下就對(duì)不可信數(shù)據(jù)進(jìn)行了HTML編碼,幫我們做了防御,還用得著我們自己再花時(shí)間研究如何防御XSS嗎?答案是肯定的,對(duì)于將要放置到HTML頁(yè)面body里的不可信數(shù)據(jù),進(jìn)行HTML編碼已經(jīng)足夠防御XSS攻擊了,甚至將HTML編碼后的數(shù)據(jù)放到HTML標(biāo)簽(TAG)的屬性(attribute)里也不會(huì)產(chǎn)生XSS漏洞(但前提是這些屬性都正確使用了引號(hào)),但是,如果你將HTML編碼后的數(shù)據(jù)放到了。

<script>…不要在這里直接插入不可信數(shù)據(jù)…</script>直接插入到SCRIPT標(biāo)簽里
<!– …不要在這里直接插入不可信數(shù)據(jù)… –>
插入到HTML注釋里

<div 不要在這里直接插入不可信數(shù)據(jù)=”…”></div>
插入到HTML標(biāo)簽的屬性名里

<div name=”…不要在這里直接插入不可信數(shù)據(jù)…”></div>
插入到HTML標(biāo)簽的屬性值里

<不要在這里直接插入不可信數(shù)據(jù) href=”…”></a>
作為HTML標(biāo)簽的名字

<style>…不要在這里直接插入不可信數(shù)據(jù)…</style>
直接插入到CSS里

最重要的是,千萬(wàn)不要引入任何不可信的第三方JavaScript到頁(yè)面里,一旦引入了,這些腳本就能夠操縱你的HTML頁(yè)面,竊取敏感信息或者發(fā)起釣魚(yú)攻擊等等。

原則2:在將不可信數(shù)據(jù)插入到HTML標(biāo)簽之間時(shí),對(duì)這些數(shù)據(jù)進(jìn)行HTML Entity編碼

在這里相當(dāng)強(qiáng)調(diào)是往HTML標(biāo)簽之間插入不可信數(shù)據(jù),以區(qū)別于往HTML標(biāo)簽屬性部分插入不可信數(shù)據(jù),因?yàn)檫@兩者需要進(jìn)行不同類(lèi)型的編碼。當(dāng)你確實(shí)需要往HTML標(biāo)簽之間插入不可信數(shù)據(jù)的時(shí)候,首先要做的就是對(duì)不可信數(shù)據(jù)進(jìn)行HTML Entity編碼。比如,我們經(jīng)常需要往DIV,P,TD這些標(biāo)簽里放入一些用戶提交的數(shù)據(jù),這些數(shù)據(jù)是不可信的,需要對(duì)它們進(jìn)行HTML Entity編碼。很多Web框架都提供了HTML Entity編碼的函數(shù),我們只需要調(diào)用這些函數(shù)就好,而有些Web框架似乎更“智能”,比如Rails,它能在默認(rèn)情況下對(duì)所有插入到HTML頁(yè)面的數(shù)據(jù)進(jìn)行HTML Entity編碼,盡管不能完全防御XSS,但著實(shí)減輕了開(kāi)發(fā)人員的負(fù)擔(dān)。

<body>…插入不可信數(shù)據(jù)前,對(duì)其進(jìn)行HTML Entity編碼…</body>
<div>…插入不可信數(shù)據(jù)前,對(duì)其進(jìn)行HTML Entity編碼…</div>
<p>…插入不可信數(shù)據(jù)前,對(duì)其進(jìn)行HTML Entity編碼…</p>
以此類(lèi)推,往其他HTML標(biāo)簽之間插入不可信數(shù)據(jù)前,對(duì)其進(jìn)行HTML Entity編碼

[編碼規(guī)則]

那么HTML Entity編碼具體應(yīng)該做哪些事情呢?它需要對(duì)下面這6個(gè)特殊字符進(jìn)行編碼:

&     –>     &amp;
<     –>     &lt;
>     –>     &gt;
”     –>     &quot;
‘     –>     &#x27;
/     –>     &#x2f;

有兩點(diǎn)需要特別說(shuō)明的是:

不推薦將單引號(hào)( ‘ )編碼為 &apos; 因?yàn)樗⒉皇菢?biāo)準(zhǔn)的HTML標(biāo)簽

需要對(duì)斜杠號(hào)( / )編碼,因?yàn)樵谶M(jìn)行XSS攻擊時(shí),斜杠號(hào)對(duì)于關(guān)閉當(dāng)前HTML標(biāo)簽非常有用

推薦使用OWASP提供的ESAPI函數(shù)庫(kù),它提供了一系列非常嚴(yán)格的用于進(jìn)行各種安全編碼的函數(shù)。在當(dāng)前這個(gè)例子里,你可以使用:

String encodedContent = 
ESAPI.encoder().encodeForHTML(request.getParameter(“input”));

原則3:在將不可信數(shù)據(jù)插入到HTML屬性里時(shí),對(duì)這些數(shù)據(jù)進(jìn)行HTML屬性編碼

這條原則是指,當(dāng)你要往HTML屬性(例如width、name、value屬性)的值部分(data value)插入不可信數(shù)據(jù)的時(shí)候,應(yīng)該對(duì)數(shù)據(jù)進(jìn)行HTML屬性編碼。不過(guò)需要注意的是,當(dāng)要往HTML標(biāo)簽的事件處理屬性(例如onmouseover)里插入數(shù)據(jù)的時(shí)候,本條原則不適用,應(yīng)該用下面介紹的原則4對(duì)其進(jìn)行JavaScript編碼。

<div attr=…插入不可信數(shù)據(jù)前,進(jìn)行HTML屬性編碼…></div>屬性值部分沒(méi)有使用引號(hào),不推薦
<div attr=’…插入不可信數(shù)據(jù)前,進(jìn)行HTML屬性編碼…’></div>
屬性值部分使用了單引號(hào)
<div attr=”…插入不可信數(shù)據(jù)前,進(jìn)行HTML屬性編碼…”></div>
屬性值部分使用了雙引號(hào)

[編碼規(guī)則]

除了阿拉伯?dāng)?shù)字和字母,對(duì)其他所有的字符進(jìn)行編碼,只要該字符的ASCII碼小于256。編碼后輸出的格式為 &#xHH; (以&#x開(kāi)頭,HH則是指該字符對(duì)應(yīng)的十六進(jìn)制數(shù)字,分號(hào)作為結(jié)束符)

之所以編碼規(guī)則如此嚴(yán)格,是因?yàn)殚_(kāi)發(fā)者有時(shí)會(huì)忘記給屬性的值部分加上引號(hào)。如果屬性值部分沒(méi)有使用引號(hào)的話,攻擊者很容易就能閉合掉當(dāng)前屬性,隨后即可插入攻擊腳本。例如,如果屬性沒(méi)有使用引號(hào),又沒(méi)有對(duì)數(shù)據(jù)進(jìn)行嚴(yán)格編碼,那么一個(gè)空格符就可以閉合掉當(dāng)前屬性。請(qǐng)看下面這個(gè)攻擊:

假設(shè)HTML代碼是這樣的: 

…content… 

攻擊者可以構(gòu)造這樣的輸入:

x onmouseover=”javascript:alert(/xss/)”

最后,在用戶的瀏覽器里的最終HTML代碼會(huì)變成這個(gè)樣子: 

…content…

 只要用戶的鼠標(biāo)移動(dòng)到這個(gè)DIV上,就會(huì)觸發(fā)攻擊者寫(xiě)好的攻擊腳本。在這個(gè)例子里,腳本僅僅彈出一個(gè)警告框,除了惡作劇一下也沒(méi)有太多的危害,但是在真實(shí)的攻擊中,攻擊者會(huì)使用更加具有破壞力的腳本,例如下面這個(gè)竊取用戶cookie的XSS攻擊:

x />

除了空格符可以閉合當(dāng)前屬性外,這些符號(hào)也可以:

% * + , – / ; < = > ^ | `(反單引號(hào),IE會(huì)認(rèn)為它是單引號(hào))

可以使用ESAPI提供的函數(shù)進(jìn)行HTML屬性編碼:

String encodedContent = ESAPI.encoder().encodeForHTMLAttribute
(request.getParameter(“input”));

原則4:在將不可信數(shù)據(jù)插入到SCRIPT里時(shí),對(duì)這些數(shù)據(jù)進(jìn)行SCRIPT編碼

這條原則主要針對(duì)動(dòng)態(tài)生成的JavaScript代碼,這包括腳本部分以及HTML標(biāo)簽的事件處理屬性(Event Handler,如onmouseover, onload等)。在往JavaScript代碼里插入數(shù)據(jù)的時(shí)候,只有一種情況是安全的,那就是對(duì)不可信數(shù)據(jù)進(jìn)行JavaScript編碼,并且只把這些數(shù)據(jù)放到使用引號(hào)包圍起來(lái)的值部分(data value)之中,例如: 

除此之外,往JavaScript代碼里其他任何地方插入不可信數(shù)據(jù)都是相當(dāng)危險(xiǎn)的,攻擊者可以很容易地插入攻擊代碼。

<script>alert(‘…插入不可信數(shù)據(jù)前,進(jìn)行JavaScript編碼…’)</script>
值部分使用了單引號(hào)
<script>x = “…插入不可信數(shù)據(jù)前,進(jìn)行JavaScript編碼…”</script>
值部分使用了雙引號(hào)
<div onmouseover=”x=’…插入不可信數(shù)據(jù)前,進(jìn)行JavaScript編碼…’“</div>
值部分使用了引號(hào),且事件處理屬性的值部分也使用了引號(hào)
特別需要注意的是,在XSS防御中,有些JavaScript函數(shù)是極度危險(xiǎn)的,
就算對(duì)不可信數(shù)據(jù)進(jìn)行JavaScript編碼,也依然會(huì)產(chǎn)生XSS漏洞,例如:
<script>
window.setInterval(‘…就算對(duì)不可信數(shù)據(jù)進(jìn)行了JavaScript編碼,
這里依然會(huì)有XSS漏洞…’);</script>

[編碼規(guī)則]

除了阿拉伯?dāng)?shù)字和字母,對(duì)其他所有的字符進(jìn)行編碼,只要該字符的ASCII碼小于256。編碼后輸出的格式為 \xHH (以 \x 開(kāi)頭,HH則是指該字符對(duì)應(yīng)的十六進(jìn)制數(shù)字)

在對(duì)不可信數(shù)據(jù)做編碼的時(shí)候,千萬(wàn)不能圖方便使用反斜杠( \ )對(duì)特殊字符進(jìn)行簡(jiǎn)單轉(zhuǎn)義,比如將雙引號(hào) ” 轉(zhuǎn)義成 \” ,這樣做是不可靠的,因?yàn)闉g覽器在對(duì)頁(yè)面做解析的時(shí)候,會(huì)先進(jìn)行HTML解析,然后才是JavaScript解析,所以雙引號(hào)很可能會(huì)被當(dāng)做HTML字符進(jìn)行HTML解析,這時(shí)雙引號(hào)就可以突破代碼的值部分,使得攻擊者可以繼續(xù)進(jìn)行XSS攻擊。例如:

假設(shè)代碼片段如下:

<script>var message =  $VAR “;</script>

攻擊者輸入的內(nèi)容為:

\”; alert(‘xss’);//

 

如果只是對(duì)雙引號(hào)進(jìn)行簡(jiǎn)單轉(zhuǎn)義,將其替換成 \” 的話,攻擊者輸入的內(nèi)容在最終的頁(yè)面上會(huì)變成:

<script>var message =  \\”; alert(‘xss’);// “;</script>

瀏覽器在解析的時(shí)候,會(huì)認(rèn)為反斜杠后面的那個(gè)雙引號(hào)和第一個(gè)雙引號(hào)相匹配,繼而認(rèn)為后續(xù)的alert(‘xss’)是正常的JavaScript腳本,因此允許執(zhí)行。

可以使用ESAPI提供的函數(shù)進(jìn)行JavaScript編碼:

String encodedContent = ESAPI.encoder().encodeForJavaScript
(request.getParameter(“input”));

原則5:在將不可信數(shù)據(jù)插入到Style屬性里時(shí),對(duì)這些數(shù)據(jù)進(jìn)行CSS編碼

當(dāng)需要往Stylesheet,Style標(biāo)簽或者Style屬性里插入不可信數(shù)據(jù)的時(shí)候,需要對(duì)這些數(shù)據(jù)進(jìn)行CSS編碼。傳統(tǒng)印象里CSS不過(guò)是負(fù)責(zé)頁(yè)面樣式的,但是實(shí)際上它比我們想象的要強(qiáng)大許多,而且還可以用來(lái)進(jìn)行各種攻擊。因此,不要對(duì)CSS里存放不可信數(shù)據(jù)掉以輕心,應(yīng)該只允許把不可信數(shù)據(jù)放入到CSS屬性的值部分,并進(jìn)行適當(dāng)?shù)木幋a。除此以外,最好不要把不可信數(shù)據(jù)放到一些復(fù)雜屬性里,比如url, behavior等,只能被IE認(rèn)識(shí)的Expression屬性允許執(zhí)行JavaScript腳本,因此也不推薦把不可信數(shù)據(jù)放到這里。

<style>
selector { property : …插入不可信數(shù)據(jù)前,進(jìn)行CSS編碼…}
 </style>
<style>
selector { property :  …插入不可信數(shù)據(jù)前,進(jìn)行CSS編碼… “}
 </style>
<span style=” property : …插入不可信數(shù)據(jù)前,進(jìn)行CSS編碼… ”></span>

[編碼規(guī)則]

除了阿拉伯?dāng)?shù)字和字母,對(duì)其他所有的字符進(jìn)行編碼,只要該字符的ASCII碼小于256。編碼后輸出的格式為 \HH (以 \ 開(kāi)頭,HH則是指該字符對(duì)應(yīng)的十六進(jìn)制數(shù)字)

同原則2,原則3,在對(duì)不可信數(shù)據(jù)進(jìn)行編碼的時(shí)候,切忌投機(jī)取巧對(duì)雙引號(hào)等特殊字符進(jìn)行簡(jiǎn)單轉(zhuǎn)義,攻擊者可以想辦法繞開(kāi)這類(lèi)限制。

可以使用ESAPI提供的函數(shù)進(jìn)行CSS編碼:

String encodedContent = 
ESAPI.encoder().encodeForCSS(request.getParameter(“input”));

原則6:在將不可信數(shù)據(jù)插入到HTML URL里時(shí),對(duì)這些數(shù)據(jù)進(jìn)行URL編碼

當(dāng)需要往HTML頁(yè)面中的URL里插入不可信數(shù)據(jù)的時(shí)候,需要對(duì)其進(jìn)行URL編碼,如下:

[編碼規(guī)則]

除了阿拉伯?dāng)?shù)字和字母,對(duì)其他所有的字符進(jìn)行編碼,只要該字符的ASCII碼小于256。編碼后輸出的格式為 %HH (以 % 開(kāi)頭,HH則是指該字符對(duì)應(yīng)的十六進(jìn)制數(shù)字)

在對(duì)URL進(jìn)行編碼的時(shí)候,有兩點(diǎn)是需要特別注意的:

1) URL屬性應(yīng)該使用引號(hào)將值部分包圍起來(lái),否則攻擊者可以很容易突破當(dāng)前屬性區(qū)域,插入后續(xù)攻擊代碼

2) 不要對(duì)整個(gè)URL進(jìn)行編碼,因?yàn)椴豢尚艛?shù)據(jù)可能會(huì)被插入到href, src或者其他以URL為基礎(chǔ)的屬性里,這時(shí)需要對(duì)數(shù)據(jù)的起始部分的協(xié)議字段進(jìn)行驗(yàn)證,否則攻擊者可以改變URL的協(xié)議,例如從HTTP協(xié)議改為DATA偽協(xié)議,或者javascript偽協(xié)議。

可以使用ESAPI提供的函數(shù)進(jìn)行URL編碼:

String encodedContent = 
ESAPI.encoder().encodeForURL(request.getParameter(“input”));

ESAPI還提供了一些用于檢測(cè)不可信數(shù)據(jù)的函數(shù),在這里我們可以使用其來(lái)檢測(cè)不可信數(shù)據(jù)是否真的是一個(gè)URL:

String userProvidedURL = request.getParameter(“userProvidedURL”);
boolean isValidURL = ESAPI.validator().isValidInput
(“URLContext”, userProvidedURL, URL”, 255, false);
if (isValidURL) 
{<a href=”<%= encoder.encodeForHTMLAttribute(userProvidedURL) %>”>
</a>}

原則7:使用富文本時(shí),使用XSS規(guī)則引擎進(jìn)行編碼過(guò)濾

Web應(yīng)用一般都會(huì)提供用戶輸入富文本信息的功能,比如BBS發(fā)帖,寫(xiě)博客文章等,用戶提交的富文本信息里往往包含了HTML標(biāo)簽,甚至是JavaScript腳本,如果不對(duì)其進(jìn)行適當(dāng)?shù)木幋a過(guò)濾的話,則會(huì)形成XSS漏洞。但我們又不能因?yàn)楹ε庐a(chǎn)生XSS漏洞,所以就不允許用戶輸入富文本,這樣對(duì)用戶體驗(yàn)傷害很大。

針對(duì)富文本的特殊性,我們可以使用XSS規(guī)則引擎對(duì)用戶輸入進(jìn)行編碼過(guò)濾,只允許用戶輸入安全的HTML標(biāo)簽,如<b>, <i>, <p>等,對(duì)其他數(shù)據(jù)進(jìn)行HTML編碼。需要注意的是,經(jīng)過(guò)規(guī)則引擎編碼過(guò)濾后的內(nèi)容只能放在<div>, <p>等安全的HTML標(biāo)簽里,不要放到HTML標(biāo)簽的屬性值里,更不要放到HTML事件處理屬性里,或者放到<SCRIPT>標(biāo)簽里。

推薦XSS規(guī)則過(guò)濾引擎:OWASP AntiSamp或者Java HTML Sanitizer

總結(jié)

由于很多地方都可能產(chǎn)生XSS漏洞,而且每個(gè)地方產(chǎn)生漏洞的原因又各有不同,所以對(duì)于XSS的防御來(lái)說(shuō),我們需要在正確的地方做正確的事情,即根據(jù)不可信數(shù)據(jù)將要被放置到的地方進(jìn)行相應(yīng)的編碼,比如放到<div>標(biāo)簽之間的時(shí)候,需要進(jìn)行HTML編碼,放到<div>標(biāo)簽屬性里的時(shí)候,需要進(jìn)行HTML屬性編碼,等等。

XSS攻擊是在不斷發(fā)展的,上面介紹的幾條原則幾乎涵蓋了Web應(yīng)用里所有可能出現(xiàn)XSS的地方,但是我們?nèi)匀徊荒艿粢暂p心,為了讓W(xué)eb應(yīng)用更加安全,我們還可以結(jié)合其他防御手段來(lái)加強(qiáng)XSS防御的效果,或者減輕損失:

對(duì)用戶輸入進(jìn)行數(shù)據(jù)合法性驗(yàn)證,例如輸入email的文本框只允許輸入格式正確的email,輸入手機(jī)號(hào)碼的文本框只允許填入數(shù)字且格式需要正確。這類(lèi)合法性驗(yàn)證至少需要在服務(wù)器端進(jìn)行以防止瀏覽器端驗(yàn)證被繞過(guò),而為了提高用戶體驗(yàn)和減輕服務(wù)器壓力,最好也在瀏覽器端進(jìn)行同樣的驗(yàn)證。

為Cookie加上HttpOnly標(biāo)記。許多XSS攻擊的目標(biāo)就是竊取用戶Cookie,這些Cookie里往往包含了用戶身份認(rèn)證信息(比如SessionId),一旦被盜,黑客就可以冒充用戶身份盜取用戶賬號(hào)。竊取Cookie一般都會(huì)依賴(lài)JavaScript讀取Cookie信息,而HttpOnly標(biāo)記則會(huì)告訴瀏覽器,被標(biāo)記上的Cookie是不允許任何腳本讀取或修改的,這樣即使Web應(yīng)用產(chǎn)生了XSS漏洞,Cookie信息也能得到較好的保護(hù),達(dá)到減輕損失的目的。

Web應(yīng)用變得越來(lái)越復(fù)雜,也越來(lái)越容易產(chǎn)生各種漏洞而不僅限于XSS漏洞,沒(méi)有銀彈可以一次性解決所有安全問(wèn)題,我們只能處處留意,針對(duì)不同的安全漏洞進(jìn)行針對(duì)性的防御。

希望本文介紹的幾條原則能幫助你成功防御XSS攻擊,如果你對(duì)于XSS攻擊或防御有任何的見(jiàn)解或疑問(wèn)的話,歡迎留言討論,謝謝。

 

責(zé)任編輯:藍(lán)雨淚 來(lái)源: FreebuF
相關(guān)推薦

2018-05-23 20:56:49

開(kāi)發(fā)原因原則

2024-04-17 08:05:18

C#并發(fā)設(shè)計(jì)

2021-08-17 16:49:04

大數(shù)據(jù)監(jiān)管物聯(lián)網(wǎng)IOT

2023-03-31 12:05:57

2022-11-02 10:31:01

IT創(chuàng)IT領(lǐng)導(dǎo)者

2010-09-08 15:07:23

2014-02-19 10:44:55

BYOD建議

2009-08-03 16:22:58

C#編程技巧

2021-10-29 05:52:01

零信任網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊

2009-06-09 22:14:17

JavaScript準(zhǔn)則

2023-10-12 08:00:00

2024-09-27 08:25:47

2021-06-30 07:25:35

開(kāi)發(fā)JavaXSS

2023-01-20 08:56:04

CIOIT領(lǐng)導(dǎo)

2020-05-11 07:55:53

AWS系統(tǒng)

2022-06-15 15:30:29

Linux新用戶建議

2013-05-22 18:06:41

2011-06-20 18:03:16

SEO

2021-08-03 14:17:47

Kubernetes容器安全

2017-03-02 07:36:40

科技新聞早報(bào)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)