先說個故事吧,在上一篇,我還想說這個案例。其實什麼叫攻擊,很簡單。擷取攻擊者想要的資訊,就黑成功了。抓到一個tomcat漏洞(這不是我說的,一個
認識的人說的),上傳一個jsp,裡面模拟httpclient,下載下傳一個木馬,運作。ok,搞定了。是以,沒有絕對的安全。
今天,泥瓦匠帶你們認識下xss,然後關于怎麼防禦的問題。至于防禦的話,仁者見仁智者見智。爾等啥都不配不上的就綽見,望各位閱讀者互相讨論。泥瓦匠目前是搞java的,是以例子上java比較多。
q: 什麼是xss? 為啥有這個呢?
a: 全名:cross site script,中文名:跨站腳本攻擊。顧名思義,是指“html注入”纂改了網頁,插入惡意的腳本,進而在使用者用浏覽網頁的時候,控制使用者浏覽器的一種攻擊。
xss根據攻擊的穩定性可分為三種:反射型xss, 存儲型xss,dom based xss.

再來了解下xss,是如何攻擊?泥瓦匠這時候想到一句話:知己知彼,百戰百勝吧。這攻擊我們不會很詳細解釋,畢竟想說的是xss防禦嘛。首先,泥瓦匠要介紹下的是:
xss
playload,所謂用以完成各種具體的功能的惡意腳本。這時候我想到了黑客精神中的小插曲,現在所謂的“黑客”不是真正的黑客,而是稱為腳本小子
(script kid)。常見的一個xss
playload,就是通過讀取浏覽器的cookie對象,進而發起了‘cookie劫持’攻擊。這個泥瓦匠會教你們去防禦哈,其中cookie的
‘httponly’辨別可以防止哦。
強大的xss playload可以做以下的事情哈:1、構造 get 與 post 請求 2、各種釣魚 3、識别使用者浏覽器 等等
q&a
q:什麼叫做釣魚呢?
a:顧名思義,願者上鈎,這裡做貶義用法。比如,人家用一個假的彈出框,或者假的頁面讓你輸入qq資訊,或者啥賬号資訊。其實你一輸入人家伺服器擷取到你的賬戶密碼了。這就是魚兒上鈎了。 如圖比喻:
兵來将擋,水來土掩。泥瓦匠在web安全上,想提醒大家的是:“再高的樹,猴子也能爬上去。”是以,我們考慮的地方有些預設都給你做好了,有些需要我們自己去關心,去設定。
其實在看不到的地方很多已經對抗xss做了些措施。比如各種浏覽器等。
一、按着上面的思路,泥瓦匠先聊下cookie,一個cookie,我們是這樣使用的:
1、浏覽器下伺服器發送請求,準備擷取cookie
2、伺服器傳回發送cookie頭,向用戶端浏覽器寫入cookie。(注意哦,這裡是浏覽器,不要當成什麼浏覽器核心)
3、在cookie到期前,浏覽器所有頁面,都會發送cookie。
這就意味着,我們cookie不能亂用。就像session一樣,是以在使用的時候,要注意下。有時候cooike在用于記住密碼的時候,千萬要注意要将
cookie設定httponly屬性為ture。這裡我以springmvc為例子。如果用到cookie的時候,應該這樣:
1
2
3
4
5
6
7
<code> </code><code>// create cookie and set it in response</code>
<code>cookie cookie1 = new cookie("cookie1", "cookievaluehttponly");</code>
<code>cookie cookie2 = new cookie("cookie2", "cookievalue");</code>
<code>cookie1.sethttponly(true);</code>
<code>response.addcookie(cookie1);</code>
<code>response.addcookie(cookie2);</code>
截個controller整個代碼看看:
我們打開浏覽器可以看到下面這種結果,通路url這個controller層,打開firebug檢視:
二、輸入校驗
輸入校驗的邏輯必須放在服務端中實作。如果用js進行的話,容易被攻擊者繞過去。是以普遍的做法是,類似很多代碼一樣進行double check:”用戶端js校驗和服務端校驗一起,這樣用戶端js校驗會阻擋大部分甚至說99%的使用者的誤操作。”
在xss防禦上,我們需要對使用者輸入的一些特殊字元校驗,過濾或者是編碼。這種輸入校驗的方式成為“xss filter”。首先我們在配置檔案中,
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<code>public class xsshttpservletrequestwrapper extends httpservletrequestwrapper</code>
<code>{</code>
<code> </code><code>public xsshttpservletrequestwrapper(httpservletrequest request)</code>
<code> </code><code>{</code>
<code> </code><code>super(request);</code>
<code> </code><code>}</code>
<code> </code><code>public string[] getparametervalues(string parameter)</code>
<code> </code><code>string[] values = super.getparametervalues(parameter);</code>
<code> </code><code>if (values==null)</code>
<code> </code><code>{</code>
<code> </code><code>return null;</code>
<code> </code><code>}</code>
<code> </code><code>int count = values.length;</code>
<code> </code><code>string[] encodedvalues = new string[count];</code>
<code> </code><code>for (int i = 0; i < </code><code>count</code><code>; i++)</code>
<code> </code><code>encodedvalues[i] = cleanxss(values[i]);</code>
<code> </code><code>return encodedvalues;</code>
<code> </code><code>public string getparameter(string parameter)</code>
<code> </code><code>string </code><code>value</code> <code>= </code><code>super</code><code>.getparameter(parameter);</code>
<code> </code><code>if (value == null)</code>
<code> </code><code>return cleanxss(value);</code>
<code> </code><code>public string getheader(string name)</code>
<code> </code><code>string </code><code>value</code> <code>= </code><code>super</code><code>.getheader(name);</code>
<code> </code><code>/**</code>
<code> </code><code>* @title: cleanxss</code>
<code> </code><code>* @description: you'll need to remove the spaces from the html entities below</code>
<code> </code><code>* @param @param value</code>
<code> </code><code>* @param @return</code>
<code> </code><code>* @return string</code>
<code> </code><code>*/</code>
<code> </code><code>private string cleanxss(string value)</code>
<code> </code><code>value</code> <code>= value.replaceall("<", "& lt;").replaceall(">", "& gt;");</code>
<code> </code><code>value = value.replaceall("\\(", "& #40;").replaceall("\\)", "& #41;");</code>
<code> </code><code>value = value.replaceall("'", "& #39;");</code>
<code> </code><code>value = value.replaceall("eval\\((.*)\\)", "");</code>
<code> </code><code>value = value.replaceall("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");</code>
<code> </code><code>value = value.replaceall("script", "");</code>
<code> </code><code>return value;</code>
<code>}</code>
三、輸出校驗
一般來說,除了富文本之外,在變量輸出到html頁面,可以使用編碼或者轉義的方式來防禦xss攻擊。這是一種各家委婉的方式吧。
用兵之道在于,如何正确的使用,才能以少勝多。web安全這場戰争也一樣,是以要如何正确的使用xss防禦。