<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          React 怎么實(shí)現(xiàn)預(yù)防XSS 攻擊的

          共 2235字,需瀏覽 5分鐘

           ·

          2020-12-03 12:15

          本文首發(fā)于政采云前端團(tuán)隊(duì)博客:淺談 React 中的 XSS 攻擊

          https://www.zoo.team/article/xss-in-react


          前言

          前端一般會(huì)面臨 XSS 這樣的安全風(fēng)險(xiǎn),但隨著 React 等現(xiàn)代前端框架的流行,使我們?cè)谄綍r(shí)開(kāi)發(fā)時(shí)不用太關(guān)注安全問(wèn)題。以 React 為例,React 從設(shè)計(jì)層面上就具備了很好的防御 XSS 的能力。本文將以源碼角度,看看 React 做了哪些事情來(lái)實(shí)現(xiàn)這種安全性的。

          XSS 攻擊是什么

          Cross-Site Scripting(跨站腳本攻擊)簡(jiǎn)稱 XSS,是一種代碼注入攻擊。XSS 攻擊通常指的是利用網(wǎng)頁(yè)的漏洞,攻擊者通過(guò)巧妙的方法注入 XSS 代碼到網(wǎng)頁(yè),因?yàn)闉g覽器無(wú)法分辨哪些腳本是可信的,導(dǎo)致 XSS 腳本被執(zhí)行。XSS 腳本通常能夠竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶,調(diào)用目標(biāo)網(wǎng)站接口并執(zhí)行攻擊者指定的操作。

          XSS 攻擊類型

          反射型 XSS

          • XSS 腳本來(lái)自當(dāng)前 HTTP 請(qǐng)求
          • 當(dāng)服務(wù)器在 HTTP 請(qǐng)求中接收數(shù)據(jù)并將該數(shù)據(jù)拼接在 HTML 中返回時(shí),例子:
          //?某網(wǎng)站具有搜索功能,該功能通過(guò) URL 參數(shù)接收用戶提供的搜索詞:
          https://xxx.com/search?query=123
          //?服務(wù)器在對(duì)此 URL 的響應(yīng)中回顯提供的搜索詞:
          <p>您搜索的是:?123p>
          //?如果服務(wù)器不對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)義等處理,則攻擊者可以構(gòu)造如下鏈接進(jìn)行攻擊:
          https://xxx.com/search?query=
          //?該 URL 將導(dǎo)致以下響應(yīng),并運(yùn)行 alert('xss'):
          <p>您搜索的是:?<img?src=""?onerror?="alert('xss')">p>
          //?如果有用戶請(qǐng)求攻擊者的 URL ,則攻擊者提供的腳本將在用戶的瀏覽器中執(zhí)行。

          存儲(chǔ)型 XSS

          • XSS 腳本來(lái)自服務(wù)器數(shù)據(jù)庫(kù)中
          • 攻擊者將惡意代碼提交到目標(biāo)網(wǎng)站的數(shù)據(jù)庫(kù)中,普通用戶訪問(wèn)網(wǎng)站時(shí)服務(wù)器將惡意代碼返回,瀏覽器默認(rèn)執(zhí)行,例子:
          //?某個(gè)評(píng)論頁(yè),能查看用戶評(píng)論。
          //?攻擊者將惡意代碼當(dāng)做評(píng)論提交,服務(wù)器沒(méi)對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)義等處理
          //?評(píng)論輸入:
          <textarea>
          ??<img?src=""?onerror?="alert('xss')">
          textarea>
          //?則攻擊者提供的腳本將在所有訪問(wèn)該評(píng)論頁(yè)的用戶瀏覽器執(zhí)行

          DOM 型 XSS

          該漏洞存在于客戶端代碼,與服務(wù)器無(wú)關(guān)

          • 類似反射型,區(qū)別在于 DOM 型 XSS 并不會(huì)和后臺(tái)進(jìn)行交互,前端直接將 URL 中的數(shù)據(jù)不做處理并動(dòng)態(tài)插入到 HTML 中,是純粹的前端安全問(wèn)題,要做防御也只能在客戶端上進(jìn)行防御。

          React 如何防止 XSS 攻擊

          無(wú)論使用哪種攻擊方式,其本質(zhì)就是將惡意代碼注入到應(yīng)用中,瀏覽器去默認(rèn)執(zhí)行。React 官方中提到了 React DOM 在渲染所有輸入內(nèi)容之前,默認(rèn)會(huì)進(jìn)行轉(zhuǎn)義。它可以確保在你的應(yīng)用中,永遠(yuǎn)不會(huì)注入那些并非自己明確編寫(xiě)的內(nèi)容。所有的內(nèi)容在渲染之前都被轉(zhuǎn)換成了字符串,因此惡意代碼無(wú)法成功注入,從而有效地防止了 XSS 攻擊。我們具體看下:

          自動(dòng)轉(zhuǎn)義

          React 在渲染 HTML 內(nèi)容和渲染 DOM 屬性時(shí)都會(huì)將 "'&<> 這幾個(gè)字符進(jìn)行轉(zhuǎn)義,轉(zhuǎn)義部分源碼如下:

          for?(index?=?match.index;?index???switch?(str.charCodeAt(index))?{
          ????case?34:?//?"
          ??????escape?=?'"';
          ??????break;
          ????case?38:?//?&
          ??????escape?=?'&';
          ??????break;
          ????case?39:?//?'
          ??????escape?=?''';
          ??????break;
          ????case?60:?//?<
          ??????escape?=?'<';
          ??????break;
          ????case?62:?//?>
          ??????escape?=?'>';
          ??????break;
          ????default:
          ??????continue;
          ????}
          ??}

          這段代碼是 React 在渲染到瀏覽器前進(jìn)行的轉(zhuǎn)義,可以看到對(duì)瀏覽器有特殊含義的字符都被轉(zhuǎn)義了,惡意代碼在渲染到 HTML 前都被轉(zhuǎn)成了字符串,如下:

          //?一段惡意代碼
          ""?onerror?="alert('xss')">?
          //?轉(zhuǎn)義后輸出到?html?中
          ?

          這樣就有效的防止了 XSS 攻擊。

          JSX 語(yǔ)法

          JSX 實(shí)際上是一種語(yǔ)法糖,Babel 會(huì)把 JSX 編譯成 React.createElement() 的函數(shù)調(diào)用,最終返回一個(gè) ReactElement,以下為這幾個(gè)步驟對(duì)應(yīng)的代碼:

          //?JSX
          const?element?=?(
          ??<h1?className="greeting">
          ????Hello,?world!
          ??h1>

          );
          //?通過(guò)?babel?編譯后的代碼
          const?element?=?React.createElement(
          ??'h1',
          ??{className:?'greeting'},
          ??'Hello,?world!'
          );
          //?React.createElement()?方法返回的?ReactElement
          const?element?=?{
          ??$$typeof:?Symbol('react.element'),
          ??type:?'h1',
          ??key:?null,
          ??props:?{
          ????children:?'Hello,?world!',
          ??????className:?'greeting'???
          ??}
          ??...
          }

          我們可以看到,最終渲染的內(nèi)容是在 Children 屬性中,那了解了 JSX 的原理后,我們來(lái)試試能否通過(guò)構(gòu)造特殊的 Children 進(jìn)行 XSS 注入,來(lái)看下面一段代碼:

          const?storedData?=?`{
          ??"ref":null,
          ??"type":"body",
          ??"props":{
          ??"dangerouslySetInnerHTML":{
          ??"__html":"
          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩五码| 国产欧美在线精品日韩 | 中文字幕有码在线观看 | 成人午夜爽爽爽 | 手机毛片网站 |