AngularJS - 逃避表达式沙箱进行 XSS 攻击

工程 | Rob Winch | 2016 年 1 月 28 日 | ...

更新:这是对 《XSS 无需 HTML:使用 AngularJS 进行客户端模板注入》 的总结。之前引用在文档中间,难以找到。总结的目的是呈现漏洞利用和修复方案,而不涉及所有细节,也不是声称这项工作是我的。

引言

AngularJS 是一个流行的 JavaScript 框架,允许在双大括号内嵌入 表达式例如,表达式 1+2={{1+2}} 将渲染为 1+2=3

这意味着,如果服务器回显了包含双大括号的用户输入,用户就可以利用 Angular 表达式执行 XSS 攻击。

服务器端写入用户输入

让我们看看一个安全地对用户输入进行 HTML 编码的页面。在我们下面的示例中,我们使用 Thymeleaf 进行 HTML 编码,然后将属性 username 输出到我们页面的 div 文本中。

<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>AngularJS - Escaping the Expression Sandbox</title>
</head>
<body>
<div th:text="${username}"></div>
</body>
</html>

如果 username 是 <script>alert('Rob')</script>,输出可能看起来像这样:

<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>AngularJS - Escaping the Expression Sandbox</title>
</head>
<body>
<div>&lt;script&gt;alert(&#39;Rob&#39;)&lt;/script&gt;</div>
</body>
</html>

您会注意到输出经过了正确的 HTML 编码。这意味着我们的应用程序目前可以免受 XSS 攻击。

添加 AngularJS

我们的应用程序目前针对 XSS 攻击是安全的。让我们更新应用程序以使用 AngularJS。

<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Angular Expression - safe</title>
<script src="angular-1.4.8.min.js"></script>
</head>
<body ng-app>
<div th:text="${username}"></div>
</body>
</html>

您会注意到两个变化:

  • 我们添加了 angular-1.4.8.min.js
  • 我们在 body 元素上添加了 ng-app

我们的应用程序现在容易受到 XSS 攻击,但我们如何利用它呢?最大的线索应该是我们对 Angular 表达式的介绍。当 username 是 1+2={{1+2}} 时会发生什么?结果将是

<html>
<head>
<title>Angular Expression - safe</title>
<script src="angular-1.4.8.min.js"></script>
</head>
<body ng-app="">
<div>1+2={{1+2}}</div>
</body>
</html>

Angular 随后会将 DOM 更新为:

<html>
<head>
<title>Angular Expression - safe</title>
<script src="angular-1.4.8.min.js"></script>
</head>
<body ng-app="">
<div>1+2=3</div>
</body>
</html>

我们可以尝试一个 username,例如 {{alert('Rob')}},但这将被 表达式沙盒 阻止。此时您可能会认为我们是安全的。然而,尽管出现在文档的安全部分,表达式沙盒并不是为了提供安全性。

更具体地说,文档对 混合客户端和服务器端模板 如下所述:

总的来说,我们不推荐这样做,因为它可能会产生意想不到的 XSS 向量。

最终,这意味着如果您允许服务器端在模板中渲染用户输入,那么该应用程序就容易受到 XSS 攻击。让我们看一个具体的例子。

逃避表达式沙盒

如果我们的 payload 被沙盒化,我们如何提供一个有效的 XSS 漏洞?如果我们的 username 是

{{
'a'.constructor.prototype.charAt=[].join;
eval('x=1} } };alert(1)//');
}}

通过覆盖原生函数 charAt,我们可以绕过 Angular 的表达式沙盒,并允许我们执行 alert(1)。有关此漏洞如何工作的完整详细信息,请参阅 XSS without HTML: Client-Side Template Injection with AngularJS

注意:此 payload 针对 Chrome 和 AngularJS 1.4.8。在其他浏览器中未知是否有效。

结论

允许服务器将用户输入回显到 Angular 模板将使您的应用程序容易受到 XSS 漏洞的攻击。总的来说,您不应该混合服务器端渲染的用户输入和客户端模板。您可以在 rwinch/angularjs-escaping-expression-sandbox 找到伴随这篇博文的示例。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有