跨站腳本攻擊(XSS)是客戶端腳本安全的頭號大敵。本文章深刻探討 XSS 攻擊原理,下一章(XSS 攻擊進階)將深刻討論 XSS 進階攻擊方式。html
本系列將持續更新。後端
XSS(Cross Site Script),全稱跨站腳本攻擊,爲了與 CSS(Cascading Style Sheet) 有所區別,因此在安全領域稱爲 XSS。跨域
XSS 攻擊,一般指黑客經過 HTML 注入 篡改網頁,插入惡意腳本,從而在用戶瀏覽網頁時,控制用戶瀏覽器的一種攻擊行爲。在這種行爲最初出現之時,全部的演示案例全是跨域行爲,因此叫作 "跨站腳本" 。時至今日,隨着Web 端功能的複雜化,應用化,是否跨站已經不重要了,但 XSS 這個名字卻一直保留下來。瀏覽器
隨着 Web 發展迅速發展,JavaScript 通吃先後端,甚至還能夠開發APP,因此在產生的應用場景愈來愈多,愈來愈複雜的狀況下, XSS 越來越難統一針對,如今業內達成的共識就是,針對不一樣的場景而產生的不一樣 XSS ,須要區分對待。可即使如此,複雜應用仍然是 XSS 滋生的溫牀,尤爲是不少企業實行迅捷開發,一週一版本,兩週一大版本的狀況下,忽略了安全這一重要屬性,一旦遭到攻擊,後果將不堪設想。安全
那什麼是 XSS 呢?咱們看下面一個例子。服務器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>XSS</title> </head> <body> <div id="t"></div> <input id="s" type="button" value="獲取數據" onclick="test()"> </body> <script> function test() { // 假設從後臺取出的數據以下 const arr = ['1', '2', '3', '<img src="11" onerror="alert(\'我被攻擊了\')" />'] const t = document.querySelector('#t') arr.forEach(item => { const p = document.createElement('p') p.innerHTML = item t.append(p) }) } </script> </html>
這個時候咱們在頁面上點擊 獲取數據
按鈕時,頁面上會出現以下信息:app
你會發現,本應該做爲數據展現在界面上的內容竟然執行了,這顯然是開發者不但願看到的。dom
XSS 根據效果的不一樣能夠分爲以下幾類:xss
簡單來講,反射型 XSS 只是將用戶輸入的數據展示到瀏覽器上(從哪裏來到哪裏去),即須要一個發起人(用戶)來觸發黑客佈下的一個陷阱(例如一個連接,一個按鈕等),才能攻擊成功,通常容易出如今搜索頁面、留言板塊。這種反射型 XSS 也叫作 非持久型 XSS(No-persistent XSS) 。ui
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="t"></div> <input id="s" type="button" value="獲取數據" onclick="test()"> </body> <script> function test() { const arr = ['1', '2', '3', '<img src="11" onerror="console.log(window.localStorage)" />'] const t = document.querySelector('#t') arr.forEach(item => { const p = document.createElement('p') p.innerHTML = item t.append(p) }) } </script> </html>
假設這是一個留言板塊,加載到這一頁時,頁面會輸出:
黑客能夠輕易盜取存儲在你本地瀏覽器的各類信息,進而模擬登錄信息,黑入帳戶,進行各類操做。
存儲型 XSS 會把用戶輸入的數據 保存 在服務器端,這種 XSS 十分穩定,十分有效,效果持久。存儲型 XSS 一般叫作 "持久型 XSS(Persistent XSS)",即存在時間比較長。
比較常見的場景就是,黑客寫下一篇包含惡意代碼的文章,文章發表後,全部訪問該博客文章的用戶都會執行這一段代碼,進行惡意攻擊。
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="t"> 這是我寫的一篇文章 </div> </body> <script> console.log(navigator.userAgent) </script> </html>
直接輸出了瀏覽器信息,黑客能夠獲取到這些信息後,發送到本身的服務器,隨意操做。
實際上,這種類型的 XSS 與是否存儲在服務器端無關,從效果上來講也是反射型 XSS,單獨劃分出來是由於此類 XSS 造成的緣由比較特殊。
簡單來講,經過修改頁面 DOM 節點造成的 XSS,稱之爲 DOM Based XSS。
例子以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>XSS</title> </head> <body> <div id="t"></div> <input type="text" id="text" value=""> <input type="button" id="s" value="search" onclick="test()"> </body> <script> function test() { const str = document.querySelector('#text').value document.querySelector('#t').innerHTML = '<a href="' + str + '" >查找結果</a>' } </script> </html>
該頁面的做用是,在輸入框內輸入一個內容,跳出查找結果能直接跳轉,效果以下:
點擊查找結果後,頁面會自動跳到百度(毒)頁面,可是細心的咱們會發現,這字符串拼接有可乘之機啊,輸入" onclick=alert(/XSS/) //
:
果真,頁面執行了咱們輸入的東西,上面的內容是,第一個雙引號閉合掉href
的第一個雙引號,而後插入onclick
事件,最後註釋符 //
註釋掉第二個雙引號,點擊跳轉連接,腳本就被執行了。