随着前端技术的发展,越来越多的框架默认对XSS做了有效的防范,遵循secure by default原则。
如果不了解前端框架本身的安全特性,就会导致代码审计过程中对XSS的审计不严密。
本文是从代码审计的视角去看不同前端框架中可能导致XSS的代码写法。
参考:https://sqreen.github.io/VueXSSDemo/#/
Vue
Vue使用双大括号将参数显示在浏览器中,双大括号默认将其中的数据解析为普通文本,而非 HTML 代码,这样避免了XSS的产生。
其他输出指令也同样会将数据解析为普通文本,比如v-model
当然实际业务中也存在输出HTML代码的需求,若想输出真正的 HTML,就需要使用 v-html
指令
1 | <p>Using mustaches: {{ rawHtml }}</p> |
若此时rawHtml为<span style="color: red">This should be malicious.</span>
,实际效果如下图:
v-html
的内容会被浏览器当作HTML字符解析,会导致XSS漏洞产生。
代码审计关键:注意
v-html
,v-html
输出的值若用户可控,就可能存在XSS。
来源:https://cn.vuejs.org/v2/guide/syntax.html#原始-HTML
Angular
Angular同样默认把所有值都当做不可信任的。 当值从模板中以属性(Property)、DOM 元素属性(Attribte)、CSS 类绑定或插值等途径插入到 DOM 中的时候, Angular 将对这些值进行无害化处理(Sanitize),对不可信的值进行编码。
在低版本(<1.6)的Angular中,存在模版注入的漏洞,用户直接传入49
会将7*7
插入到Angular的解析之中导致代码执行。
但前端框架更新速度是非常快的,截止到写文章,目前最新的Angular版本为v9.1.9
,及时更新可以一定程度避免框架本身导致的漏洞。
回到前端开发利用Angular框架回显参数时触发XSS的问题上来。
和Vue一样,Angular也使用双大括号将数据显示在浏览器中,双大括号默认将其中的数据解析为普通文本
不同的是Angular使用[innerHTML]
来表示其中的内容会被浏览器正常解析,不过Angular会识别其中的值,并将其进行无害化处理。
比如存在以下场景,一处使用显示
htmlSnippet
,另一处使用[innerHTML]="htmlSnippet"
显示htmlSnippet
1 | <h3>Binding innerHTML</h3> |
当htmlSnippet的内容如下时
1 | htmlSnippet = 'Template <script>alert("seikei")</script> <b>Syntax</b>'; |
得到的结果如下,最后一行<script>
标签不见了,不过它不是被浏览器解析了,而是被Angular自动进行了无害化处理,移除了<script>
标签,保留安全的内容,比如片段中的<b>
标签。
那万一Angular无害化处理器把业务所需的内容过滤了怎么办呢?
为了防止这种情况,Angular可以使用以下方法把值标记为可信任的,这样无害化处理器就不会再对该值进行过滤。
bypassSecurityTrustHtml
bypassSecurityTrustScript
bypassSecurityTrustStyle
bypassSecurityTrustUrl
bypassSecurityTrustResourceUrl
如下场景
1 | <h4>An untrusted URL:</h4> |
dangerousUrl为恶意代码,trustedUrl是经过信任的代码,可以不经过无害化处理器直接解析。
1 | dangerousUrl = 'javascript:alert("Hi seikei")'; |
结果是trusted URL会导致XSS产生,而untrusted不会。
代码审计关键:注意
[innerHTML]
、[href]
、[src]
等,再关注其传入的值是否经过bypassSecurityTrust
标记为信任,若值是信任的且用户可控,就可能存在XSS漏洞。
来源:https://angular.cn/guide/security#xss
React
React使用dangerouslySetInnerHTML
作为HTML输入的方法,并且需要向其传递包含 key 为 __html
的对象。只有使用dangerouslySetInnerHTML
会存在XSS。
1 | import React from 'react'; |
代码审计关键:关注
dangerouslySetInnerHTML
,若用户输入在dangerouslySetInnerHTML
中,可能导致XSS。
来源:https://zh-hans.reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
Thymeleaf
其实thymeleaf算不上前端框架,但是也能控制输入到前端页面的内容。在这里简单记录一下。
thymeleaf作为模版引擎,可以处理HTML,XML,JavaScript,CSS。thymeleaf有自己的XSS转义方法,thymeleaf模版在对th:text
标签进行渲染的时候,默认对特殊字符进行了转义,所以我们输入的XSS payload是在输出时被转义的。
而th:utext
不会将字符转义,这就会导致XSS产生。
代码审计关键:关注
th:utext
,th:utext
中的内容用户可控则存在XSS。