首發tools:https://www.t00ls.net/thread-59512-1-1.html
存儲型XSS
最近做測試的時候碰到了一個前端頁面使用了Vue框架的項目
在測試XSS漏洞的過程中通過保存構造的Payload后發現頁面顯示不正常,這讓我覺得肯定有戲
事不宜遲,翻看JS源代碼發現一個名為project_name屬性的值被構造的單引號閉合了,導致語句出錯。可以看到它在這里實例了一個Vue構造器,在el 屬性中使用id選擇器將該實例指向了頁面上id 為 mainbody的div元素。
可控點為project_name屬性的值,這個屬性是用來渲染編輯框內容的,既然這里直接將惡意語句輸出在了js里,那么我們就不用考慮頁面的渲染問題了,直接在數據屬性data區構造一個任意屬性,在賦值屬性時執行我們的alert()函數進行彈窗,構造Payload,
',x:alert(/xss/),//
保存Payload
成功彈窗
下面來分析一下payload,'
用於閉合前面的屬性值,,
分割屬性,構造一個x
屬性,執行彈窗函數alert(),//
注釋掉后面的單引號防止報錯停止執行
反射型XSS
我們再來看另一個反射型XSS,這次的觸發點位於這三個欄目頁面中,可控點是getDefectTree方法內的axios請求參數jid,該方法位於Vue綁定的方法methods中。這里也使用了單引號賦值屬性,而該系統后端轉義了雙引號沒有轉義單引號導致此處被閉合。
追蹤調用過程發現是某個按鈕點擊事件
那么現在想要讓他自動執行的話有兩個思路,一個是在Vue內構造,一個是閉合Vue
Vue內構造
先來看看Vue內構造,在Vue組件的生命周期中有這幾個鈎子函數
beforecreate: 一般使用場景是在加 loading事件 的時候
created :處於loading結束后,還做一些初始化,實現函數自執行(data數據已經初始化,但是DOM結構渲染完成,組件沒有加載)
beforemount:處於組件創建完成,但未開始執行操作
mounted :處於發起后端請求,獲取數據,配合路由鈎子執行操作(DOM渲染完成,組件掛載完成 )
beforeupdate、updated:處於數據更新的前后
beforeDestroy:當前組件還在的時候,想刪除組件
destroyed:當前組件已被銷毀,清空相關內容
我們可以構造一個方法,然后構造生命周期鈎子函數,利用指定的生命周期函數在實例加載前后自動執行綁定的方法。可利用的鈎子函數為created
和mounted
。這里就選擇created作為Payload,構造Payload
new Vue({
el: "#mainbody",
data: {},
created(){
this.test()
},
methods: {
test(){
alert(1)
}
}
})
可以看到在實例Vue時,在created鈎子函數中執行了我們構造的test方法成功彈窗,test方法內存在惡意代碼。
接下來直接將觸發點處小段代碼精簡后Copy到控制台進行構造,這樣對括號的閉合有幫助,因為有閉合提示。
new Vue({
el: "#mainbody",
data: {},
methods: {
getDefectTree(func){
axios.get("", {
params: {
jid: '11',//可控點
}
})
.then(function (response) {
})
}
}
})
首先要閉合params參數,構造'}
,
然后閉合axios,構造'}})
因為這個函數沒有自動執行,所有我們還需要跳出這個函數和methods方法區,構造'}})}}
跳出方法區后就可以構造生命周期鈎子函數了,構造'}})}},created(){this.test()}
這時前面已經處理完了,我們現在開始閉合后面的括號,后面的按照閉合點前到methods的寫法炮制一番即可,構造'}})}},created (){this.test()},methods: {go(){axios.get("", {params: {//
,記得注釋掉最后的單引號
沒有報錯,離成功又進了一步,下面在構造的methods中新建一個方法test,將彈窗代碼置於其中即可,構造'}})}},created (){this.test()},methods: {test(){alert(/test/)},go(){axios.get("", {params: {//
get,下面就將Payload復制到url進行測試,
可以看到成功彈框,這里其實還有一種方法就是構造一個數據區,這樣也能觸發而且簡短一點,Payload'}})}},data:{x:alert(/test/)},methods: {go(){axios.get("", {params: {//
閉合Vue
閉合Vue的話只需要考慮前面一個花括號,一個圓括號,后面部分new 一個Vue實例和前面保持一致即可。Payload:'}})}}});alert(1);new Vue({methods: {go(){axios.get("", {params: {//