javascript
css
html
前端
舉一個小例子java
使用express起一個web服務器,而後設置一下請求接口。經過ajax的GET請求將參數發往服務器,服務器解析成json後響應。將返回的數據解析後顯示到頁面上。(沒有對返回的數據進行解碼和過濾等操做。)node
1 html 2 <textarea name="txt" id="txt" cols="80" rows="10"> 3 <button type="button" id="test">測試</button> 4 5 js 6 var test = document.querySelector('#test') 7 test.addEventListener('click', function () { 8 var url = `/test?test=${txt.value}` // 1. 發送一個GET請求 9 var xhr = new XMLHttpRequest() 10 xhr.onreadystatechange = function () { 11 if (xhr.readyState === 4) { 12 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { 13 // 3. 客戶端解析JSON,並執行 14 var str = JSON.parse(xhr.responseText).test 15 var node = `${str}` 16 document.body.insertAdjacentHTML('beforeend', node) 17 } else { 18 console.log('error', xhr.responseText) 19 } 20 } 21 } 22 xhr.open('GET', url, true) 23 xhr.send(null) 24 }, false) 25 26 express 27 var express = require('express'); 28 var router = express.Router(); 29 30 router.get('/test', function (req, res, next) { 31 // 2. 服務端解析成JSON後響應 32 res.json({ 33 test: req.query.test 34 }) 35 })
如今咱們經過給textarea添加一段有攻擊目的的img標籤,git
<img src="null" onerror='alert(document.cookie)' />
實際的頁面時這樣的。github
ok如今,咱們點擊<測試>按鈕,一個XSS攻擊就發生了。下面圖片中是獲取了本地的部分cookie信息web
實際上,咱們只是模擬攻擊,經過alert獲取到了我的的cookie信息。可是若是是黑客的話,他們會注入一段第三方的js代碼,而後將獲取到的cookie信息存到他們的服務器上。這樣的話黑客們就有機會拿到咱們的身份認證作一些違法的事情了。ajax
以上,存在的一些問題,主要在於沒有對用戶輸入的信息進行過濾,同時沒有剔除掉DOM節點中存在的一些有危害的事件和一些有危害的DOM節點。
1 test.addEventListener('click', function () { 2 var node = window.eval(txt.value) 3 window.alert(node) 4 }, false) 5 6 txt中的代碼以下 7 <img src='null' onerror='alert(123)' />
以上經過eval語句就形成了XSS攻擊。
使用js或css破環頁面正常的結構與樣式
流量劫持(經過訪問某段具備window.location.href定位到其餘頁面)
Dos攻擊:利用合理的客戶端請求來佔用過多的服務器資源,從而使合法的用戶沒法獲得服務器響應
利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻擊)用戶的身份執行一些管理動做,或執行一些通常的如發微博、加好友、發私信等操做。
利用可被攻擊的域受到其餘域信任的特色,以受信任來源的身份請求一些平時不容許的操做,如進行不當的投票活動。
沒有過濾危險的屬性節點。如事件,style,src,href等
沒有對cookie設置httpOnly
若是將以上三點都在渲染過程當中過濾,那麼出現的XSS攻擊的改了也就小不少。
解決方法以下
2.解碼:原樣顯示內容的時候必須解碼,否則顯示不到內容了。
3.過濾:把輸入的一些不合法的東西都過濾掉,從而保證安全性。如移除用戶上傳的DOM屬性,如onerror,移除用戶上傳的Style節點,iframe, script節點等。
經過一個例子講解一下如何處理用戶輸入的數據。
存在一個parse函數,對輸入的數據進行處理,返回處理以後的數據
對輸入的數據(如DOM節點)進行解碼(使用第三方庫 he.js)
過濾掉一些元素有危害的元素節點與屬性節點。如script標籤,onerror事件等。(使用第三方庫HTMLParser.js)
1 <script src='/javascripts/htmlparse.js'></script> 2 <script src='/javascripts/he.js'></script> 3 // 第三方庫資源在文章底部給出 4 5 // parse函數實現以下 6 7 function parse (str) { 8 // str假如爲某個DOM字符串 9 // 1. result爲處理以後的DOM節點 10 let result = '' 11 // 2. 解碼 12 let decode = he.unescape(str, { 13 strict: true 14 }) 15 HTMLParser(decode, { 16 start (tag, attrs, unary) { 17 // 3. 過濾常見危險的標籤 18 if (tag === 'script' || tag === 'img' || tag === 'link' || tag === 'style' || tag === 'iframe' || tag === 'frame') return 19 result += `<${tag}` 20 for (let i = 0; i < attrs.length; i++) { 21 let name = (attrs[i].name).toLowerCase() 22 let value = attrs[i].escaped 23 // 3. 過濾掉危險的style屬性和js事件 24 if (name === 'style' || name === 'href' || name === 'src' || ~name.indexOf('on')) continue 25 result += ` ${name}=${value}` 26 } 27 result += `${unary ? ' /' : ''} >` 28 }, 29 chars (text) { 30 result += text 31 }, 32 comment (text) { 33 result += `<!-- ${text} -->` 34 }, 35 end (tag) { 36 result += `</${tag}>` 37 } 38 }) 39 return result 40 }
所以,有了以上的parse函數以後,就能夠避免大部分的xss攻擊了。
1 test.addEventListener('click', function () { 2 // ... 省略部分代碼 3 xhr.onreadystatechange = function () { 4 if (xhr.readyState === 4) { 5 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { 6 // 3. 客戶端解析JSON,並執行 7 // test按鈕的點擊事件中惟一的變化就是使用parse對服務端返回的數據進行了解碼和過濾的處理。 8 var str = parse(JSON.parse(xhr.responseText).test) 9 // 經過parse解析以後返回的數據就是安全的DOM字符串 10 var node = `${str}` 11 document.body.insertAdjacentHTML('beforeend', node) 12 } 13 } 14 } 15 // ... 省略部分代碼 16 }, false)
那麼,例子說完了
稍微總結一下
XSS分爲反射型XSS,存儲型XSS和DOM XSS
反射型XSS是在將XSS代碼放在URL中,將參數提交到服務器。服務器解析後響應,在響應結果中存在XSS代碼,最終經過瀏覽器解析執行。
存儲型XSS是將XSS代碼存儲到服務端(數據庫、內存、文件系統等),在下次請求同一個頁面時就不須要帶上XSS代碼了,而是從服務器讀取。
DOM XSS的發生主要是在JS中使用eval形成的,因此應當避免使用eval語句。
XSS危害有盜取用戶cookie,經過JS或CSS改變樣式,DDos形成正經常使用戶沒法獲得服務器響應。
XSS代碼的預防主要經過對數據解碼,再過濾掉危險標籤、屬性和事件等。
參考資源