React是怎么防范XSS攻击的

常规的前端防范XSS攻击方式是通过对敏感字符进行转义完成的。

   function escape(str) {
      str = str.replace(/&/g, '&')
      str = str.replace(/</g, '&lt;')
      str = str.replace(/>/g, '&gt;')
      str = str.replace(/"/g, '&quto;')
      str = str.replace(/'/g, '&#39;')
      str = str.replace(/`/g, '&#96;')
      str = str.replace(/\//g, '&#x2F;')
      return str
    }

在React内部也针对XSS攻击做了设计:

ReactDOM 负责DOM层的所有事务,在渲染所有输入内容前,就会默认进行转义。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。

这样前端层的防范工作大致完成了。

那么如果使用React进行SSR,这个时候它是如何防范的呢?

先来看一下React是如何转换vDOM的:

在编写React代码时,我们通常采用JSX的方式,无需关心JSX是如何创建出vDOM对象的,以及后续是如何创建成DOM元素的(render())。

每个 JSX 元素只是调用 React.createElement(component, props, ...children) 的语法糖。因此,使用 JSX 可以完成的任何事情都可以通过纯 JavaScript 完成。

React.createElement 是React Core中的全局API,该方法调用方式为:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

它实际上创建了一个这样的对象

// 注意:这是简化过的结构
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

再来看完全版
$$typeof

上图中,我们今天的问题需要核心关注的属性是 $$typeof, type 和 props属性我们都能够理解,$$typeof是什么鬼?

这其实就是React为防范XSS攻击做的另外一层设计

假设这么一个场景,服务端允许用户可以提交一个JSON格式的数据,那么看完vDOM的构建流程就会发现这个JSON数据是可以被用来构建vDOM,进而触发XSS攻击

const dangerData = {
  type: stealYourPassword(), // DANGER!!
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

但是 React 会使用$$typeof 来检验标记是否安全,并且使用Symbol数据类型作为value;

因为JSON中无法传递 Symbol 格式数据,而如果 dangerData 中如果没有有效的 $$typeof value,则会被 React 判定为无效数据,直接潇洒走身甚至不留下一句废话(拒绝处理)。

React就是通过以上2种方式防范XSS攻击。 Salute~


1 + 3 =
2 评论
    ZanderChrome 89OSX
    2021年03月16日 回复

    Salute~(ps: 评论内容不少于一个汉字有些强人所难

      GodGcChrome 89Windows 10
      2021年03月16日 回复

      @Zander 去年有一波bot经常来刷垃圾评论就卡了一下留言机制~

求知若飢,虛心若愚。