當(dāng)項(xiàng)目的安全團(tuán)隊(duì)找上門告訴您,您開發(fā)的項(xiàng)目存在 XSS 安全漏洞,作為一個(gè)開發(fā)人員,就問您慌不慌??
HTML 內(nèi)容寫入的時(shí)候,如果稍不注意就會(huì)觸發(fā)隱藏 BOSS 漏洞 XSS。
XSS 漏洞原理就是利用了網(wǎng)站上內(nèi)容輸入的地方,比如說常見的評(píng)論提交,老六
通過輸入評(píng)論的地方,提交一些 包含 JS 代碼的內(nèi)容
到服務(wù)器,服務(wù)器沒做任何操作直接寫入到數(shù)據(jù)庫,最后在評(píng)論查詢的時(shí)候直接將數(shù)據(jù)庫的內(nèi)容原樣返給前端,而前端拿到此內(nèi)容的時(shí)候,也不做任何處理,直接將內(nèi)容以 HTML 的形式渲染的頁面中,這時(shí)候 老六
輸入的非法內(nèi)容就會(huì)被當(dāng)做 JS 代碼執(zhí)行,這就是典型的 XSS 注入攻擊。
要避免 XSS 漏洞,就需要對(duì)不可信的內(nèi)容進(jìn)行過濾;或者不要
把這部分內(nèi)容當(dāng)做 HTML 處理,直接當(dāng)做文本
渲染也可以避免 XSS 注入。
DOM 屬性操作
在了解 DOM 內(nèi)容操作之前,先學(xué)習(xí)幾個(gè)常用的 DOM 屬性操作方法,畢竟 JS 與 CSS 聯(lián)動(dòng)一般都是通過 DOM 屬性進(jìn)行關(guān)聯(lián)。
比如 JS 控制 class 屬性的變化,再在 CSS 中編寫不同的 class 樣式,就可以讓 HTML 元素渲染成不同的樣子。
element.getAttribute(name)
element.setAttribute(name, value)
element.removeAttribute(name)
element.classList.add(c1, c2, c3, ...)
element.classList.remove(c1, c2, c3, ...)
element.classList.toggle(className, force)
element.classList.contains(className)
element.id
element.className
element.style
img.src
通過 className
可直接設(shè)置元素的 class 屬性,這兒有一個(gè)問題,為什么不是直接使用 class
設(shè)置呢?
原因是:class 是 JS 中的關(guān)鍵字,為避免引起一些語法問題,所以就換了一個(gè)名字 className
。
通過 className
控制類名的增刪改雖然也不是不能做,但是始終有那么一點(diǎn)點(diǎn)麻煩,所以后來就引入了 classList
用來專門控制 class 屬性。
而 Attribute
相關(guān)的幾個(gè)方法,則是可以用來控制元素的所有屬性,包括自定義屬性和一些默認(rèn)的屬性 id、style、className 等。所以記住 Attribute 幾個(gè)方法就已經(jīng)可以打穿 DOM 屬性操作了。
示例:
<style>
.red {
color: red;
}
.blue {
color: blue;
}
[data-type="bold"] {
font-weight: bold;
}
[data-type="italic"] {
font-style: italic;
}
</style>
<div id="test">公眾號(hào):前端路引</div>
<img id="img">
<script>
const test = document.getElementById('test');
const img = document.getElementById('img');
test.setAttribute('data-type', 'bold')
const type = test.getAttribute('data-type')
console.log('?? ~ type:', type);
test.removeAttribute('data-type')
test.setAttribute('data-type', 'italic')
const hasRed = test.classList.contains('red')
console.log('?? ~ hasRed:', hasRed);
test.classList.add('red')
test.classList.remove('red')
test.classList.toggle('blue')
img.src = 'https://developer.mozilla.org/static/media/firefox.1eabb4da07c095ca04fa.svg'
console.log('?? ~ img.src:', img.src);
img.id = 'img-1'
console.log('?? ~ img.id:', img.id);
img.className = 'img-1'
console.log('?? ~ img.className:', img.className);
img.style.border = '1px solid red'
img.style.borderWidth = '4px'
img.style['border-color'] = 'blue'
img.style.width = '100px'
console.log('?? ~ img.style:', img.style['border-width']);
</script>
在使用 style
屬性設(shè)置樣式的時(shí)候,如果使用的是 .
語法賦值,那么必須要改為 小駝峰命名
,原因是 JS 中的 .
語法不支持短橫線,比如 borderWidth
,不能使用 border-width
。
在使用數(shù)組取值語法的時(shí)候,可以直接使用 css 的屬性賦值,比如 img.style['border-color'] = 'blue'
。
運(yùn)行結(jié)果:

DOM 內(nèi)容操作
DOM 屬性操作一般不會(huì)觸發(fā)安全問題, XSS 注入都是發(fā)生在 DOM 內(nèi)容操作的時(shí)候,所以在使用 JS 進(jìn)行 DOM 內(nèi)容操作時(shí)需特別小心。
常用的兩個(gè)個(gè)方法:
element.innerHTML = htmlString;
element.textContent = textString;
實(shí)例:
<div id="test1">公眾號(hào):前端路引</div>
<div id="test2">公眾號(hào):前端路引</div>
<script>
const test1 = document.getElementById('test1');
const test2 = document.getElementById('test2');
test1.innerHTML = '<strong>警告</strong>:用戶輸入內(nèi)容';
test2.textContent = '<strong>安全文本</strong>';
console.log(test2.innerHTML);
console.log(test2.textContent);
</script>
運(yùn)行結(jié)果:

XSS 注入
在使用 innerHTML 設(shè)置 HTML 內(nèi)容時(shí),如果用戶輸入的內(nèi)容中包含 JS 腳本,那么就會(huì)導(dǎo)致 XSS 注入。
比如這樣:
<div id="test1">公眾號(hào):前端路引</div>
<div id="test2">公眾號(hào):前端路引</div>
<script>
const test1 = document.getElementById('test1');
const h1 = `<script>alert("XSS");<\/script>`;
test1.innerHTML = h1;
const test2 = document.getElementById('test2');
const h2 = `<img src=x onerror="alert('XSS')">`;
test2.innerHTML = h2;
</script>
HTML5 規(guī)范規(guī)定:通過 innerHTML 動(dòng)態(tài)插入的 <script>
標(biāo)簽不會(huì)執(zhí)行其中的 JavaScript 代碼。
這是瀏覽器的一種安全機(jī)制,目的是防止開發(fā)者無意或惡意插入可執(zhí)行腳本。
XSS 注入可能導(dǎo)致的問題:非法用戶直接在網(wǎng)站中運(yùn)行 JS 代碼,可以獲取用戶信息,從而偽造一些請(qǐng)求,達(dá)到非法目的。
寫在最后
在使用 JS 操作 DOM 內(nèi)容的時(shí)候,需特別防范 XSS 注入問題,尤其是用戶輸入的內(nèi)容更加要加強(qiáng)防范,可以把任何用戶當(dāng)做一個(gè)潛在的攻擊者,他們所有的輸入都是不可信的,這樣可以避免很多的安全問題。
轉(zhuǎn)自https://www.cnblogs.com/linx/p/18951405
該文章在 2025/7/4 9:36:57 編輯過