扣丁书屋

关于 XSS 攻击,在 React 中我们可以做这些防范措施!

XSS 攻击其中的一种类型是基于 DOM 型,攻击者很容易将包含恶意的 JavaScript 代码注入前端页面中,从而发起恶意攻击。

如今,很大一部分网站都在使用 React 进行开发,本文带大家了解 XSS 攻击是如何影响着我们的 React 应用程序,及如何避免应用程序受到 XSS 攻击

React 会受到 XSS 攻击吗?

如下所示,让我们先用 React 写一段存在 XSS 攻击的恶意代码,看它运行之后会发生什么?

const content = `<img onerror='alert("xss ");' src='xxx.png' /> Test XSS 攻击`;
class XSSTest extends React.Component {
  render() {
    return (
      <div> { content } </div>
    )
  }
}

当运行之后,浏览器为我们呈现的是一段字符串而不是被解析运行的 DOM。这是因为 React 中的 JSX 提供了防止注入攻击,在渲染所有的输入内容前,默认会进行**转义**,这些内容都会被转换成字符串输出到 DOM ,有效的防止了 XSS 攻击

如果想在我们的 DOM 上渲染 HTML 该怎么办?

dangerouslySetInnerHTML

dangerouslySetInnerHTML 是 React 解析含有 HTML 标记内容的一种方式,也是原生 DOM 元素 innerHTML 的替代方案,从这个命名 dangerously 也能看出是一个危险的 API,以此来警示用户,使用 dangerouslySetInnerHTML API 直接设置含有 HTML 标签的内容很容易遭到 XSS 攻击

继续上面的示例,让我们做下修改。

const content = `<img onerror='alert("xss ");' src='xxx.png' /> Test XSS 攻击`;
class XSSTest extends React.Component {
  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: content }}></div>
    )
  }
}

运行上面代码之后,会出现以下界面,页面被 XSS 注入了。

image.png

有的时候在内容管理系统(CMS)中包含有 HTML 标记的内容,确实需要在页面展示,你应该做的是在解析前先通过一个工具函数处理掉内容中的恶意脚本。

通常这类工具函数不需要自己重新编写,社区已经有一些不错的解决方案,例如 github.com/leizongmin/js-xss 这个工具,同时支持浏览器端、Node.js 服务端,可通过白名单策略控制允许的 HTML 标签和属性。

import xss from 'xss';
const content = xss(`<img onerror='alert("xss ");' src='xxx.png' /> Test XSS 攻击`);

再次运行看下展现效果,发现当通过 xss() 工具函数包装处理之后,img 标签里的 onerror 属性被转义了。

image.png

除此之外还有一个用来处理含有恶意代码的工具 sanitize-html,默认有一些过滤策略,如果想获得更多内容,还需要自定义允许的标签和属性。

Refs 滥用

React 提供的 Refs 允许我们操作 DOM 节点或在 render() 方法中创建的 React 元素。

Refs 设计的应用场景是在媒体播放、焦点和文本选择,及实现动画与一些基于 DOM 的第三方库配合使用,例如结合 react-transition-group 实现动画在严格模式下必须使用 refs <CSSTransition nodeRef={React.createRef()} /> 否则会警告 findDOMNode is deprecated in StrictMode,这也是警告我们不要直接操作 DOM。

当 Refs 被过度滥用时,往往就会出现一些不可控的影响,如下例所示,通过创建的 xssTestRef 对象来操作 DOM 节点是有风险的,XSS 很容易被注入。

import React from 'react'; 

const content = `<img onerror='alert("xss ");' src='xxx.png' /> Test XSS 攻击`;
const xssTestRef = React.createRef();
class XSSTest extends React.Component {
  componentDidMount() {
    xssTestRef.current.innerHTML = content;
  }
  render() {
    return (
      <div ref={xssTestRef}>11</div>
    )
  }
}

export default XSSTest;

总结

为了更好的预防应用程序出现 XSS 攻击,我们要了解它是什么,什么情况下会发生,本文我们的讲解主要围绕 XSS 攻击的 DOM 类型来看,除此之外还有存储型,这涉及到服务端,关于 XSS 的详细介绍可参考这篇文章 “[Web 安全 - 跨站脚本攻击 XSS 三种类型及防御措施] ”。

关于 XSS 攻击,在 React 中我们可以做这些防范措施:

  • 尽可能使用 JSX 呈现页面内容,React 在背后会为我们做了一些处理,防止 XSS 攻击。
  • 不要直接操作 DOM,尤其是使用 innerHTML 时要多加注意,如果有可能尽量选择 innerText 代替,最好方法还是使用 JSX 渲染。
  • 勿滥用 Refs,避免借助 Refs 做一些危险的 DOM 操作。
  • 使用 dangerouslySetInnerHTML API 时,确保渲染前先对数据进行处理,可以通过 js-xss、sanitize-html、DOMPurify 这些工具函数实现恶意脚本过滤。
  • 最后,Web 安全这个话题有很多内容,推荐你关注这个指南 #Web 安全系列#,希望可以帮助到你。

文中一些外链无法跳转,可阅读原文查看。

- END -


https://mp.weixin.qq.com/s/y3D2wN_LazkaoCivB5KXIg

深入 React 函数组件的 re-render 原理及优化

发布于:1年以前  |  615次阅读  |  详细内容 »

手写系列-实现一个铂金段位的 React

发布于:1年以前  |  484次阅读  |  详细内容 »

如何写出更优雅的 React 组件 - 代码结构篇

发布于:1年以前  |  581次阅读  |  详细内容 »

React 精品组件:mac-scrollbar

发布于:1年以前  |  548次阅读  |  详细内容 »

React 精品组件:mac-scrollbar

发布于:1年以前  |  530次阅读  |  详细内容 »

React 18 Beta 来了

发布于:1年以前  |  630次阅读  |  详细内容 »

手把手教你写一个 React 状态管理库

发布于:1年以前  |  568次阅读  |  详细内容 »

如何将 React 应用程序加载时间减少 70%

发布于:1年以前  |  618次阅读  |  详细内容 »

React 18 新特性之 startTransition

发布于:1年以前  |  586次阅读  |  详细内容 »

Reaction Engines成立新合资公司以打造紧凑、轻质的氨反应器

英国的Reaction Engines公司已经宣布成立一家合资企业以打造紧凑、轻质的氨反应器。这家公司表示,这种反应器可以用于航运和离网能源发电等困难行业的脱碳,并且还可以用于航空。

发布于:1年以前  |  639次阅读  |  详细内容 »

你不知道的 React 最佳实践

发布于:1年以前  |  515次阅读  |  详细内容 »

这才是 React Hooks 性能优化的正确姿势

发布于:1年以前  |  562次阅读  |  详细内容 »

所属标签

最多阅读

Android插件化方案 3年以前  |  235043次阅读
SourceTree,让你忘掉Git命令的工具 3年以前  |  3705次阅读
朴素贝叶斯分类器的应用 3年以前  |  3356次阅读
在Python的Django框架中包装视图函数 3年以前  |  3247次阅读
用Sublime打造Protobuf迷你IDE 3年以前  |  3241次阅读
Python贪吃蛇游戏编写代码 3年以前  |  3224次阅读
在Sublime中高亮显示Proto Buffer 3年以前  |  3222次阅读
Google Shell 风格指南 3年以前  |  3110次阅读
Google Python 风格指南 3年以前  |  3097次阅读
Genymotion下载及安装使用 3年以前  |  3045次阅读
Markdown语法 转义 3年以前  |  2990次阅读
Markdown语法 链接 3年以前  |  2860次阅读
Markdown语法 段落内代码 3年以前  |  2814次阅读
java中NIO与传统IO 3年以前  |  2769次阅读

手机扫码阅读