漏洞簡介
Cross-Site Scripting(為了與CSS區別,安全領域叫做XSS)攻擊是注入的一種,主要是將惡意腳本注入到可信站點的HTML頁面等網頁文件中,當攻擊者將帶有惡意腳本的網頁鏈接發送給用戶,用戶打開鏈接,瀏覽器會認為惡意腳本來自可信站點而執行
舉個例子
@app.route("/")
def index():
param = request.args.get("param", "")
response = make_response("<p>Hello {}</p>".format(param))
response.set_cookie("key", "value", httponly=False) # 關閉框架自帶的httponly=true
response.headers["X-XSS-Protection"] = 0 # Chrome本身的XSS防御關閉
return response
構造一個惡意URL http://test.com/param=<script>alert(document.cookie)</script>
瀏覽器打開后可以看到頁面的反饋,彈出一個彈框,帶有設置的 key: value 的Cookie
實際攻擊可以將上述代碼邏輯修改為,通過Ajax把Cookie信息發送到攻擊者服務器,攻擊者就可以盜取用戶身份訪問站點
XSS攻擊發生在
- 數據通過不可信源進入Web應用程序,最常見的是Web請求
- 數據被包含在動態內容中,該動態內容被發送到Web用戶而不被驗證為惡意內容,發送到Web瀏覽器的惡意內容通常采用JS的一種形式,但也可以包括HTML、Flash或者瀏覽器可執行的任何其他類型代碼
XSS的攻擊效果
- 基于XSS的攻擊種類幾乎是無限的
- 它們通常包括向攻擊者發送諸如Cookie或其他會話信息之類的私有數據,將受害者重定向到攻擊者控制的Web內容,或者在用戶的機器上執行其他惡意操作
- 因為客戶端JS等腳本語言的靈活性,XSS攻擊可以和其他攻擊方式在合適場景中相結合,造成更大的破壞
XSS的類型
反射型XSS
反射型XSS是用戶輸入直接作為響應的一部分作為服務器輸出,如用戶提交的表單、URL作為錯誤信息、搜索結果返回給用戶,攻擊者構造惡意的URL,Web表單發送給用戶,用戶點擊就會觸發
比如上面漏洞介紹里舉的例子就是反射型XSS
存儲型XSS
存儲型XSS會把用戶輸入的數據“存儲”到服務端,往往是數據庫,往往具有更強的穩定性和破壞性,產生這種漏洞的頁面功能往往是 往往是論壇消息、訪問者日志、評論字段等
舉個例子
我們在類似QQ空間的Web系統中提交文章和評論,會被存儲在服務器數據庫中,我們可以根據文章ID查詢到文章內容
文章的顯示頁面邏輯往往如下
@app.route("/")
def index():
post_id = request.args.get("id", "")
post = db.query(post_id=post_id).first()
response = make_response("<textview> {}<textview>".format(post.content))
response.set_cookie("key", "value", httponly=False) # 關閉框架自帶的httponly=true
response.headers["X-XSS-Protection"] = 0 # Chrome本身的XSS防御關閉
return response
可以看到邏輯和上面反射型XSS基本是一樣的,當用戶將 <script>alert(document.cookie)</scirpt> 一類的攻擊腳本寫入文章,其他用戶訪問時便會觸發XSS
存儲型XSS由于不用在URL中構造惡意腳本也更容易對用戶進行釣魚,不易被識別
DOM型XSS
以上兩種XSS是根據惡意腳本是否能持久化(保存在服務端)進行劃分的,DOM Based XSS從效果上來說也是反射型XSS,但因為成因特別,就單獨作為一類
我們把修改頁面DOM節點形成的XSS,稱為DOM Based XSS
比如前端頁面的代碼為
<p>Select your language:</p>
<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
惡意請求 http://www.some.site/page.html?default=<script>alert(document.cookie)</script>
我們發現上面這樣的請求和反射型XSS差不多,那么為什么DOM型XSS要單獨分為一類呢
因為在前后端分離的頁面中,SPA等模式中,這些請求會只在前端消化,不會傳送到后端
另外一種情況,還是上面的頁面,假如我們的服務器對XSS有著非常好的過濾和編碼方式,請求從服務器返回時類似 <script>,document.cookie,alert 這些字段都去掉了,那有什么辦法再生成XSS攻擊呢
我們把URL變成 http://www.some.site/page.html#default=<script>alert(document.cookie)</script> ,我們可以發現此時攻擊仍然能夠生效
URL有個特點, # 被稱為錨點,用于定位頁面位置,#符號后的內容不會傳輸到服務器
再進一步思考,反射型和存儲型XSS中,參數值為惡意腳本,服務器端沒有經過檢查和過濾將惡意腳本拼接到了HTML頁面中,瀏覽器加載頁面執行腳本造成了XSS攻擊,而通過URL錨點觸發的XSS沒有經過服務器,瀏覽器充當服務器角色拼接腳本到HTML頁面中
也就是說我們多把后臺服務改變網頁代碼造成的XSS叫做反射型XSS,而網頁本身的JS改變的叫做DOM型XSS
筆者認為在B/S構架中,越來越靈活的Web使得瀏覽器和JS充當了一個客戶端里的小型服務器,對用戶的部分響應不需要再經過真正服務端的處理,預置在頁面JS腳本中的一部分函數和功能直接處理了用戶輸入輸出,或者對服務器的返回進行再處理,因此DOM型XSS也是針對瀏覽器和JS這個小型服務器的攻擊,才被單獨作為一類
除了上面例子中href.location獲取參數外,還要注意一些請求參數在服務器端經過一定的編碼和過濾,但仍然可以通過DOM的改變對這些參數再一次進行處理,所以要注意防御XSS是防御最后瀏覽器顯示的頁面,而對DOM改變的操作相當于返回給用戶的頁面不用從真正服務端給出,而是瀏覽器和JS給出的
XSS的利用方式
基本上XSS能夠做到事就是JS一類的腳本能做到的事,這里舉一些XSS的利用方式,但不具體說明
- 盜取用戶Cookie(登錄態)
- 構造GET、POST等HTTP方法模擬網站邏輯以劫持用戶身份執行(類似CSRF)
- 盜取頁面數據,如一下用戶敏感信息
- 識別用戶瀏覽器
- 識別用戶訪問歷史
- XSS蠕蟲
修復方式
編碼轉換
這是防御XSS中最重要最有效的一步,服務端對要輸出給用戶的Web文件內容做以下編碼轉換(實體編碼),同理,如果JS改變了DOM,也要在JS中對數據內容進行以下編碼,對于用戶的輸入輸出更要重點處理
& --> &
< --> <
> --> >
" --> "
/ --> /
' --> ' 單引號也有轉換成'的情況,但是不推薦,因為這種轉換不在HTML的規范中,而是在XML和XHTML的規范中
隨著前端技術的發展,使用類似Angular JS、VUE JS的框架,本身自帶編碼轉換,了解相關模塊的配置之后使用
建議是在輸出的時候進行驗證和過濾,常見的情況如下
|
注入點 |
示例 |
方法 |
|
HTML元素注入 |
|
|
|
HTML原屬屬性 |
|
|
|
URL請求參數 |
|
|
|
CSS值 |
|
|
|
JavaScript |
|
不適合編碼來保護,沒有內置編碼方法提供保護,可以通過URL編碼等但是容易對應用邏輯產生影響 |
使用Cookie的httponly標識
為Cookie字段帶上httponly的標識,可以防止JS讀取Cookie信息,因此可以有效防止XSS攻擊中盜取用戶Cookie的能力
但是這種方式不是防御了XSS漏洞,只是減少了XSS漏洞造成的損失,但依舊十分有效,前端頁面不需要讀取Cookie的話盡量為每個Cookie配置這個標識
使用X-XSS-Protection頭部進行防御
瀏覽器本身內置了XSS的防御審計工具,可以通過X-XSS-Protection進行配置,但是瀏覽器的防御攻擊也是人寫的代碼,本身具有安全隱患
建議在看明白上文后使用,建議按需求使用X-XSS-Protection: 1; mode=block和X-XSS-Protection: 0兩種配置,但其實瀏覽器本身也在升級,未來可能會更加好用
XSS過濾
存在一些情況,比如富文本,不能使用HTML實體編碼的方式進行XSS防御,因為富文本中需要用到HTML標簽來顯示,在了解需求的情況下使用白名單進行過濾,因為XSS攻擊的靈活只推薦使用白名單
設置白名單需要對XSS的可以利用的HTML標簽和位置有一定了解,參考OWASP的開源項目anti-samy
不使用Flash
Flash已淘汰,不推薦使用
浙公網安備 33010602011771號