React 的一些最佳安全實踐

大家好,我是 ConardLi

React.js、Vue.js 這些現代的前端框架默認已經對安全做了非常多的考慮,但是這仍然不能阻礙我們寫出一些安全漏洞 。。。因爲框架永遠不能完全限制我們編程的靈活性,只要有一定的靈活性存在就意味着有安全風險。

下面我就帶大家一起來看一下,爲了保證我們 React 應用的安全性,有哪些值得遵循的最佳實踐。

dangerouslySetInnerHTML

React 會對默認的數據綁定 ({}) 進行自動轉義來防止 XSS 攻擊,所有數據都會認爲是 textContent

但是爲了保障開發的靈活性,它也給我們提供了一些直接渲染 HTML 的方法,比如 dangerouslySetInnerHTML

在把數據傳入 dangerouslySetInnerHTML 之前,一定要確保數據是經過過濾或轉義的,比如可以通過 dompurify.sanitize 進行過濾:

import dompurify from "dompurify";
import "./styles.css";

export default function App() {
  const code = "<input onfocus=alert(1) autofocus />";
  return (
    <div class>
      <div dangerouslySetInnerHTML={{ __html: dompurify.sanitize(code) }} />
    </div>
  );
}

避免直接操作 DOM 注入 HTML

除了 dangerouslySetInnerHTML ,我們當然還可以直接通過原生的 DOM API 來插入 HTML

另外也可以通過 ref 來訪問 DOM 來插入 HTML

這兩個操作都是相當危險的操作,推薦大家既然用了 React 就要儘量用 React 的編寫方式來寫代碼,儘量不要直接操作 DOM,如果你確實要渲染富文本,還是推薦用上面提到的 dangerouslySetInnerHTML,而且數據要經過過濾或轉義。

服務端渲染

當使用服務端渲染函數時,數據綁定也會提供自動內容轉義,比如 ReactDOMServer.renderToString()ReactDOMServer.renderToStaticMarkup()

在將字符串發送給客戶端進行注水之前,避免將字符串直接拼接到 renderToStaticMarkup() 的輸出上。

爲了避免 XSS,不要將未過濾的數據與 renderToStaticMarkup() 的輸出連接在一起:

app.get("/"function (req, res) {
  return res.send(
    ReactDOMServer.renderToStaticMarkup(
      React.createElement("h1", null, "Hello ConardLi!")
    ) + otherData
  );
});

JSON 注入

JSON 數據與服務器端渲染的 React 頁面一起發送是很常見的。始終對 < 字符進行轉義來避免注入攻擊:

window.JSON_DATA = ${JSON.stringify(jsonData).replace( /</g, '\\u003c')}

URL 注入

前面幾個基本上都是直接渲染未經過濾的富文本導致的 XSS,實際上通過 URL 僞協議也可以執行 javascript 腳本:

因此所有需要注入到代碼裏的 URL 參數,我們都要做好 URL 的合法性驗證,千萬不要直接注入進去:

import "./styles.css";

function isSafe(url) {
  if (url && !url.startsWith("http")) {
    return null;
  }
  // ... 其他判斷
}

export default function App() {
  const code = "javascript:alert('xss')";
  return (
    <div class>
      測試 URL 注入
      <a href={isSafe(code)}>一個平平無奇的鏈接</a>
    </div>
  );
}

避免有漏洞的 React 版本

React 以前也被測試出有比較高危的安全漏洞,建議經常保持更新,來避免這些有漏洞的 React 版本:

避免有漏洞的其他依賴

一般我們的項目都會依賴大量的開源代碼,有時漏洞並不是我們寫出來的,而是這些依賴帶進來的,想詳細瞭解可以看看我之前寫的這篇文章:

你必須要注意的依賴安全漏洞

因此我們無論使用任何框架,定期進行依賴更新都是不錯的選擇。

Eslint React 安全配置

推薦大家通過 EslintReact 安全配置(https://github.com/snyk-labs/eslint-config-react-security/)來對代碼進行約束,它會自動幫助我們發現一些代碼中的安全風險。

最後

參考:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KNbOa19OOnP6Rh1Uk2iotw