漏洞詳解。
DOM XSS(Cross-site scripting)是一種Web安全漏洞,它利用了瀏覽器的DOM(檔案物件模型)解析機制,通過注入惡意程式碼來攻擊使用者。
DOM XSS與傳統的反射型或儲存型XSS有所不同。在傳統的XSS攻擊中,攻擊者通常在網頁的URL或表單欄位中注入惡意程式碼,使用者存取網頁時惡意程式碼就會被執行。而在DOM XSS攻擊中,惡意程式碼被注入到網頁的DOM中,當用戶與網頁互動時,惡意程式碼就會被執行。
DOM XSS攻擊的危害可能比傳統的XSS攻擊更加嚴重,因為它不需要將惡意指令碼傳遞給伺服器,因此很難檢測和防止。攻擊者可以利用DOM XSS來竊取使用者的敏感資訊、執行釣魚攻擊、劫持使用者對談等。
DOM XSS漏洞的原因在於,瀏覽器在解析HTML和JavaScript時,將HTML和JavaScript混合在一起處理,因此惡意程式碼可以通過修改DOM節點或屬性來注入到網頁中。攻擊者可以通過各種方式來實現DOM XSS攻擊,例如修改URL引數、修改表單資料、使用可編輯的HTML元素等。
下面將演示一個DOM的操作範例:
<!DOCTYPE html> <html> <head> <title>DOM範例</title> </head> <body> <h1 id="title">Hello, World!</h1> <p>This is a paragraph.</p> </body> </html> JavaScript程式碼: // 獲取標題元素 var titleElement = document.getElementById("title"); // 修改標題文字 titleElement.innerHTML = "Hello, DOM!"; // 建立一個新段落元素 var newParagraph = document.createElement("p"); newParagraph.innerHTML = "This is a new paragraph."; // 將新元素插入檔案 document.body.appendChild(newParagraph);
這段程式碼首先獲取具有ID「title」的元素,並使用innerHTML
屬性將該元素的文字內容更改為「Hello,DOM!」然後,它建立一個新的段落元素,並使用createElement()
方法和innerHTML
屬性將新元素的文字內容設定為「This is a new paragraph.」最後,它使用appendChild()
方法將新元素新增到檔案中。
下面我們將對四個等級的程式碼分別進行分析。
LOW:
程式碼審計:
Unknown Vulnerability Source vulnerabilities/xss_d/source/low.php <?php # No protections, anything goes ?>
發現沒有任何資訊,直接檢視網頁原始碼(這裡擷取的是我們要分析的部分)。
<form name="XSS" method="GET"> <select name="default"> <script> if (document.location.href.indexOf("default=") >= 0) { var lang = document.location.href.substring(document.location.href.indexOf("default=")+8); document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>"); document.write("<option value='' disabled='disabled'>----</option>"); } document.write("<option value='English'>English</option>"); document.write("<option value='French'>French</option>"); document.write("<option value='Spanish'>Spanish</option>"); document.write("<option value='German'>German</option>"); </script> </select>
這段程式碼是一個HTML表單,其中包含一個下拉式選單(<select>
元素),名為default
,並使用GET方法提交資料。當頁面URL中存在default=
引數時,該引數的值將被新增到下拉式選單中作為預設選項。
下拉式選單的選項內容由JavaScript程式碼動態生成。如果URL中存在default=
引數,JavaScript將讀取該引數的值並將其新增到下拉式選單中作為第一個選項。如果沒有該引數,JavaScript將新增預設的四個選項:English、French、Spanish和German。
這裡漏洞的產生,是因為JavaScript程式碼使用了document.write
方法來將HTML程式碼動態寫入到頁面中。document.write()
是一個JavaScript方法,它可以將文字、HTML程式碼或JavaScript程式碼寫入到檔案中。這裡他沒有對使用者的輸入做任何的過濾和驗證。
漏洞利用:
http://127.0.0.1/DVWA-master/DVWA-master/vulnerabilities/xss_d/?default=<script>alert('XSS');</script>
在利用漏洞時我們只要在url中直接構建即可。
Medium:
程式碼審計:
Unknown Vulnerability Source vulnerabilities/xss_d/source/medium.php <?php // Is there any input? if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) { $default = $_GET['default']; # Do not allow script tags if (stripos ($default, "<script") !== false) { header ("location: ?default=English"); exit; } } ?>
default
引數從HTTP GET請求中傳遞過來,如果有,則將其存到變數$default
中。stripos()
函數判斷$default
字串中是否包含<script
字串,如果包含,則說明使用者嘗試注入指令碼程式碼,這時候就將請求重定向到?default=English
頁面,並終止程式碼的執行。$default
字串中不包含<script
字串,則說明使用者的請求是安全的,可以繼續在後續程式碼中使用。那麼通過程式碼審計我們可以得知對<script>標籤進行了過濾,那麼我們使用其他標籤進行攻擊。
漏洞利用:
http://127.0.0.1/DVWA-master/DVWA-master/vulnerabilities/xss_d/?default=</option></select><img src=x onerror=alert(1)>
<img>
標籤的onerror
事件屬性是一種常見的XSS攻擊方式,在原本載入圖片的過程中,如果這個圖片無法正常載入,瀏覽器就會自動執行onerror
事件屬性中的JavaScript程式碼。攻擊者可以利用這一點,將惡意程式碼放置在onerror
事件屬性中,一旦圖片載入失敗,該程式碼就會在使用者瀏覽器中執行。除此之外,還有一些標籤能進行XSS攻擊。
onload
屬性的<img>
標籤,當該標籤載入時,它可能會執行一個JavaScript函數,該函數會嘗試從瀏覽器中獲取敏感資訊。<img src="hack.gif" onload="stealInfo()">
iframe標籤。攻擊者可以向一個iframe
標籤中參照一個惡意網站,該網站可能包含一個惡意指令碼,該指令碼可能會執行跨源攻擊。
a標籤。攻擊者可以在一個<a>
標籤中插入一個惡意的href
屬性,該屬性將指向一個惡意網站,當用戶點選該連結時,它可能會導致跨站點指令碼攻擊。
High:
程式碼審計:
Unknown Vulnerability Source vulnerabilities/xss_d/source/high.php <?php // Is there any input? if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) { # White list the allowable languages switch ($_GET['default']) { case "French": case "English": case "German": case "Spanish": # ok break; default: header ("location: ?default=English"); exit; } } ?>
這裡進行了白名單驗證。程式碼首先檢查 GET 請求是否具有名為 'default' 的引數,並且該引數的值不為空。如果存在該引數,則使用 switch 語句對該引數進行檢查,檢查是否包含在允許列表中(指定為 "French", "English", "German" 或 "Spanish")。如果在允許列表中,則不進行任何操作,否則,將網頁重定向到同一頁面,但將 'default' 引數設定為英語("English")。
漏洞利用:
http://127.0.0.1/DVWA-master/DVWA-master/vulnerabilities/xss_d/?default=English#</option></select><BODY ONLOAD=alert(document.cookie)>
可以看到我們在default引數值後加上了#,需要注意的是,#號註釋掉的原有程式碼並不會影響新插入的程式碼的執行,因為#號會把其後面的內容都註釋掉,而不會對其前面的程式碼造成影響。
Impossible:
程式碼審計:
Unknown Vulnerability Source vulnerabilities/xss_d/source/impossible.php <?php # Don't need to do anything, protection handled on the client side ?>
<form name="XSS" method="GET"> <select name="default"> <script> if (document.location.href.indexOf("default=") >= 0) { var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
// 這裡的語句變了,並沒有對我們輸入的內容進行URL解碼,所以我們輸入的任何內容都是經過URL編碼,然後直接賦值。因此不存在XSS漏洞。 document.write("<option value='" + lang + "'>" + (lang) + "</option>"); document.write("<option value='' disabled='disabled'>----</option>"); } document.write("<option value='English'>English</option>"); document.write("<option value='French'>French</option>"); document.write("<option value='Spanish'>Spanish</option>"); document.write("<option value='German'>German</option>"); </script> </select>
防禦方法:
對使用者輸入進行過濾和驗證:在使用者端和伺服器端都需要對使用者輸入進行正規表示式匹配和過濾,以確保使用者輸入不包含任何可疑字元或程式碼。
使用CSP:Content Security Policy (CSP)可以限制從哪些源載入資源(如指令碼、影象、CSS等),以及哪些動作允許執行(如eval()、setTimeout()等)。通過在HTTP響應頭設定CSP策略,可以防止XSS攻擊。
消除DOM XSS源:通過使用框架或庫提供的API,可以有效地避免DOM型XSS攻擊。例如,使用jQuery的.text()和.html()方法來插入文字和HTML,而不是使用.innerHTML屬性,可以避免一些DOM XSS攻擊。
對JavaScript API進行限制:在某些情況下,為了保護網站免受XSS攻擊,可以通過限制JavaScript API的存取來實現。例如,可以對document.cookie進行限制,可以使用HttpOnly標誌來防止JavaScript存取cookie。
對輸入進行編碼:將使用者輸入作為HTML、CSS或JavaScript的字串進行編碼,以確保任何使用者輸入都不會被執行為惡意程式碼。
總之,防止DOM型XSS攻擊需要綜合使用上述措施,特別是對使用者輸入進行過濾和驗證,並使用CSP限制惡意資源的載入和動作的執行。