防范跨站脚本(XSS)攻击
跨站脚本(XSS)允许攻击者将恶意代码注入到页面中。这些代码可以偷取用户数据 (特别是它们的登录数据),还可以冒充用户执行操作。它是Web上最常见的攻击方式之一。
为了防范 XSS 攻击,你必须阻止恶意代码进入 DOM。比如,如果某个攻击者能骗你把 <script> 标签插入到 DOM,就可以在你的网站上运行任何代码。 除了 <script>,攻击者还可以使用很多 DOM 元素和属性来执行代码,比如
<img onerror="...">、<a href="javascript:...">。
如果攻击者所控制的数据混进了 DOM,就会导致安全漏洞。
无害化范例
<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>
插值的内容总会被编码 - 其中的 HTML 不会被解释,所以浏览器会在元素的文本内容中显示尖括号。
如果希望这段 HTML 被正常解释,就必须绑定到一个 HTML 属性上,比如 innerHTML。但是如果把一个可能被攻击者控制的值绑定到 innerHTML 就会导致 XSS 漏洞。 比如,包含在 <script> 标签的代码就会被执行:
export class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
Angular 认为这些值是不安全的,并自动进行无害化处理。它会移除 <script> 标签,但仅仅保留安全的内容,比如该片段中的 <b> 元素。
- 信任安全值
注入DOM服务,然后调用下面的方法之一,你就可以把一个值标记为可信任的。
constructor(
private sanitizer:DomSanitizer
)
bypassSecurityTrustHtml
bypassSecurityTrustScript
bypassSecurityTrustStyle
bypassSecurityTrustUrl
bypassSecurityTrustResourceUrl
- 配合管道符使用demo
<article [innerHTML]="albumInfo.detailRichIntro | safeContent"></article>
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
type contentType = 'html' | 'style' | 'script' | 'url' | 'resourceUrl';
const funcMap = {
html: 'bypassSecurityTrustHtml',
style: 'bypassSecurityTrustStyle',
script: 'bypassSecurityTrustScript',
url: 'bypassSecurityTrustUrl',
resourceUrl: 'bypassSecurityTrustResourceUrl'
}
@Pipe({
name: 'safeContent'
})
export class SafeContentPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(value: string, type: contentType = 'html'): unknown {
return this.sanitizer[funcMap[type]](value);
}
}
HTTP级别的漏洞
Angular 内置了一些支持来防范两个常见的 HTTP 漏洞:跨站请求伪造(XSRF)和跨站脚本包含(XSSI)。 这两个漏洞主要在服务器端防范,但是 Angular 也自带了一些辅助特性,可以让客户端的集成变得更容易。
在跨站请求伪造(XSRF 或 CSFR)中,攻击者欺骗用户,让他们访问一个假冒页面(例如 evil.com), 该页面带有恶意代码,秘密的向你的应用程序服务器发送恶意请求(例如 example-bank.com)。
假设用户已经在 example-bank.com 登录。用户打开一个邮件,点击里面的链接,在新页面中打开 evil.com。
该 evil.com 页面立刻发送恶意请求到 example-bank.com。这个请求可能是从用户账户转账到攻击者的账户。 与该请求一起,浏览器自动发出 example-bank.com 的 cookie。
如果 example-bank.com 服务器缺乏 XSRF 保护,就无法辨识请求是从应用程序发来的合法请求还是从 evil.com 来的假请求。
为了防止这种情况,你必须确保每个用户的请求都是从你自己的应用中发出的,而不是从另一个网站发出的。 客户端和服务器必须合作来抵挡这种攻击。
常见的反 XSRF 技术是服务器随机生成一个用户认证令牌到 cookie 中。 客户端代码获取这个cookie,并用它为接下来所有的请求添加自定义请求页头。 服务器比较收到的cookie值与请求页头的值,如果它们不匹配,便拒绝请求。
这个技术之所以有效,是因为所有浏览器都实现了同源策略。只有设置 cookie 的网站的代码可以访问该站的cookie,并为该站的请求设置自定义页头。 这就是说,只有你的应用程序可以获取这个cookie令牌和设置自定义页头。evil.com 的恶意代码不能。
跨站脚本包含(XSSI)
跨站脚本包含,也被称为 Json 漏洞,它可以允许一个攻击者的网站从 JSON API 读取数据。这种攻击发生在老的浏览器上, 它重写原生 JavaScript 对象的构造函数,然后使用 <script> 标签包含一个 API 的 URL。
只有在返回的JSON能像JavaScript一样可以被执行时,这种攻击才会生效。所以服务端会约定给所有 JSON 响应体加上前缀 ")]}',\n",来把它们标记为不可执行的, 以防范这种攻击。
Angular 的 HttpClient 库会识别这种约定,并在进一步解析之前,自动把字符串 ")]}',\n" 从所有响应中去掉。
引用:Angular官网
网友评论