当他们说 React 受 XSS 保护时,这是什么意思?

IT技术 reactjs security xss
2021-04-07 03:47:22

我在 React 教程中读到了这个。这是什么意思?

react是安全的。我们不会生成 HTML 字符串,因此 XSS 保护是默认设置。

如果 React 是安全的,XSS 攻击如何工作?这种安全性是如何实现的?

2个回答

ReactJS 在设计上非常安全,因为

  1. 视图中的字符串变量会自动转义
  2. 使用 JSX,你传递一个函数作为事件处理程序,而不是一个包含恶意代码的字符串

所以像这样的典型攻击是行不通的

const username = "<img onerror='alert(\"Hacked!\")' src='invalid-image' />";

class UserProfilePage extends React.Component {
  render() {
    return (
      <h1> Hello {username}!</h1>
    );
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

但 ...

❗❗❗警告❗❗❗

还有一些 XSS 攻击向量需要你在 React 中自己处理!

1. XSS 通过 dangerouslySetInnerHTML

当您使用时,dangerouslySetInnerHTML您需要确保内容不包含任何 javascript。React 不能在这里为你做任何事情。

const aboutUserText = "<img onerror='alert(\"Hacked!\");' src='invalid-image' />";

class AboutUserComponent extends React.Component {
  render() {
    return (
      <div dangerouslySetInnerHTML={{"__html": aboutUserText}} />
    );
  }
}

ReactDOM.render(<AboutUserComponent />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

2.通过a.href属性的XSS

示例 1:使用 javascript:code

点击“运行代码片段”->“我的网站”查看结果

const userWebsite = "javascript:alert('Hacked!');";

class UserProfilePage extends React.Component {
  render() {
    return (
      <a href={userWebsite}>My Website</a>
    )
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

示例 2:使用 base64 编码数据:

点击“运行代码片段”->“我的网站”查看结果

const userWebsite = "data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGFja2VkISIpOzwvc2NyaXB0Pg==";

class UserProfilePage extends React.Component {
  render() {
    const url = userWebsite.replace(/^(javascript\:)/, "");
    return (
      <a href={url}>My Website</a>
    )
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

3. XSS 通过攻击者控制的props

const customPropsControledByAttacker = {
  dangerouslySetInnerHTML: {
    "__html": "<img onerror='alert(\"Hacked!\");' src='invalid-image' />"
  }
};

class Divider extends React.Component {
  render() {
    return (
      <div {...customPropsControledByAttacker} />
    );
  }
}

ReactDOM.render(<Divider />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

这里有更多资源

这个答案太神奇了!最后附上代码片段和参考资料......!谢谢!
2021-05-22 03:47:22
自从编写此答案以来,React 是否已经处理了上述任何示例?我在问,因为我阅读了以下幻灯片:slideshare.net/kseniadmitrieva/...幻灯片 #20 用户控制的道具在 11 月 15 日在 React 0.14 中修复
2021-06-08 03:47:22
@RahulYadav 使用 dompurify 包来清理数据。这是链接npmjs.com/package/dompurify
2021-06-09 03:47:22
@omer 不,React 决定不在 React 级别处理这种攻击向量。这里有一些好的评论,解释了为什么他们不在 React 级别处理github.com/facebook/react/issues/3473 ( github.com/facebook/react/issues/3473#issuecomment-91349525 , github.com/facebook/react /issues/3473#issuecomment-90594748 )
2021-06-11 03:47:22
@omer 您所指的问题是一个安全错误,它已修复,但我列出的第 3 点与该问题无关,您仍然可以通过在任何 react 版本下执行我的代码来检查第 3 点的工作。
2021-06-13 03:47:22

React 会自动为你转义变量......它可以防止通过带有恶意 Javascript 的字符串 HTML 进行 XSS 注入......自然地,输入也会随之被清理。

例如,假设你有这个字符串

var htmlString = '<img src="javascript:alert('XSS!')" />';

如果您尝试在react中呈现此字符串

render() {
    return (
        <div>{htmlString}</div>
    );
}

你会在页面上看到整个字符串,包括<span>元素标签。又名在浏览器中你会看到<img src="javascript:alert('XSS!')" />

如果您查看源 html,您会看到

<span>"<img src="javascript:alert('XSS!')" />"</span>

这里有一些关于什么是 XSS 攻击的更多细节

React 基本上做到了,所以你不能插入标记,除非你自己在渲染函数中创建元素......据说他们确实有一个允许这种渲染的函数被调用dangerouslySetInnerHTML......这里有一些关于它的更多细节


编辑:

有几件事需要注意,有一些方法可以解决 React 逃避的问题。一种更常见的方式是当用户为你的组件定义 props 时。不要将用户输入的任何数据扩展为props!

逃避一切?真的吗?默认情况下,React 并不安全,您必须手动执行很多操作,并且您必须了解攻击向量。当您尝试使用 {html} 插入它时,React 所做的就是将 html 转义为字符串。但是还有一百万种其他方式可以允许 XSS,而 React 并不能防止这些方式。<a href="{...}" />, <img src={...} />, <iframe src="{...} /> 以及大量其他允许注入可执行 javascript 的道具。然后通过 style={...} 属性注入 CSS 脚本。@Marty Aghajanyan 下面的回答实际上概述了可能的风险。
2021-05-22 03:47:22
@andree 感谢您指出我的错字。这是一个 3 年前的帖子。显然,有很多方法可以解决 React 逃避的问题,每个开发人员都应该对此感到厌烦。
2021-05-22 03:47:22
感谢您编辑您的答案@John Ruddell。无意冒犯,但您的回答让 React 看起来比实际更安全,而且由于您的回答是第一个出现在该主题上的回答之一,我只是想指出这一点。不幸的是,这是我在整体前端(不仅仅是 React)安全性中看到的一个常见主题——表面上看起来很安全或很容易保护,但当你深入研究时,结果发现存在很大的漏洞。基本的安全问题应该有很容易找到的答案,并在某处进行了总结,不幸的是,这不是我最近的经验。
2021-06-08 03:47:22
嗯……随着时间的推移,随着安全性的测试,文档会出来。我们曾经有用的答案现在没有那么有用了。困难的部分是使所有答案与不断变化的技术保持同步
2021-06-20 03:47:22