Answers:
从设计上来说,ReactJS是相当安全的
所以像这样的典型攻击是行不通的
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>
但是...
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>
示例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>
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>
这里有更多资源
React自动为您转义变量...它可以防止通过带有恶意Javascript的字符串HTML进行XSS注入。自然,输入也将与此一起进行清理。
举例来说,假设您有这个字串
var htmlString = '<img src="javascript:alert('XSS!')" />';
如果您尝试在响应中呈现此字符串
render() {
return (
<div>{htmlString}</div>
);
}
您会在页面上从字面上看到包括<span>
元素标签在内的整个字符串。aka在浏览器中,您将看到<img src="javascript:alert('XSS!')" />
如果您查看源HTML,则会看到
<span>"<img src="javascript:alert('XSS!')" />"</span>
React基本上做到了这一点,因此除非您在render函数中自己创建元素,否则您将无法插入标记...也就是说,它们确实具有允许此类渲染其调用的功能dangerouslySetInnerHTML
... 这里是有关它的更多详细信息
没什么要注意的,有一些方法可以解决React逃脱的问题。一种更常见的方式是用户为组件定义道具。不要将用户输入的任何数据扩展为道具!