XSS(Cross-Site Scripting)即为跨站脚本攻击。XSS-Lab是一个XSS的练习平台。可以在BUUOJ上很方便的进行练习。以下是我在做XSS-Lab的时候总结的题解和一些思路,给想要刷题的同学提供一些参考。
1.通用payload
<script>alert(1)</script>
可以直接加入新标签 level1
闭合原有标签后可以加入新标签 level2
οnmοuseοver='javascript:alert(1)'或者οnmοuseοver=alert(1)
使用了html实体编码 level3 level17 level18
闭合原有标签后过滤了<和> level4
οnclick=alert(1)
闭合原有标签后过滤了<和> level10
<a href=javascript:alert(1)>
绕过过滤了<script>和onmouseover level5
<a img=0 οnerrοr=alert(1)>
没有现成可填充标签且过滤了script level16
Tips
过滤<script>可以<Script>也可以<script >(空格只能在结尾)level6
绕过使用str_replace过滤为空,双写法 level7
对payload进行html编码绕过 level8 level9
空格可以用%0a替换 level16
通过改HTTP头部来做到XSS
HTTP_REFERER 在HTTP头中加入Referer level11
HTTP_USER_AGENT 在HTTP头中加入User-Agent level12
COOKIE在HTTP头中加入COOKIE信息 level13
angular中ng-include函数,可以包含外部的html页面。在服务器上写一个弹窗的页面,在原来的页面包含此页面。
绕过CORS可以使用加入使用在HTTP头中加入允许所有域名访问。level-15
2.题解
level-1
进入页面,给出了一个参数是name,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<h2>xxx</h2>标签中
所以我们直接尝试弹窗,构造payload为test<script>alert(123)</script>
level-2
进入页面,给出了一个参数是keyword,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<input name=keyword value="test">中
如果我们想要插入alert的代码,我们可以尝试构造如下
进入页面,我们直接尝试弹窗,构造payload为"><script>alert(1)</script>
level-3
进入页面,给出了一个参数是keyword,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<input name=keyword value='test'>中
和上道题目类似,只不过此时用来闭合value的为单引号,我们尝试payload为'><script>alert(1)</script>,查看源代码如下图
我们输入的<和>被转义成了<和>
查找资料,这里采用了实体编码htmlspecialchars,htmlspecialchars() 函数可以把一些预定义的字符转换为 HTML 实体。
可用的引号类型:
ENT_COMPAT 默认 仅编码双引号
ENT_QUOTES 编码双引号和单引号
ENT_NOQUOTES 不编码任何引号
所以此处我们不能选择有<和>的方式,但是可以使用不带有尖括号的特殊字符进行尝试:
onmouseover函数在鼠标指针移动到元素上被触发,onmouseover = 'javascript:alert(1)',在鼠标指针移动到元素会弹窗alert(1)。
闭合引号,构造payload为'onmouseover = 'javascript:alert(1)
level-4
进入页面,给出了一个参数是keyword,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<input name=keyword value='test'>中
用来闭合value的为双引号,我们尝试payload为"><script>alert(1)</script>,查看源代码如下图
当我们传入的payload中包含<和>就会被删除,所以和上道题一样,我们传入的payload中不能包含<和>,根据上道题的经验构造payload为"onmouseover = "javascript:alert(1)(注意此时用来闭合的为")
level-5
进入页面,给出了一个参数是keyword,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<input name=keyword value='test'>中
用来闭合value的为双引号,我们尝试payload为"><script>alert(1)</script>,查看源代码如下图
我们传入的payload中的<script>被替换成了</scr_ipt>。
构造payload为" οnmοuseοver="javascript:alert(1)
image-20220206000322694
我们传入的payload中的onmouseover被替换成了o_nmouseover。
有什么解决方法呢?
使用大小写绕过,html对大小写不敏感
可以使用超链接的方式<a href="javascript:alert(1)">,注意闭合标签,构造payload为test"><a href="javascript:alert(1)
这里对script的过滤是对<script进行的过滤,若是对整体<script>过滤的话,我们可以使用<script >来绕过.
空格只能加在尾部,< script>是不符合要求的。
以下我们使用超链接的方法绕过
此时的页面有一个_
点击此处
level-6
大小写过滤
进入页面,给出了一个参数是keyword,我们尝试传入参数为test,查看源代码,如下图,此时的参数是在<input name=keyword value="test">中
用来闭合value的为双引号,我们还是尝试payload为"><script>alert(1)</script>,查看源代码如下图
<script>还是被过滤了
onmouseover和href都被过滤了,我们就直接使用大小写过滤就轻松绕过了。
payload为"><Script>alert(1)</scripT>
level1-level6 都比较容易盲测
从level7开始,个人建议在对照github上的源码再进行练习。
level-7
4
直接看源代码
使用php中的str_replace函数对script,on,src,data,href进行了过滤,将关键字替换为空,且无法使用大小写绕过。但是str_replace函数只会替换一次,因此我们可以使用双写来绕过。
payload为test" oonnmouseover="javascript:alert(1),构成的完成句子如下
<input name=keyword value="test" oonnmouseover="javascript:alert(1)">
level-8
html编码绕过过滤
直接看源代码
本题在level-7的基础上多过滤了一个",且关键词不是被过滤为空,所以不能用双写的方法绕过。我们level-7的paylaod无法使用,我们此时可以构成的是payload恰好可以在<a>标签里面,自然而然就想到构成<a href="javascript:alert(1)">,payload为javascript:alert(1)。
将javascript代码使用html编码,就可以避免payload中的script被过滤了。
payload为javascript:alert(1)
level-9
本题在level-8的基础上,payload中必须要包含http。我们可以直接用注释符将后来的内容注释掉,我们填进去的http://不会对原来的句子造成影响。payload为javascript:alert(1) //http://,填充payload之后如下:
再使用html编码之后,payload为javascript:alert(1) //http://
level-10
发现str33是可以通过t_sort传入参数的。
可以使用payload为?t_sort=test" type="text" οnmοuseοver="javascript:alert(1)
当然也可以使用onclick属性构成payload为?t_sort=test type="text" οnclick=alert(1)
此时构成的input如下
level 11-level13 都是通过更改HTTP头来做到XXS
level-11
HTTP_REFERER
在HTTP头中加入Referer
进入页面,直接查看源代码,如下图所示。
尝试传入参数,发现只有t_sort是可用的,但是引号会被转义,传入的payload中的引号同时也被转义。目前看起来没有什么可以利用的点。
查看源代码
查看源代码可知,HTTP_REFERER过滤了<和>之后赋值给了t_ref,我们可以构造$str33为test" type="text" οnclick="alert(1),此时构成的标签如下:
可以使用burp在HTTP头中加入Referer: test" type="text" οnclick="alert(1),这样就可以发送HTTP_REFERER。
level-12
HTTP_USER_AGENT
在HTTP头中加入User-Agent
直接查看源码
和level-11类似,只不过这次要添加的头部信息是HTTP_USER_AGENT,$str33为test" type="text" οnclick="alert(1)"
此时input标签内容如下
利用burp改包
level-13
COOKIE
在HTTP头中加入COOKIE信息
直接查看源码
和level-11类似,只不过这次要添加的头部信息是$_COOKIE,$str33为test" type="text" οnclick="alert(1)"
此时input标签内容如下
利用burp改包
level-14
level-14的环境出现问题
level-15
angular中ng-include函数,可以包含外部的html页面。
在服务器上写一个弹窗的页面,在原来的页面包含此页面。绕过CORS可以使用加入使用在HTTP头中加入允许所有域名访问。
ng-include是Angularjs中的指令,可以包含外部的html文件。所以我们可以用来包含一个存在XSS的页面,最简单的思路就是包含一个前面我们已经打通的页面,但是并没有打通。
另辟蹊径,我们也可以自己在服务器上传一个存在XSS的页面,然后payload中包含这个页面。
构造存在XSS的页面的代码如下:
payload为src='http://xxx.xxx.xxx.xxx.xxx'
但是并没有成功,检查一下页面
注意到因为CORS被阻拦,我们在HTTP头中加入允许所有域名访问
level-16
没有现成可填充标签且过滤了script标签
<a img=0 οnerrοr=alert(1)>
查看源码
我们通过get参数传入的keyword,过滤了/,,script,可以显示在中间的位置。
构造payload为<img src=0 οnerrοr=alert(1)>,过滤的空格可以用%0a替换,最终的为?payloadkeyword=<img%0asrc=0%0aοnerrοr=alert(1)>
level-17
传参不严格造成XSS
οnmοuseοver=alert(1)
传入的参数都经过htmlspecialchars处理,因此payload中不能包含&,",',<,>。传参的同时,可以进行XSS
arg01=1&arg02=2 οnmοuseοver=alert(1)
level-18
几乎和level-18一样,payload为arg01=1&arg02=2 οnmοuseοver=alert(1)