XSS(跨站腳本)概述
Cross-Site Scripting 簡稱為“CSS”,為避免與前端疊成樣式表的縮寫"CSS"沖突,故又稱XSS。一般XSS可以分為如下幾種常見類型:
1.反射性XSS;
2.存儲型XSS;
3.DOM型XSS;
XSS漏洞一直被評估為web漏洞中危害較大的漏洞,在OWASP TOP10的排名中一直屬于前三的江湖地位。
XSS是一種發生在前端瀏覽器端的漏洞,所以其危害的對象也是前端用戶。
形成XSS漏洞的主要原因是程序對輸入和輸出沒有做合適的處理,導致“精心構造”的字符輸出在前端時被瀏覽器當作有效代碼解析執行從而產生危害。
因此在XSS漏洞的防范上,一般會采用“對輸入進行過濾”和“輸出進行轉義”的方式進行處理:
輸入過濾:對輸入進行過濾,不允許可能導致XSS攻擊的字符輸入;
輸出轉義:根據輸出點的位置對輸出到前端的內容進行適當轉義;
pikachu之XSS
反射型xss(get)
問我喜歡的NBA球星,那必然牢大,然后直接出來頁面。
嘗試隨便輸入123,我們發現輸入的內容全都會出現在頁面上。
想直接構造<script>alert(1)</script>,但是發現一個問題,這個框框太小了不夠用...于是我們打開控制臺,找到框框的位置,將框框的20改為100,如下:
這次就能輸入了,彈框成功。
或者可以在url的參數進行操作,令參數=<script>alert(1)</script>,彈框即可
反射性xss(post)
點擊提示直接登錄,再次填入kobe。
這道題跟上題一樣,填入paylaod直接彈框,不再多說。
存儲型xss
依舊輸入<script>alert(1)</script>
反復刷新頁面,依然彈窗,說明存儲型xss是永久型的。
DOM型xss
這道題我們隨便輸入一個,發現下面生成了超鏈接,但是是一個空超鏈接,無論我們輸入什么都是這幾個字。
接下來輸入百度網址,點擊超鏈接發現可以跳轉百度。
那么猜測結構可能是<a href="我們的輸入">what do you see?</a>
這樣的話輸入" >45查看有沒有閉合成這樣:
<a src="" >45">what do you see?</a>假如成功閉合,那么超鏈接的文本應該變成
45">what do you see?
可惜沒有。
嘗試將雙引號換成單引號,成功。
輸入' οnclick=alert(1)>45
按理來說結構變成這樣,應該點擊一下就會彈框。
<a src='' onlick=alert(1)>45'>what do you see?</a>
成功。
DOM型xss-x
這里隨便輸入,然后點擊請說出你的傷心往事,然后下面又出現了一個超鏈接。
點擊超鏈接,然后又出現了一個超鏈接,并且url參數位置出現了一個#符號。
試著將輸入改為http://www.baidu.com,然后點擊請輸入你的傷心往事,發現url參數增加了我們輸入的鏈接。
點擊下面超鏈接,然后點擊出現的另外一個就讓往事都隨風,都隨風吧超鏈接,成功跳轉百度。
構造paylaod
' οnclick=alert(1)>
最終點擊就讓往事都隨風,都隨風吧成功彈窗。
源代碼如下,這里其實就是我們輸入' οnclick=alert(1)>內容會出現在url參數位置,即text=' οnclick=alert(1)>#然后點擊請說出你的傷心往事,然后就會執行domxss()函數,這個函數中的
var str =window.location.search
就是首先將url的參數從?到最后(或者#,但是不返回#)賦給str,也就是str=?text=' οnclick=alert(1)>,
然后這里var txss = decodeURIComponent(str.split("text=")[1]);,就是將str的內容按照text=進行分隔,然后存入數組。
如:[ "?", "' οnclick=alert(1)>" ],然后提取[1]位置也就是' οnclick=alert(1)>,并且賦值給txss,使用decodeURIComponent()對經過URL編碼的字符串進行解碼。
然后將txss的所有+號換成空格,隨后賦值給xss。
然后是最關鍵的
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就讓往事都隨風,都隨風吧</a>"; |
它會將"<a href='"+xss+"'>就讓往事都隨風,都隨風吧</a>";賦值給我們的名為dom屬性的內容,而xss就是' οnclick=alert(1)>,所以就是將
"<a href='' οnclick=alert(1)>'>就讓往事都隨風,都隨風吧</a>";賦值給dom,而dom就是一個顯示內容的地方,也就是顯示出來'>就讓往事都隨風,都隨風吧這個鏈接,點擊就會彈窗。
window.location.search
:這是瀏覽器提供的一個屬性,它返回當前頁面URL中從問號??
?開始到末尾(或到#
錨點,不返回最后的#)的部分,也就是查詢字符串(Query String)。示例:如果當前頁面的URL是?
https://example.com/vulnerable-page?text=<script>alert('xss')</script>&other=123
,那么?window.location.search
?的值就是?"?text=<script>alert('xss')</script>&other=123"
。
document.getElementById("dom").innerHTML
document
:代表整個HTML網頁文檔。.getElementById("dom")
:獲取元素。這是一個方法,用于在?document
?中查找一個?id
?屬性為?"dom"
?的HTML元素。.innerHTML
:獲取或設置元素的HTML內容。這個屬性代表該元素內部的所有HTML代碼。
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就讓往事都隨風,都隨風吧</a>";
在頁面上找到一個ID為?
dom
?的元素,然后把它里面的所有內容替換成一個新的超鏈接。這個新鏈接的地址(href
)來自于變量?xss
?的值,鏈接顯示的文本是“就讓往事都隨風,都隨風吧”。
xss之盲打
這道題兩個框都輸入彈框js腳本,發現頁面底下就出現了謝謝參與。。。沒什么返回
點擊提示,進入后臺界面,然后登錄管理員賬號,登錄后臺的時候彈框了。這種就是xss盲打,攻擊者無法看到攻擊是否成功,當管理員訪問后臺的時候就會執行輸入的攻擊腳本。
xss之過濾
思路一
首先輸入<script>alert(1)</script>,發現返回>。
任意輸入幾個字符,發現會原樣返回,那么肯定我們輸入的payload某被過濾了。
輸入<sad>試一下,發現被過濾。
輸入<b>abc</b>,發現<b>起作用了,abc進行了加粗,那么到這里其實可以猜測出系統可能使用了白名單,經過測試,<s>,<img src="">,<a href=""></a>也可以存活。
既然<img src="">可以存活,那么我們可以構造一個payload試一試
payload:<img src="1" οnerrοr="alert(1)">? ##因為圖片的地址不正確導致報錯從而導致onerror事件觸發,其中onerror其實也可以替代成onclick事件,通過點擊圖片觸發彈框事件。
其實<a>超鏈接標簽也存活,那么也可以想到一個思路,構造payload
payload:<a href="#" οnclick=alert(1)>鏈接</a>
其中#是一個占位符,它的作用有:
1.讓這個?<a>
?標簽保持一個合法鏈接的樣式和行為(鼠標變成小手,有鏈接顏色),但阻止它進行真正的頁面跳轉。
2.當用戶點擊這個鏈接時,瀏覽器會將頁面滾動到頂部(因為?#
?代表頁面頂部錨點)
可以使用<s>標簽,payload:
<s οnclick=alert(1)>123 ##點擊劃線123即可觸發。
思路二
我們輸入"<>'on/`() script img href src查看一下回顯,發現回顯這樣。
然后一個一個的進行測試,輸入",測試,輸入<>,測試...最終發現,如果單個輸入的話那么全部都可以輸出,這里就要大膽猜測一下了,為什么全部輸入的時候script后面的保存完好呢?當然肯定不是單獨過濾了script,因為直接輸入script的話可以輸出。反正肯定跟script有關。
嘗試輸入"script,'script,<script,>script,()script,/script...
接下來發現,除了<script以外,所有的組合全部都沒有被過濾。
嘗試輸入:<55bf58script,在<和script之間混合數據,最后發現無論混合多少數據或者不加入數據,都會被過濾,那么大膽猜測過濾了<.*script。
可以考慮大小寫繞過
payload:
<sCript>alert(1)</sCript>
<sCript>prompt(/xss/)</sCript> <sCript>prompt(`xss`)</sCript>?<sCript>prompt('xss')</sCript>
<sCript>confirm(1)</sCript>
這里既然不能使用script,就開始考慮別的如<s>,<img>標簽,這里不在贅述。
xss之htmlspecialchars
思路一
輸入<script>alert(1)</script>,發現竟然把我記錄了!當看到這種超鏈接那么背后肯定是有<a>標簽的。
查看頁面源代碼,發現<>都被編碼了,因此這關想閉合標簽是不行了。但是發現單引號沒有被html編碼,所有可以考慮閉合單引號。
payload:
#' οnclick='confirm(/xss/)'或者#' οnclick='confirm(/xss/)閉合單引號。
思路二
可以之間修改前端代碼嘗試,然后點擊超鏈接發現彈框。
htmlspecialchars()的作用就是把預定義的字符轉換為了HTML實體。預定義的字符如下:
& 成為 &
" 成為 "
' 成為 '或'
< 成為 <
> 成為 >
htmlspecialchars()函數默認是不對單引號進行轉義的,要想連單引號一起轉義,需要給函數傳入參數ENT_QUOTES,所以一般情況下如果遇到htmlspecialchars()函數的話,考慮一下單引號的閉合從而進行攻擊。
ENT_COMPAT:默認編碼,但是編碼雙引號不編碼單引號
ENT_QUOTES:編碼雙引號和單引號
ENT_NOQUOTES:不編碼任何引號
xss之href輸出
思路一
首先輸入百度網址,看一下怎么個事,然后點擊下面超鏈接跳轉到了百度頁面,這道題一想就可以知道在<a>標簽上面做手腳。
檢查代碼,然后在這里發現了我們輸入的網址。
更改為這樣
<a href="#" οnclick="confirm(`xss`)">...
點擊超鏈接發現彈框。
思路二
同樣也可以在輸入框構造,但是經過我的測試<,>,',"都被htmlspecialchars()函數編碼了,那么想要通過閉合的方法好像行不通了。
這里可以利用JavaScript協議。
payload:
javascript:alert(document.cookie)
javascript:prompt(document.cookie)
javascript:confirm(document.cookie)
輸入后點擊超鏈接發現提取了我的cookie。
解析:
javascript: 這是一個偽協議,表示接下來的內容是 JavaScript 代碼,可以在當前頁面的上下文中執行。
document.cookie: 這是一個 JavaScript 表達式,用于獲取當前頁面的 Cookie 值。Cookie 是一種用于在客戶端和服務器之間存儲數據的機制,它可以用于標識和跟蹤用戶會話狀態。xss之js輸出
xss之js輸出
輸入<script>alert(1)</script>,頁面沒變化,但是查看頁面源代碼我們發現了下面的一段javascript的if語句,其中ms的內容就是我們輸入的內容。
這里嘗試閉合,構造:';alert(1);//
完整閉合如下
通過//將';進行注釋
如果不注釋';的話,那么語句是$ms='';alert(1);';,在紅色部分語句可能會發生錯誤。
$ms='';alert(1);//';
因為alert(1)本身就在javascript腳本中,所以會直接執行。