主讲人简介
ashx:
腾讯安全科恩实验室安全研究员、Katzebin战队副队长、TCTF出题人之一;主要研究Web安全,在各类的Web应用中发掘不少高危漏洞;作为A*0*E与Katzebin成员参与多场CTF竞赛。
前言
随着前端技术的高速发展,前后端分离的开发模式已经深入人心。由于后端不再直接输出页面,转以API接口的方式提供服务,导致XSS在这类新项目中不再常见。不过安全永远是一个动态的过程,新的开发技术会带来新的攻击面。现今前端最常用的主要是三个框架:React、Vuejs和Angular,本文将具体介绍基于React框架开发的前端应用的攻击面。其他框架也可依此类推。
React应用长什么样?
什么是JSX?
const element = ( <h1 className="greeting"> Hello, world! </h1>);
const element = { type: 'h1', props: { className: 'greeting',
children: 'Hello, world!' }};
常规XSS
滥用Ref
由于React有几个版本对Ref做了相当多的改动,因此在实际审计时看到的ref用法可能和图中的不同,对挖掘DOM XSS无影响。
滥用dangerouslySetInnerHTML
动态组件传参/动态创建组件
const a = JSON.parse(location.hash.substr(1))
// hash = #{dangerouslySetInnerHTML:
{__html: '<script>alert(1)</script>'}}
return <div {...a} />
它和以下的ES5代码功能基本等价
var a = JSON.parse(location.hash.substr(1))
var b = {}
for (var key in a) {
// 此处存在原型链污染,仅为示例
b[key] = a[key]}
return React.createElement({ "type": "div", "props": b})
特殊DOM标签的特殊属性
const id = location.hash.substr(1)const a = <a href={id} />
const b = <iframe src={id} />
SSR时的可疑输入
function renderFullPage(html, preloadedState) {
return `
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
</head>
<body>
<div id="root">${html}</div>
<script>
// WARNING: See the following for security issues around embedding JSON in HTML:
// https://redux.js.org/usage/server-rendering#security-considerations
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(
/</g,
'\\u003c'
)}
</script>
<script src="/static/bundle.js"></script>
</body>
</html>
`
}
原型链污染
SSR时的前端和后端的代码绝大多数是共用的,因此可以通过审计前端代码的方式来对SSR服务进行攻击。如果前端打包时存在Sourcemap泄漏,就可以更直观地看到具体的依赖库,之后直接搜CVE或者npm audit。此处的原型链污染想要RCE难度较大,一般的SSR框架,除了express(Nodejs下的WebServer框架)以外,不怎么依赖别的Nodejs平台相关的库和API。对于原型链污染来说,部署最广泛的可攻击目标是模板引擎,但SSR一般不使用这些库,导致攻击面相对较小。
const a = <div {...props} />
hasOwnProperty
检查其是否是原型链属性。const {id, username, password} = props
var _props = props,
id = _props.id,
username = _props.username,
password = _props.password;
const {id, title, message, dismissible, showDismissButton, buttons, allowHTML, image} = notification
// ...
return (
<div>
<div style={metaStyles} className={classnames.notificationMeta}>
{title &&
(allowHTML ? (
<h4
style={titleStyles}
className={classnames.notificationTitle}
dangerouslySetInnerHTML={{__html: title}}
/>
) : (
<h4 style={titleStyles} className={classnames.notificationTitle}>
{title}
</h4>
))}
dangerouslySetInnerHTML
,可以把这种危险参数作为原型链污染的目的地。按此处的逻辑,只需要 Object.prototype.allowHTML
为 true
,页面里就会直接把 Object.prototype.title
属性原样输出。as
:https://chakra-ui.com/docs/layout/box#as-prop 。该属性的效果大致如下:const a = <Box as="button" />
const b = <Box />
return <div>{a}{b}</div>
<div>
<button></button>
<div></div>
</div>
as
的实现,代码在此处:https://github.com/emotion-js/emotion/blob/23f43ab9f24d44219b0b007a00f4ac681fe8712e/packages/styled/src/base.js#L134const Styled: PrivateStyledComponent<Props> = withEmotionCache((props, cache, ref) => {
const finalTag = (shouldUseAs && props.as) || baseTag
for (let key in props) {
if (shouldUseAs && key === 'as') continue
if (finalShouldForwardProp(key)) {
newProps[key] = props[key]
}
}
newProps.className = className
newProps.ref = ref
const ele = React.createElement(finalTag, newProps)
props.as
是否属于props对象(对于UI框架一般也没有检查的必要)finalTag = props.as
,即原型链污染可控props
到 newProps
时未检查属性是否属于props对象<iframe src="javascript:alert(1)">
并。as属性在几乎所有UI框架中都存在,这使得一个原型链污染漏洞可以在几乎所有UI框架中造成XSS。(这题无法直接给Object设置一个 dangerouslySetInnerHTML
属性,这会使其他代码无法运行)as
属性有点类似各种CMS的反序列化链,虽然不是漏洞,但这种feature会被原型链污染漏洞滥用。React Native?
后利用窃取数据
XSS不只是弹窗,后续利用也值得关注。获取用户数据是XSS漏洞的一大危害,而在React框架中获取数据需要一些技巧。
最轻松的获取数据的方法是从DOM或者是localStorage等数据展示/持久化存储的地方获取数据,但有些数据(例如Token)一般不会被渲染在页面内,需要从React内部获取这些数据。
在从React内部获取数据之前,可以考虑通过Hook相关API的方式来获取数据。对 fetch API和 XMLHttpRequest API进行hook (https://github.com/wendux/Ajax-hook ),或者是对数据附近的JavaScript/BOM/DOMAPI进行Hook,都是比较好实现又不依赖于React的通用解决方案。
如果实在难以获得数据,必须从React内部获得,则需要对React的相关概念进行学习。一个React项目的数据一般会存储在这些地方:Prop、State、Context,或是ReduxStore。从外部很难获取到React内部的值。
Context等属性可以在该属性内的 stateNode 属性找到,对于Redux只需要找到需要的数据在哪个React节点内被调用,读取其props/state也可以间接获取内部数据。获取这些数据最主要的麻烦是如何寻找到对应的ReactDOM节点,这需要配合Dev Tool和源码慢慢挖掘。
自查React项目的安全问题
扩展阅读
腾讯安全科恩实验室
关注我们,KeenLab Tech Talk系列将持续以视频/文本形式输出技术干货,涵盖: 漏洞分析、工具分享、技巧总结、算法优化 、入门引导 、赛题讲解 等安全领域主题。更有不定期抽奖活动等你参与!