亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React怎么防止XSS攻擊論$$typeof的作用

發布時間:2022-07-28 10:45:01 來源:億速云 閱讀:139 作者:iii 欄目:開發技術

這篇文章主要介紹了React怎么防止XSS攻擊論$typeof的作用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇React怎么防止XSS攻擊論$typeof的作用文章都會有所收獲,下面我們一起來看看吧。

    JSX

    先來簡單復習一下 JSX 的基礎知識。JSX 是React.createElement的語法糖

    <div id="container">hello</div>

    經過 babel 編譯后:

    React.createElement(
      "div" /* type */,
      { id: "container" } /* props */,
      "hello" /* children */
    );

    React.createElement最終返回的結果就是一個對象,如下:

    {
      type: 'div',
      props: {
        id: 'container',
        children: 'hello',
      },
      key: null,
      ref: null,
      $$typeof: Symbol.for('react.element'),
    }

    這就是一個 React element 對象。

    我們甚至可以在代碼中直接寫 React element 對象,React 照樣能正常渲染我們的內容:

    render() {
      return (
        <div>
          {{
            $$typeof: Symbol.for('react.element'),
            props: {
              dangerouslySetInnerHTML: {
                __html: '<img src="x" onerror="alert(1)">'
              },
            },
            ref: null,
            type: "div",
          }}
        </div>
      );
    }

    可以復制這段代碼本地運行一下,可以發現瀏覽器彈出一個彈窗,并且img已經插入了 dom 中。

    這里,$$typeof 的作用是啥?為什么使用 Symbol() 作為值?

    在了解之前,我們先來簡單看下 XSS 攻擊

    XSS 攻擊

    我們經常需要構造 HTML 字符串并插入到 DOM 中,比如:

    const messageEl = document.getElementById("message");
    var message = "hello world";
    messageEl.innerHTML = "<p>" + message + "</p>";

    頁面正常顯示。但是如果我們插入一些惡意代碼,比如:

    const messageEl = document.getElementById("message");
    var message = '<img src onerror="alert(1)">';
    messageEl.innerHTML = "<p>" + message + "</p>";

    此時頁面就會彈出一個彈窗,彈窗內容顯示為 1

    因此,直接使用 innerHTML 插入文本內容,存在 XSS 攻擊的風險

    防止 XSS 攻擊的方法

    為了解決類似的 XSS 攻擊方法,我們可以使用一些安全的 API 添加文本內容,比如:

    • 使用 document.createTextNode('hello world') 插入文本節點。

    • 或者使用 textContent 而不是 innerHTML 設置文本內容。

    • 對于一些特殊字符,比如 <>,我們可以進行轉義,將其轉換為 &#60; 以及 &#62;

    • 對于富文本內容,我們可以設置黑名單,過濾一些屬性,比如 onerror 等。

    React 對于文本節點的處理

    React 使用 createTextNode 或者 textContent 設置文本內容。

    對于下面的代碼:

    render() {
      const { count } = this.state
      return (
        <div onClick={() => this.setState({ count: count + 1})}>
          {count}
        </div>
      );
    }

    React 在渲染過程中會調用setTextContent方法為div節點設置內容,其中,第一次渲染時,直接設置div節點的textContent,第二次或者第二次以后的更新渲染,由于第一次設置了textContent,因此divfirstChild值存在,是個文本節點。此時直接更新這個文本節點的nodeValue即可

    var setTextContent = function (node, text) {
      if (text) {
        var firstChild = node.firstChild;
        // 如果當前node節點已經設置過textContent,則firstChild不為空,是個文本節點TEXT_NODE
        if (
          firstChild &&
          firstChild === node.lastChild &&
          firstChild.nodeType === TEXT_NODE
        ) {
          firstChild.nodeValue = text;
          return;
        }
      }
      // 第一次渲染,直接設置textContent
      node.textContent = text;
    };

    綜上,對于普通的文本節點來說,由于 React 是采用 textContent 或者 createTextNode 的方式添加的,因此是不會存在 XSS 攻擊的,即使上面示例中,count 的值為 '<img src="x" onerror="alert(1)">'也不會有被攻擊的風險

    dangerouslySetInnerHTML 處理富文本節點

    有時候我們確實需要顯示富文本的內容,React 提供了dangerouslySetInnerHTML方便我們顯式的插入富文本內容

    render() {
      return (
        <div
          id="dangerous"
          dangerouslySetInnerHTML={{ __html: '<img src="x" onerror="alert(1)">' }}
        >
        </div>
      );
    }

    React 在為 DOM 更新屬性時,會判斷屬性的key是不是dangerouslySetInnerHTML,如果是的話,調用setInnerHTML 方法直接給 dom 的innerHTML屬性設置文本內容

    function setInitialDOMProperties(
      tag,
      domElement,
      rootContainerElement,
      nextProps
    ) {
      for (var propKey in nextProps) {
        if (propKey === "dangerouslySetInnerHTML") {
          var nextHtml = nextProp ? nextProp.__html : undefined;
          if (nextHtml != null) {
            setInnerHTML(domElement, nextHtml);
          }
        }
      }
    }
    var setInnerHTML = function (node, html) {
      node.innerHTML = html;
    };

    可以看出,React 在處理富文本時,也僅僅是簡單的設置 DOM 的innerHTML屬性來實現的。

    對于富文本潛在的安全風險,交由開發者自行把控。

    $$typeof 的作用

    render() {
      const { text } = this.state
      return (
        <div>
          {text}
        </div>
      );
    }

    假設這個text是從后端返回來的,同時后端允許用戶存儲 JSON 對象,如果用戶傳入下面這樣的一個類似 React element 的對象:

    {
      type: "div",
      props: {
        dangerouslySetInnerHTML: {
          __html: '<img src="x" onerror="alert(1)">'
        },
      },
      ref: null
    }

    別忘了前面說過,我們在 JSX 中直接插入 React element 對象也是能夠正常渲染的。

    在這種情況下,在React0.13版本時,這是一個潛在的XSS攻擊,這個漏洞源于服務端。如果攻擊者惡意偽造一個類似 React element 對象的數據返回給前端,React 就會執行惡意代碼。但是 React 可以采取措施預防這種攻擊。

    React0.14版本開始,React 為每個 element 都添加了一個Symbol標志:

    {
      $$typeof: Symbol.for('react.element'),
      props: {
        id: 'container'
      },
      ref: null,
      type: "div",
    }

    這個行得通,是因為 JSON 不支持Symbol。因此即使是服務端有風險漏洞并且返回一個 JSON,這個 JSON 也不會包含Symbol.for('react.element').,在 Reconcile 階段,React 會檢查element.$$typeof標志是否合法。不合法的話直接報錯,React 不能接受對象作為 children

    專門使用 Symbol.for() 的好處是, Symbols 在 iframe 和 worker 等環境之間是全局的。因此,即使在更奇特的條件下,Symbols 也能在不同的應用程序之間傳遞受信任的元素。同樣,即使頁面上有多個 React 副本,它們仍然可以“同意”有效的 $$typeof 值

    如果瀏覽器不支持Symbols,React 使用0xeac7代替

    {
      $$typeof: '0xeac7',
    }

    關于“React怎么防止XSS攻擊論$typeof的作用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“React怎么防止XSS攻擊論$typeof的作用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    周至县| 南溪县| 池州市| 蓬溪县| 明光市| 固阳县| 科技| 清丰县| 酉阳| 鹰潭市| 永州市| 伊通| 溧阳市| 江油市| 永宁县| 吕梁市| 揭西县| 安顺市| 称多县| 牟定县| 中西区| 江城| 百色市| 嘉鱼县| 乳山市| 泰宁县| 崇文区| 通渭县| 潜江市| 库伦旗| 玉林市| 房山区| 安岳县| 台州市| 喜德县| 巴彦淖尔市| 城步| 凤台县| 郧西县| 霍州市| 九江县|