本页面介绍了Angular内置的针对常见的Web应用程序漏洞和跨站脚本攻击等攻击的内置保护。 它不包括应用程序级别的安全性,如身份验证(此用户是谁?)和授权(此用户可以做什么?)。
有关下述攻击和缓解的更多信息,请参阅OWASP指南项目。
报告漏洞
要报告Angular本身的漏洞,请发送电子邮件至[email protected]。
有关Google如何处理安全问题的更多信息,请参阅Google的安全理念。
最佳实践
- 随时关注最新的Angular库版本。 我们会定期更新Angular库,这些更新可能会修复先前版本中发现的安全缺陷。 检查角度更改日志中的安全相关更新。
- 不要修改您的Angular副本。 Angular的私人定制版本倾向于落后于当前版本,可能不包含重要的安全修复和增强功能。 相反,与社区分享你的Angular改进,并提出请求。
- 尽可能避免在文档中标记为“安全风险”的Angular API。有关更多信息,请参阅本页面的信任安全值部分。
防止跨站点脚本(XSS)
跨站点脚本(XSS)使攻击者能够将恶意代码注入到网页中。 例如,此类代码可以窃取用户数据(特别是登录数据)或执行操作以模拟用户。 这是网络上最常见的攻击之一。
要阻止XSS攻击,您必须防止恶意代码进入DOM(文档对象模型)。 例如,如果攻击者可以诱使你在DOM中插入一个<script>标签,他们可以在你的网站上运行任意代码。 攻击并不局限于<script>标记 - DOM中的许多元素和属性允许执行代码,例如<img onerror =“...”>和<a href="javascript:...">。 如果攻击者控制的数据进入DOM,则预计存在安全漏洞。
Angular的跨站脚本安全模型
要系统地阻止XSS错误,Angular默认将所有值视为不可信。 当一个值通过属性,属性,样式,类绑定或插值从模板插入到DOM中时,Angular会清理并转义不受信任的值。
Angular模板与可执行代码相同:模板中的HTML,属性和绑定表达式(但不包括绑定的值)是值得信赖的。 这意味着应用程序必须防止攻击者可以控制的值永远不会变成模板的源代码。 切勿通过连接用户输入和模板来生成模板源代码。 为了防止这些漏洞,请使用脱机模板编译器,也称为模板注入。
消毒和安全环境
消毒是对不可信值的检查,将其转化为可以安全插入DOM的值。 在许多情况下,消毒不会彻底改变值。消毒取决于上下文:CSS中的无害值在URL中可能是危险的。
Angular定义了以下安全上下文:
- 将值解释为HTML时使用HTML,例如绑定到innerHtml时。
- 将CSS绑定到style属性时使用Style。
- URL用于URL属性,例如<a href>。
- 资源URL是一个将要作为代码加载和执行的URL,例如,在<script src>中。
Angular为HTML,Style和URL清理不可信的值; 清理资源URL是不可能的,因为它们包含任意代码。 在开发模式中,Angular在消毒过程中必须更改一个值时才会打印控制台警告。
消毒示例
以下模板将htmlSnippet的值绑定到一个元素的内容,并将其绑定到元素的innerHTML属性一次:
lib/src/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>
内插内容总是被转义 - HTML不被解释,浏览器在元素的文本内容中显示尖括号。
要解释HTML,请将其绑定到诸如innerHTML之类的HTML属性。 但是将攻击者可能控制的值绑定到innerHTML中通常会导致XSS漏洞。 例如,包含在<script>标签中的代码被执行:
lib/src/inner_html_binding_component.dart (class)
class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
var htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
Angular认为这个值是不安全的,并自动清理它,这会移除<script>元素,但会保留文本和<b>元素等安全内容。
避免直接使用DOM API
内置的浏览器DOM API不会自动保护您免受安全漏洞的侵害。 例如,文档和许多第三方API包含不安全的方法。 避免直接与DOM进行交互,而应尽可能使用Angular模板。
内容安全策略
内容安全策略(CSP)是一种防御XSS的纵深防御技术。 要启用CSP,请将Web服务器配置为返回适当的Content-Security-Policy HTTP标头。 请阅读Web基础知识网站上的内容安全策略。
使用脱机模板编译器
脱机模板编译器可以防止模板注入整个类的漏洞,并大大提高应用程序性能。在生产部署中使用脱机模板编译器; 不要动态生成模板。 Angular信任模板代码,因此生成模板(特别是包含用户数据的模板)绕开了Angular的内置保护。
服务器端XSS保护
在服务器上构建的HTML容易受到注入攻击。 将模板代码注入Angular应用程序与将可执行代码注入应用程序相同:它使攻击者可以完全控制应用程序。 为防止出现这种情况,请使用自动转义值的模板语言来防止服务器上的XSS漏洞。 不要使用模板语言在服务器端生成Angular模板; 这样做带来了引入模板注入漏洞的高风险。
信任安全值
有时应用程序真的需要包含可执行代码,从某个URL显示<iframe>,或构建潜在的危险URL。 为了防止在这些情况下出现自动消毒,您可以告诉Angular您检查了一个值,检查它是如何生成的,并确保它始终是安全的。 不过要小心。 如果您信任可能具有恶意的值,则会在您的应用中引入安全漏洞。 如有疑问,请找专业的安全审查员。
要将值标记为可信,请注入DomSanitizationService并调用以下方法之一:
- bypassSecurityTrustHtml
- bypassSecurityTrustScript
- bypassSecurityTrustStyle
- bypassSecurityTrustUrl
- bypassSecurityTrustResourceUrl
请记住,值是否安全取决于上下文,因此请选择正确的上下文以用于您预期的值使用。 想象一下,以下模板需要将URL绑定到javascript:alert(...)调用:
lib/src/bypass_security_component.html (URL)
<h4>A untrusted URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
<h4>A trusted URL:</h4>
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
通常,Angular会自动清理URL,禁用危险代码,并且在开发模式下,将此操作记录到控制台。 为防止出现这种情况,请使用bypassSecurityTrustUrl调用将URL值标记为受信任的URL:
lib/src/bypass_security_component.dart (excerpt)
BypassSecurityComponent(this.sanitizer) {
// javascript: URLs are dangerous if attacker controlled.
// Angular sanitizes them in data binding, but we can
// explicitly tell Angular to trust this value:
dangerousUrl = 'javascript:alert("Hi there")';
trustedUrl = sanitizer.bypassSecurityTrustUrl('javascript:alert("Hi there")');
如果您需要将用户输入转换为可信值,请使用控制器方法。以下模板允许用户输入YouTube视频ID并将相应的视频加载到<iframe>中。<iframe src>属性是资源URL安全上下文,因为不受信任的源也可以,例如在用户不知情可私自执行文件下载。 所以调用控制器上的一个方法来构建一个可信的视频URL,这会导致Angular允许绑定到<iframe src>中:
lib/src/bypass_security_component.html (iframe)
<h4>Resource URL:</h4>
<p>Showing: {{dangerousVideoUrl}}</p>
<p>Trusted:</p>
<iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl"></iframe>
<p>Untrusted:</p>
<iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl"></iframe>
lib/src/bypass_security_component.dart (excerpt)
void updateVideoUrl(String id) {
// Appending an ID to a YouTube URL is safe.
// Always make sure to construct SafeValue objects as
// close as possible to the input data, so
// that it's easier to check if the value is safe.
dangerousVideoUrl = 'https://www.youtube.com/embed/$id';
videoUrl = sanitizer.bypassSecurityTrustResourceUrl(dangerousVideoUrl);
}
审计Angular应用程序
Angular应用程序必须遵循与常规Web应用程序相同的安全原则,并且必须进行审核。 应该在安全审查中审核的特定于Angular的API(例如bypassSecurityTrust方法)在文档中标记为安全敏感。