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

我在反应教程上看到的,这是什么意思?

反应是安全的。我们不生成 HTML 字符串,所以 XSS 保护是默认的。

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

89555 次浏览

React 会自动转义变量... 它防止通过带有恶意 Javascript 的字符串 HTML 注入 XSS。.当然,输入也会与此一起进行消毒。

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

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

如果您尝试呈现此字符串以进行响应

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

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

如果你查看源代码 html 你会看到

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

下面是关于什么是 XSS 攻击的更多细节

React 基本上使得你不能插入标记,除非你自己创建渲染函数中的元素... 也就是说,他们确实有一个允许这样渲染的函数,称为 dangerouslySetInnerHTML... 这里有更多关于它的细节


编辑:

几乎没有什么值得注意的,有办法可以避开 React 逃脱的东西。一种更常见的方法是当用户为您的组件定义道具时。不要扩展任何数据从用户输入作为道具!

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 攻击载体,您需要处理自己在反应!

1. XSS via dangerouslySetInnerHTML

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

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. XSS via a.href 属性

示例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 通过攻击者控制的道具

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>

这里有更多的资源