2

我认为使用 React 的dangerouslySetInnerHTML属性将从服务器获取的标记放置在页面上是很常见的,即

const SomeComponent = () => {
  const [markup, setMarkup] = useState(null)

  useEffect(() => { 
    const resp = await fetch(...)
    setMarkup(resp.content)
  })

  return <div dangerouslySetInnerHTML={{ __hmtl: markup }} />
}

如果这是另一种情况,并且标记来自页面上的表单,这显然会带来风险,因为您无法信任表单上输入的数据,而且我们不会在此处进行任何清理。

但是,我们将从服务器返回的数据放在页面上,因此可能存在某种程度的信任。对服务器的调用发生在代码中,大概我们知道我们正在调用的 API。

但是,即使我们信任服务器,考虑来自受信任服务器的数据实际上是不明智的吗?在数据返回之前,不良行为者可以干预网络吗?

4

1 回答 1

2

完全信任的问题dangerouslySetInnerHTML

有许多理由需要采取最低限度的预防措施dangerouslySetInnerHTML。由于浏览器的逻辑是在其他地方定义的,因此其他地方就会成为故障点。

  • 用于审查和修改您如何构建 HTML 代码逻辑的内部流程是否失败?这是否允许 XSS 攻击?
  • 是否有人忘记更新 SSL 证书?域名注册?并且有人已经对其进行了网络抢注,而现在您的应用程序使用了来自被劫持域的 API?
  • DNS 名称服务器是否被黑客入侵以将您的 API 域指向不同的服务器?那么路由器或任何中间网络设备呢?
  • 你自己的服务器被黑了吗? 最不可能(眨眼),但也有可能。

安全使用dangerouslySetInnerHTML

但是,有时您需要这样做dangerouslySetInnerHTML,因为这是最简单的解决方案。 例如,通过将粗体、斜体等标记保存和存储为原始 HTML,存储、保存和检索标记非常容易。

至少,请<script>在发送给用户之前清理任何标签的数据,以绝对消除任何有害的可能性。您可以通过使用 转换您的 HTML document.createElement(),然后删除任何<script>标记节点来做到这一点。

有趣的事实:当您创建带有<script>标签的元素时,SO 的演示不喜欢它!下面的代码片段不会运行,但它确实可以在:JSBin.com 上的 Full Working Demo 上运行

var el = document.createElement( 'html' );
el.innerHTML = "<p>Valid paragraph.</p><p>Another valid paragraph.</p><script>Dangerous scripting!!!</script><p>Last final paragraph.</p>";

var scripts = el.getElementsByTagName( 'script' );

for(var i = 0; i < scripts.length; i++) {
  var script = scripts[i];
  script.remove();
}

console.log(el.innerHTML);

document.getElementById('main').append(el);

于 2020-11-12T23:08:43.937 回答