危险的SetInnerHTML的安全替代品

时间:2015-03-14 01:40:52

标签: reactjs

我想在我的网站上使用动态博客(使用React)。最初,我打算将帖子存储在我的数据库中的原始HTML中,并使用dangerouslySetInnerHTML生成内容。然而,我担心安全问题。虽然我的应用程序没有任何敏感数据,但我不熟悉XSS,知道我打开我的应用程序所带来的所有危险。

我很好奇是否有一种在我的应用中动态加载博客页面的高效,安全的方法。在这种情况下使用https://github.com/odysseyscience/react-router-proxy-loader会有用吗?有一个博客文件夹JSX与我的应用程序的其余部分分开并使用它加载它(诚然,我不确定react-router-proxy-loader如何工作)。

我愿意接受建议。

谢谢,

凯文

6 个答案:

答案 0 :(得分:33)

如果您主要关注XSS,可以使用DOMPurify清理HTML,然后再通过dangerouslySetInnerHTML将其插入DOM。它只有10K缩小了。 And it works in Node too.

答案 1 :(得分:7)

https://facebook.github.io/react/tips/dangerously-set-inner-html.html

“故意命名dangerouslySetInnerHTML被故意选为令人恐惧的......”

“在充分了解安全后果并正确清理数据之后......”

我认为,如果您信任自己的CMS /服务器(而不是从第三方接收),它已经清理了数据(此步骤也已完成),那么您可以使用dangerouslySetInnerHTML进行插入。

正如Morhaus所说,也许使用DOMPurify,因为它(奖励)可能处理这个不幸的一点:“所以提供的HTML必须是格式良好的(即,通过XML验证)。”我怀疑使用HTML5的非XML版本的某些内容可能会成为一个问题。 (注意:我还没有自己使用它,因为我很喜欢你。)

答案 2 :(得分:2)

如其他答案所述,许多库(dompurifyxss 等)可以解析您提供给浏览器的 HTML,删除任何恶意部分并安全地显示它。

问题是:你如何强制使用这些库。

为此,您可以安装 RisXSS,这是一个 ESLint 插件,它会警告 dangerouslySetInnerHTML 如果 您之前没有对其进行消毒(从某种意义上说,这是 react/no-danger ESLint 规则的改进版本)。

为此,请安装 dompurifyeslint-plugin-risxss

npm install dompurify eslint-plugin-risxss

risxss 添加到您的 ESLint 插件,然后使用 DOMPurify:

import { sanitize } from 'dompurify';

export const MyArticle = ({ post }) => (
  <>
    <div dangerouslySetInnerHTML={{ post.content }} /> {/* You will receive a warning */}
    <div dangerouslySetInnerHTML={{ __html: sanitize(post.content) }} /> {/* All good here */}
  </>
);

免责声明:我是 RisXSS 插件的贡献者。

答案 3 :(得分:1)

如果您确定输入HTML是安全的(没有XSS风险)但可能格式不正确(例如,文本中有随机class YourCollectionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('categoriesConfigs', CollectionType::class, array( 'entry_type' => CategoriesConfigType::class, 'entry_options' => array('required' => false) ); } } ),并且您想要防止你的应用程序因为意外的DOM更改而失败,那么你可以试试这个:

<

(基于https://stackoverflow.com/a/14216406/115493

但如果您对您的HTML可能不是XSS安全有任何疑问,请使用上面提到的DOMPurify。

答案 4 :(得分:1)

我遇到了同样的问题,并以更好的解决方案结束。如果您使用lodash

输入类似下面的信息并且解决方案适合您
&lt;em&gt;paragraph text example:&lt;/em&gt;

我的解决方案:

import _ from 'lodash';

const createMarkup = encodedHtml => ({
  __html: _.unescape(encodedHtml),
});

/* eslint-disable react/no-danger */
const Notes = ({ label }) => (
  <div>
    <div dangerouslySetInnerHTML={createMarkup(label)} />
  </div>
);

答案 5 :(得分:0)

文章How to prevent XSS attacks when using dangerouslySetInnerHTML in React建议使用jam3 / no-sanitizer-with-danger eslint规则检查传递给危险SetInnerHTML的内容是否包装在此消毒剂函数中

有效代码示例为

const sanitizer = dompurify.sanitize;
return <div dangerouslySetInnerHTML={{__html: sanitizer(title)}} />; // Good

它还描述了3个消毒剂库:
DOMPurify
Xss
xss-filters