欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

利用脚本注入漏洞攻击ReactJS应用程序

来源:本站整理 作者:佚名 时间:2017-08-08 TAG: 我要投稿

ReactJS是一款能够帮助开发者构建用户接口的热门JavaScript库。在它的帮助下,开发者可以构建出内容丰富的客户端或Web应用,并且提前加载内容以提供更好的用户体验。
从设计角度来看,只要你能够按照开发标准来使用ReactJS的话,它其实是非常安全的。但是在网络安全领域中,没有任何东西是绝对安全的,而错误的编程实践方式将导致类似脚本注入漏洞之类的问题产生,这些错误的编程方式包括:
1.利用用户提供的对象来创建React组件;
2.利用用户提供的href属性来配置标签,或利用其他可注入的属性来设置其他的HTML标签(例如link标签);
3.显示地设置一个元素的dangerouslySetInnerHTML属性(危险的HTML标签属性);
4.向eval()传递用户提供的字符串数据;
接下来,让我们一起看一看这些潜在的问题将如何影响ReactJS应用程序,并最终导致了脚本注入漏洞的出现。
组件、属性和元素
在ReactJS应用程序中,组件是最基本的组成部分。从本质上来说,这些组件其实都类似于JavaScript函数,它们可以接受任意的输入数据,然后返回React元素。一个基本的ReactJS组件如下所示:
class Welcome extends React.Component {
  render() {
return Hello, {this.props.name};
  }
}
请注意上面代码中的return语句,这是一种JavaScript中的语句扩展(JSX)。在项目构建的过程中,JSX代码将会被编译成常规的JavaScript(ES5)代码。下面给出的两种样本代码其功能是完全相同的:
// JSX
const element = (
 
  Hello, world!
 
);
// Transpiled to createElement() call
const element = React.createElement(
  ‘h1’,
  {className: ‘greeting’},
  ‘Hello, world!’
);
在创建新的React元素时,使用的是component类中的createElement()函数:
React.createElement(
  type,
  [props],
  [...children]
)
这个函数可以接受三个参数:
1.type参数:该参数可以是一个标签名(例如'div'或'span'),或一个component类。但是在React Native中只允许component类。
2.props参数:该参数包含一个传递给新元素的属性列表。
3.children参数:该参数包含新元素的子节点。
如果你能够控制其中任何一个参数的话,那么这个参数就会变成攻击向量。
注入子节点
早2015年3月份,Daniel LeCheminant报告了一个存在于HackerOne的存储型跨站脚本漏洞(XSS)。这个漏洞的成因如下:HackerOne的Web应用会将用户所提供的任意对象当作children参数传递给React.createElement()函数。根据我们的推测,存在漏洞的代码可能跟下方给出的代码比较相似:
/* Retrieve a user-supplied, stored value from the server and parsed it as JSON for whatever reason.
attacker_supplied_value = JSON.parse(some_user_input)
*/
render() {
 return {attacker_supplied_value};
}
这段JSX代码将会被转译成如下所示的JavaScript代码:

React.createElement("span", null, attacker_supplied_value};
如果其中的attacker_supplied_value是一个字符串的话(正常情况),代码将会生成一个正常的span元素。但是在当前版本的ReactJS中,createElement()函数还会接受以children参数形式传递的普通对象。Daniel通过一个JSON编码的对象利用了这个漏洞,他在这个对象中包含了dangerouslySetInnerHTML属性,这将允许他向React呈现的输出效果中注入原始的HTML代码。最终的PoC代码:
{
 _isReactElement: true,
 _store: {},
 type: “body”,
 props: {
   dangerouslySetInnerHTML: {
     __html:
     "Arbitrary HTML
     alert(‘No CSP Support :(‘)
     link"
    }
  }
}
相关的漏洞缓解方案可以在React.js的GitHub主页上找到,感兴趣的同学可以参考。在2015年11月份,Sebastian Markbåge提交了一个修复方案:为React元素引入了$$typeof: Symbol.for('react.element')属性。由于无法从一个注入对象引用全局JavaScript符号,所以Daniel设计的漏洞利用技术(注入child元素)就无法再使用了。
控制元素类型
虽然我们不能再将普通对象来当作ReactJS元素来使用了,但是组件注入并非不可能实现,因为createElement()函数还可以接受type参数中的字符串数据。我们假设开发者采用了如下所示的代码:
// Dynamically create an element from a string stored in the backend.
element_name = stored_value;
React.createElement(element_name, null);
如果stored_value是一个由攻击者控制的字符串,那我们就可以创建任意的React组件了。但是此时创建的是一个普通的无属性HTML元素,而这种东西对于攻击者来说是没有任何作用的。因此,我们必须要能够控制新创建元素的属性才可以。
注入属性(props)
请大家先看看下面给出的这段代码:
// Parse attacker-supplied JSON for some reason and pass
// the resulting object as props.
// Don't do this at home unless you are a trained expert!
attacker_props = JSON.parse(stored_value)
React.createElement("span", attacker_props};
这样一来,我们就可以向新元素中注入任意属性了。我们可以使用下面给出的Payload来设置dangerouslySetInnerHTML属性:

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载