Angular9 防范跨站腳本(XSS)攻擊

2020-07-08 14:27 更新

跨站腳本(XSS)允許攻擊者將惡意代碼注入到頁(yè)面中。這些代碼可以偷取用戶(hù)數(shù)據(jù) (特別是它們的登錄數(shù)據(jù)),還可以冒充用戶(hù)執(zhí)行操作。它是 Web 上最常見(jiàn)的攻擊方式之一。

為了防范 XSS 攻擊,你必須阻止惡意代碼進(jìn)入 DOM。比如,如果某個(gè)攻擊者能騙你把 <script> 標(biāo)簽插入到 DOM,就可以在你的網(wǎng)站上運(yùn)行任何代碼。 除了 <script>,攻擊者還可以使用很多 DOM 元素和屬性來(lái)執(zhí)行代碼,比如 <img onerror="...">、<a href="javascript:...">。 如果攻擊者所控制的數(shù)據(jù)混進(jìn)了 DOM,就會(huì)導(dǎo)致安全漏洞。

Angular 的“跨站腳本安全模型”

為了系統(tǒng)性的防范 XSS 問(wèn)題,Angular 默認(rèn)把所有值都當(dāng)做不可信任的。 當(dāng)值從模板中以屬性(Property)、DOM 元素屬性(Attribte)、CSS 類(lèi)綁定或插值等途徑插入到 DOM 中的時(shí)候, Angular 將對(duì)這些值進(jìn)行無(wú)害化處理(Sanitize),對(duì)不可信的值進(jìn)行編碼。

Angular 的模板同樣是可執(zhí)行的:模板中的 HTML、Attribute 和綁定表達(dá)式(還沒(méi)有綁定到值的時(shí)候)會(huì)被當(dāng)做可信任的。 這意味著應(yīng)用必須防止把可能被攻擊者控制的值直接編入模板的源碼中。永遠(yuǎn)不要根據(jù)用戶(hù)的輸入和原始模板動(dòng)態(tài)生成模板源碼! 使用離線模板編譯器是防范這類(lèi)“模板注入”漏洞的有效途徑。

無(wú)害化處理與安全環(huán)境

無(wú)害化處理會(huì)審查不可信的值,并將它們轉(zhuǎn)換成可以安全插入到 DOM 的形式。多數(shù)情況下,這些值并不會(huì)在處理過(guò)程中發(fā)生任何變化。 無(wú)害化處理的方式取決于所在的環(huán)境:一個(gè)在 CSS 里面無(wú)害的值,可能在 URL 里很危險(xiǎn)。

Angular 定義了四個(gè)安全環(huán)境 - HTML,樣式,URL,和資源 URL:

  • HTML:值需要被解釋為 HTML 時(shí)使用,比如當(dāng)綁定到 innerHTML 時(shí)。

  • 樣式:值需要作為 CSS 綁定到 style 屬性時(shí)使用。

  • URL:值需要被用作 URL 屬性時(shí)使用,比如 <a href>。

  • 資源 URL 的值需要作為代碼進(jìn)行加載并執(zhí)行,比如 <script src> 中的 URL。

Angular 會(huì)對(duì)前三項(xiàng)中種不可信的值進(jìn)行無(wú)害化處理,但不能對(duì)第四種資源 URL 進(jìn)行無(wú)害化,因?yàn)樗鼈兛赡馨魏未a。在開(kāi)發(fā)模式下, 如果在進(jìn)行無(wú)害化處理時(shí)需要被迫改變一個(gè)值,Angular 就會(huì)在控制臺(tái)上輸出一個(gè)警告。

無(wú)害化示例

下面的例子綁定了 htmlSnippet 的值,一次把它放進(jìn)插值里,另一次把它綁定到元素的 innerHTML 屬性上。

Path:"src/app/inner-html-binding.component.html" 。

<h3>Binding innerHTML</h3>
<p>Bound value:</p>
<p class="e2e-inner-html-interpolated">{{htmlSnippet}}</p>
<p>Result of binding to innerHTML:</p>
<p class="e2e-inner-html-bound" [innerHTML]="htmlSnippet"></p>

插值的內(nèi)容總會(huì)被編碼 - 其中的 HTML 不會(huì)被解釋?zhuān)詾g覽器會(huì)在元素的文本內(nèi)容中顯示尖括號(hào)。

如果希望這段 HTML 被正常解釋?zhuān)捅仨毥壎ǖ揭粋€(gè) HTML 屬性上,比如 innerHTML。但是如果把一個(gè)可能被攻擊者控制的值綁定到 innerHTML 就會(huì)導(dǎo)致 XSS 漏洞。 比如,包含在 <script> 標(biāo)簽的代碼就會(huì)被執(zhí)行:

Path:"src/app/inner-html-binding.component.ts (class)" 。

export class InnerHtmlBindingComponent {
  // For example, a user/attacker-controlled value from a URL.
  htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}

Angular 認(rèn)為這些值是不安全的,并自動(dòng)進(jìn)行無(wú)害化處理。它會(huì)移除 <script> 標(biāo)簽,但保留安全的內(nèi)容,比如該片段中的 <b> 元素。

避免直接使用 DOM API

瀏覽器內(nèi)置的 DOM API 不會(huì)自動(dòng)保護(hù)你免受安全漏洞的侵害。比如 document、通過(guò) ElementRef 拿到的節(jié)點(diǎn)和很多第三方 API,都可能包含不安全的方法。如果你使用能操縱 DOM 的其它庫(kù),也同樣無(wú)法借助像 Angular 插值那樣的自動(dòng)清理功能。 所以,要避免直接和 DOM 打交道,而是盡可能使用 Angular 模板。

瀏覽器內(nèi)置的 DOM API 不會(huì)自動(dòng)針對(duì)安全漏洞進(jìn)行防護(hù)。比如,document(它可以通過(guò) ElementRef 訪問(wèn))以及其它第三方 API 都可能包含不安全的方法。 要避免直接與 DOM 交互,只要可能,就盡量使用 Angular 模板。

內(nèi)容安全策略

內(nèi)容安全策略(CSP) 是用來(lái)防范 XSS 的縱深防御技術(shù)。 要打開(kāi) CSP,請(qǐng)配置你的 Web 服務(wù)器,讓它返回合適的 HTTP 頭 Content_Security_Policy。 要了解關(guān)于內(nèi)容安全策略的更多信息,請(qǐng)參閱 HTML5Rocks 上的內(nèi)容安全策略簡(jiǎn)介。

使用離線模板編譯器

離線模板編譯器阻止了一整套被稱(chēng)為“模板注入”的漏洞,并能顯著增強(qiáng)應(yīng)用程序的性能。盡量在產(chǎn)品發(fā)布時(shí)使用離線模板編譯器, 而不要?jiǎng)討B(tài)生成模板(比如在代碼中拼接字符串生成模板)。由于 Angular 會(huì)信任模板本身的代碼,所以,動(dòng)態(tài)生成的模板 —— 特別是包含用戶(hù)數(shù)據(jù)的模板 —— 會(huì)繞過(guò) Angular 自帶的保護(hù)機(jī)制。 要了解如何用安全的方式動(dòng)態(tài)創(chuàng)建表單,請(qǐng)參見(jiàn) 構(gòu)建動(dòng)態(tài)表單 一章。

服務(wù)器端 XSS 保護(hù)

服務(wù)器端構(gòu)造的 HTML 很容易受到注入攻擊。當(dāng)需要在服務(wù)器端生成 HTML 時(shí)(比如 Angular 應(yīng)用的初始頁(yè)面), 務(wù)必使用一個(gè)能夠自動(dòng)進(jìn)行無(wú)害化處理以防范 XSS 漏洞的后端模板語(yǔ)言。不要在服務(wù)器端使用模板語(yǔ)言生成 Angular 模板, 這樣會(huì)帶來(lái)很高的 “模板注入” 風(fēng)險(xiǎn)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)