当前位置:   article > 正文

【小迪安全】红蓝对抗 | 网络攻防 | V2022全栈培训笔记(PHP开发12-17)_小迪安全红蓝对抗网络攻防2022全站培训笔记

小迪安全红蓝对抗网络攻防2022全站培训笔记

第12天 PHP开发个人博客项目&文章功能显示&数据库操作&数据接收

知识点:

1、PHP入门-语法&提交等
2、MsQL入门-数据库操作
3、HTML+CS5入门-样式编排

演示案例:

小迪博客文章阅读功能初步实现

实现功能:
前端文章导航,点入内容显示,更改I♪显示不同内容
实现步骤:
1、前端页面显示编写-HTML&CSS
HTML 是一种用于创建网页的标记语言,全称为超文本标记语言。使用html构造显示前端文章导航站点。
在这里插入图片描述

2、数据库文章数据导入-MySQL工操作
首先配置数据库连接–验证数据库配置–定义数据查询到的变量并赋值–连接具体表–执行具体字段显示
在这里插入图片描述
在这里插入图片描述
每次查询数据时都需要执行核查数据库配置的语句所以可以把数据库连接配置写成配置文件
在这里插入图片描述
在这里插入图片描述

3、PHP操作MYSQL编写-PHP变量提交
要实现提交一个参数传到数据库中查询,需要先通过GET获取提交的参数,然后通过数据库语法(where id = ?)指定查询内容(此处因为没有对传入的参数进行限制就导致了sql注入,例如where id=1 union select name from admin)
在这里插入图片描述
除了使用GET传参外,还可以使用PSOT和REQUEST传参,这样就是sql注入中的get方式和post方式注入
组件:
Navicat:操作数据库
Dreamweaver:前端页面设计
PhpStorm:PHP开发IDE
phpStudy:PHP搭建环境

第13天 PHP开发个人博客项目8&文件操作类&编辑器&上传下载删除读写

知识点:

1、文件操作类代码编写
2、文件上传&下载&删除

HTML前端代码:

<!DOCTYPE html>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
    <h2>文件上传表单</h2>
    <form action="upload.php" method="post" enctype="multipart/form-data">
        <input type="file" name="fileToUpload" id="fileToUpload">
        <input type="submit" value="上传文件" name="submit">
    </form>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

解释:

HTML表单用于创建文件上传功能。
表单的action属性设置为"upload.php",意味着表单数据将被发送到upload.php文件。
表单的method属性设置为"post",表示表单数据将使用POST请求方法发送。
enctype属性设置为"multipart/form-data"。这在上传文件时是必需的,它允许表单数据包含二进制数据。

PHP后端代码(upload.php):

<?php
if(isset($_POST["submit"])) {
    $targetDir = "uploads/";  // 指定上传文件存储的目录
    $targetFile = $targetDir . basename($_FILES["fileToUpload"]["name"]); // 获取上传文件的路径

    $uploadOk = 1;  // 标志变量,用于检查文件上传是否成功
    $imageFileType = strtolower(pathinfo($targetFile,PATHINFO_EXTENSION)); // 获取文件扩展名

    // 检查文件是否已经存在
    if (file_exists($targetFile)) {
        echo "对不起,该文件已存在。";
        $uploadOk = 0;
    }

    // 检查文件大小(最大100MB)
    if ($_FILES["fileToUpload"]["size"] > 100000000) {
        echo "对不起,您的文件太大了。";
        $uploadOk = 0;
    }

    // 只允许特定的文件格式(可以根据需要添加更多)
    if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
        && $imageFileType != "gif" ) {
        echo "对不起,只允许上传JPG、JPEG、PNG和GIF格式的文件。";
        $uploadOk = 0;
    }

    // 如果文件上传成功
    if ($uploadOk == 0) {
        echo "对不起,上传文件失败。";
    } else {
        // 将文件移动到指定目录
        if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $targetFile)) {
            echo "文件". basename( $_FILES["fileToUpload"]["name"]). "已上传成功。";
        } else {
            echo "对不起,上传文件时发生错误。";
        }
    }
}
?>

  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

解释:

PHP脚本从检查是否点击了提交按钮开始(if(isset( P O S T [ " s u b m i t " ] ) ) )。它设置了 _POST["submit"])))。 它设置了 POST["submit"])))。它设置了targetDir变量,指定上传文件存储的目录。
使用basename()函数获取上传文件的名称,并将其附加到目标目录以创建 t a r g e t F i l e 路径。初始化 targetFile路径。 初始化 targetFile路径。初始化uploadOk标志变量,用于检查文件上传是否成功。
使用pathinfo()函数从目标文件路径获取文件扩展名。
进行多个检查,例如文件是否已经存在、文件大小限制和允许的文件格式。
如果所有检查通过,使用move_uploaded_file()函数将临时上传的文件移动到指定目录。

HTML 前端代码:

<!DOCTYPE html>
<html>
<head>
    <title>文件下载示例</title>
</head>
<body>
    <h1>文件下载示例</h1>
    <a href="download.php?file=example.txt">点击这里下载文件</a>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

上述 HTML 代码中,我们创建了一个简单的页面,其中包含一个标题和一个链接。当用户点击链接时,将触发 download.php 页面。

PHP 后端文件上传代码:

<?php
// 检查是否有文件上传错误
if ($_FILES["fileToUpload"]["error"] > 0) {
    echo "Error: " . $_FILES["fileToUpload"]["error"] . "<br>";
} else {
    // 获取上传的文件名和临时文件路径
    $fileName = $_FILES["fileToUpload"]["name"];
    $tmpName = $_FILES["fileToUpload"]["tmp_name"];

    // 指定上传到服务器的目录
    $uploadDir = "uploads/";

    // 将上传的文件移动到指定的目录,并重命名为随机字符串 + 原始文件名
    $newFileName = uniqid() . "-" . $fileName;
    $targetFile = $uploadDir . $newFileName;
    move_uploaded_file($tmpName, $targetFile);

    // 输出上传成功的提示信息
    echo "The file " . $fileName . " has been uploaded.";
}
?>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

首先获取通过 GET 请求传递的 file 参数,该参数包含了要下载的文件名。

接着,我们检查文件是否存在,如果存在则设置响应头信息来告诉浏览器该文件需要被下载。Content-Type 头指定了文件的 MIME 类型,Content-Disposition 头指定了文件下载的方式和文件名,Content-Length 头指定了文件的大小。

最后,使用 readfile() 函数将文件内容发送给浏览器进行下载。

如果文件不存在,我们会输出一条错误消息并结束脚本的执行。

HTML 前端文件删除代码:

<!DOCTYPE html>
<html>
<head>
    <title>File Delete Form</title>
</head>
<body>
    <h2>File Delete Form</h2>

    <!-- 创建一个表单,用于向服务器发送要删除的文件名 -->
    <form action="delete.php" method="post">
        <!-- 添加一个输入框,用于输入要删除的文件名 -->
        File name:
        <input type="text" name="fileName">

        <!-- 添加一个提交按钮 -->
        <input type="submit" value="Delete File" name="submit">
    </form>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

PHP 后端文件删除代码:

<?php
// 获取要删除的文件名
$fileName = $_POST["fileName"];

// 指定要删除的文件路径
$filePath = "uploads/" . $fileName;

// 检查文件是否存在
if (file_exists($filePath)) {
    // 删除文件
    unlink($filePath);

    // 输出删除成功的提示信息
    echo "The file " . $fileName . " has been deleted.";
} else {
    // 输出文件不存在的错误信息
    echo "Error: The file " . $fileName . " does not exist.";
}
?>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

通过 $_POST 数组获取前端提交的要删除的文件名,并使用 unlink() 函数删除指定路径下的文件。需要注意的是,在执行删除操作之前,需要确保要删除的文件具有足够的写入权限,否则会导致删除失败。

在实际应用中,为了保护服务器和用户数据的安全性,需要对文件删除操作进行一些额外的安全性检查。例如,在删除前可以询问用户是否确认删除操作,并验证用户身份,避免未经授权的删除操作。

3、文件内容&读取&写入
4、第三方编辑器引用实例

演示案例:

  • 小迪博客-文件操作&上传&下载&删除&读取&写入等
    #文件上传类:-任意文件上传
    1、代码自主写
    2、外部编辑器源码引用
    3、开发框架引用
    #文件下载类:-任意文件下载
    1、直连URL访问
    2、传参头部修改

直连下载会暴露文件存储路径,如果服务器端的文件存储路径包含敏感信息,建议使用 PHP 内置的 readfile()函数来直接输出文件内容,以避免泄露敏感信息。同时,可以设置响应头信息中的 Content-Disposition 属性为inline,使浏览器将文件直接显示在页面中,而不是下载到本地。
传参下载可能存在参数注入攻击的风险,因此在接收和处理来自客户端的参数时,应该对输入值进行过滤和验证,避免恶意用户利用特殊字符或脚本代码等手段构造攻击请求。例如,可以使用
PHP 内置的 filter_input() 函数来对参数值进行过滤,或使用正则表达式来匹配合法的参数格式。
在下载文件之前,应该对用户身份进行验证,确保只有具备相应权限的用户才能访问和下载文件。例如,在使用传参下载时,可以检查用户的登录状态和角色权限,避免未经授权的下载操作。
对于需要下载的文件,建议对其类型、大小、来源和安全性等进行检查和限制,避免下载恶意软件、病毒或大型文件等对服务器端和客户端带来的负担和安全威胁。例如,可以使用
PHP 内置的 mime_content_type() 函数检查文件 MIME 类型,或使用 filesize() 函数检查文件大小,并在前端添加文件大小限制。对于上传到服务器的文件,可以使用防病毒软件和防火墙等工具对文件进行检查和过滤。
//http://www.xiaodi.com/soft/软件.zip
//http://www.xiaodi.com/soft/down.php?filename=.zip

#文件删除类-任意文件删除
1、文件删除
2、文件夹删除
删除文件使用unlink()函数,删除文件夹使用rmdir()函数。
#文件内容操作类-任意文件读取&写入
1、文件读取
2、文件写入
在这里插入图片描述
文件包换漏洞
1、本地文件包含
2、远程文件包含
web漏洞核心
1、可控变量
2、特定函数

第14天 PHP开发-个人博客项目8输入输出类&留言板8访问IP&UA头来源

知识点:

1、PHP-全局变量_SERVER
利用全局变量可以查看服务器和执行环境信息

// $_SERVER['REMOTE_PORT'] //端口。
// $_SERVER['REMOTE_ADDR'] //当前用户 IP
// $_SERVER['REMOTE_HOST'] //当前用户主机名 
// $_SERVER['SERVER_NAME'] //服务器主机的名称。
// $_SERVER['PHP_SELF']//正在执行脚本的文件名
// $_SERVER['argv'] //传递给该脚本的参数。
// $_SERVER['argc'] //传递给程序的命令行参数的个数。
// $_SERVER['GATEWAY_INTERFACE']//CGI 规范的版本。
// $_SERVER['SERVER_SOFTWARE'] //服务器标识的字串
// $_SERVER['SERVER_PROTOCOL'] //请求页面时通信协议的名称和版本
// $_SERVER['REQUEST_METHOD']//访问页面时的请求方法
// $_SERVER['REQUEST_URI'] //URL路径
// $_SERVER['QUERY_STRING'] //查询(query)的字符串。
// $_SERVER['DOCUMENT_ROOT'] //当前运行脚本所在的文档根目录
// $_SERVER['HTTP_ACCEPT'] //当前请求的 Accept: 头部的内容。
// $_SERVER['HTTP_ACCEPT_CHARSET'] //当前请求的 Accept-Charset: 头部的内容。
// $_SERVER['HTTP_ACCEPT_ENCODING'] //当前请求的 Accept-Encoding: 头部的内容
// $_SERVER['HTTP_ACCEPT_LANGUAGE'];//浏览器语言
// $_SERVER['HTTP_CONNECTION'] //当前请求的 Connection: 头部的内容。例如:“Keep-Alive”。
// $_SERVER['HTTP_HOST'] //获取当前程序所在主机,当前请求的 Host: 头部的内容。
// $_SERVER['HTTP_REFERER'] //链接到当前页面的前一页面的 URL 地址。
// $_SERVER['HTTP_USER_AGENT'] //当前请求的 User_Agent: 头部的内容。
// $_SERVER['HTTPS']//如果通过https访问,则被设为一个非空的值(on),否则返回off
// $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名。
// $_SERVER['SERVER_ADMIN'] #管理员信息
// $_SERVER['SERVER_PORT'] #服务器所使用的端口
// $_SERVER['SERVER_SIGNATURE'] #包含服务器版本和虚拟主机名的字符串。
// $_SERVER['PATH_TRANSLATED'] #当前脚本所在文件系统(不是文档根目录)的基本路径。
// $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面需要指向自己时非常有用。
// $_SERVER['PHP_AUTH_USER'] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的用户名。
// $_SERVER['PHP_AUTH_PW'] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的密码。
// $_SERVER['AUTH_TYPE'] #当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是认证的类型
  • 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
  • 28
  • 29
  • 30
  • 31
  • 32

例如获取并返回访问者UA头信息,若此时功能点有获取并展示UA的功能,可以尝试进行抓包修改ua头为js代码,此时就造成了xss注入。

2、MYSQL-插入语法INSERT
3、输入输出-XSS&反射&存储
输入框输入js语句(例如:)会导致浏览器在显示时会将语句执行,从而弹窗的操作(XSS反射)
留言板输入js语句后,因为留言板的功能会将语句保存并展示,就造成了语句存储在了数据库中就导致了xss存储型注入,利用存储型注入可以获取用户cookie。

4、安全问题-XSS跨站&CSRF等
全局变量$_SERVER中有// $_SERVER[‘HTTP_REFERER’] //链接到当前页面的前一页面的 URL 地址。使用这一变量可以获取访问该链接前的上一个链接地址,在预防CSRF(跨站脚本注入)中可以起到验证跳转地址是否为恶意地址,起到防范作用。

CSRF:
要成功实施 CSRF(跨站请求伪造)攻击,通常需要满足一定的前提条件,包括:
1、 目标网站存在漏洞:CSRF 攻击的基本原理是利用用户在访问目标网站时已经登录过的认证信息,因此目标网站必须存在相应的漏洞才能被攻击者利用。例如,目标网站没有进行有效的身份验证或令牌校验,允许从外部发送请求等。
2、用户已经登录目标网站:由于 CSRF攻击需要利用用户已经登录过的认证信息,因此攻击者必须确保受害用户在攻击发起时已经登录了目标网站,并且浏览器保存了相关的 Cookie 或Session 信息。
3、攻击者能够构造恶意请求:为了实施 CSRF攻击,攻击者需要能够构造出目标网站所接受的合法请求格式,并将其发送到目标网站。

演示案例:

  • 小迪博客输入输出&留言板&访问获取
    通过输入输出、留言板实现xss反射型和存储型注入
  • 墨者靶场-IP地址伪造来源&来源页伪造
    通过burp抓包修改refer字段绕过网页的访问限制(来源页伪造)
    网站存在IP地址限制访问,通过抓包修改来源IP实现绕过
    在这里插入图片描述
    只有当代码中获取IP为$_SERVER[“HTTP_X_FORWORDED_FOR”]时才可通过抓包改包实现绕过。
    在这里插入图片描述

第15天 PHP开发-个人博客项目&登录验证&Cookie&Session&验证码安全

知识点:

1、后台验证-登录用户逻辑安全
2、后台验证-COOKIE&SESSION
3、后台验证-验证码&万能密码等
万能密码:判断是否登录成功是看将提交的用户密码带入数据库进行查询后是否返回数据或返回行数是否对应。
因为出巡过程中是将参数带入到数据库查询,select * from data where username=‘admin’ and pass=‘pass’
此时构造用户名为 ’ or 1=1 # 带入到数据库中查询就为 select * from data where username=’ ’ or 1=1 # and pass=‘pass’
此时假 或 真 为真 后面的语句通过#注释,即可绕过登录判定
验证码安全:验证码不失效,可通过burp抓包再不修改验证码的情况下进行密码替换。

登录验证的流程:
1、发送登录请求帐号密码
2、接受帐号密码
3、判断帐号密码的准确性
正确成功登录->跳转成功页面
错误失败登录->重新登录
HTTP是无状态的协议,所以为了记录身份状态信息会使用cookie和session来存储。
后台管理系统有多个文件页面,为了方便验证,一般会选用cookie或session进行验证
cookie:身份验证存储到客户端浏览器内
cookie安全:cookie修改 伪造 盗取
session:身份验证存储到服务端服务器内
session安全:劫持

Cookie 和 Session 是两种常见的 Web 应用程序状态管理机制,用于在客户端和服务器端之间保存用户数据并实现用户身份认证。它们的不同点如下:

1、存储位置:Cookie 保存在客户端(浏览器)中,而 Session 保存在服务器端。

2、数据安全性:Cookie 中存储的数据可以被客户端篡改和查看,因此需要进行加密处理或者设置 HttpOnly 属性来防止 XSS 攻击;Session 中存储的数据只有存在服务器端,因此相对更安全。

3、存储容量:Cookie 的存储容量通常比较小,一般限制在 4KB 左右;Session 的存储容量相对更大。

4、生命周期:Cookie 可以设置生命周期,可以在浏览器关闭后仍然保持一段时间;Session 默认情况下在浏览器关闭后就会失效,或者等待一定时间后自动过期。

5、应用场景:Cookie 主要用于实现无状态的 HTTP 协议下的用户身份验证、记住密码等功能,适合于分布式系统和负载均衡环境;Session 主要用于保存用户的会话信息,适合于需要维护会话状态的应用场景。

总之,在选择 Cookie 和 Session 进行状态管理时,需要根据具体的应用需求和安全性要求进行选择。对于敏感数据和操作,建议采用 Session 来维护会话状态,并采取相应的加密和验证措施来提高数据安全性;对于较为简单的用户身份认证和状态管理,可以使用 Cookie 方便快捷地实现。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

演示案例:

小迪博客-后台登录&COOKIE&SESSION
本地靶场-某CMS后台登录验证COOKIE脆弱
burp抓包修改cookie信息绕过
在这里插入图片描述

第16天 PHP开发-个人博客项目&JS-Ajax&前端逻辑&购物&登录&上传

知识点:

1、Js前端验证-文件上传
对上传文件的后缀名进行验证,符合要求的才能上传,可以通过PHP或者JS代码实现。
两种去验证的区别:
PHP验证的代码看不到只能黑盒测试
JS验证的代码的可以看到的白盒测试
JS禁用可以绕过前端验证
2、Js-Ajax传递-登录-状态

js ajax 请求->返回->读取返回的数据->JS ajax代码进行解析->结果
php 请求->返回->返回结果(服务器不会理会你自慰)

Ajax接收infocode参数判断是否验证成功。可通过burp抓包修改参数绕过登录验证。

3、JS-Ajax传递-购物-参数

演示案例

1、文件上传-类型-过滤
设计:通过JavaScript进行文件后缀筛选验证
2、状态回显-登录-状态码
设计:通过Ajax传递数据进行用户登录验证
3、参数修改-购物一参数修改
设计:通过Ajax传递数据进行购物验证
设计1:商品价格以前端设置价格为准,数据接收价格后运算
通过修改前端传递的价格和数量绕过
设计2:商品价格以数据库对应价格为准,数据接收价格后运算
虽然价格取自数据库,但是判断还是由JS代码判断,修改价格仍可绕过
设计3:商品价格以数据库对应价格为准,数据只接受数量后运算
此时判断之前也会从数据库取价格,但是因为数量是由js传递的,修改数量换成小数或者负数可以实现绕过
设计4:商品价格以数据库对应价格为准,数据只接受数量后做过滤运算

彩蛋: APP 验证码绕过
抓取输入正确验证码时的回显
在这里插入图片描述
替换输入错误验证码后的回显可绕过
在这里插入图片描述

第17天 PHP开发-个人博客项目&TP框架&路由访问&安全写法&历史漏洞

知识点:

1、基于TP框架入门安装搭建使用
2、基于TP框架内置安全写法评估
3、基于TP框架实例源码安全性评估

演示案例

  • 入门-简单了解-安装&调试&入口&配置
  • 使用-路由访问控制器&对象&函数&参数
  • 安全-SQL注入-不安全写法对比官方写法
  • 安全-RCE执行-历史安全漏洞对比框架版本
  • 实例-CMS源码-EyouCMS&Fastadmin&YFCMF

#安全-$QL注入-不安全写法对比官方写法
1、参数过滤
2、内置过滤
#安全-RCE执行-历史安全漏洞对比框架版本
1、框架版本漏洞
2、框架写法安全
3、黑盒白盒看版本
#实例-CMS:源码-EyouCMS&Fastadmin&YFCMF

AdminLTE后台管理系统
1ayui后台管理系统
thinkcmf
H-ui,admin后台管理系统
tpshop
FsatAdmin
eyoucms
LarryCMS后台管理系统
tpadmin,后台管理系统
snake后台管理系统
ThinkSNS
DolphinPHP后台管理系统
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

https://github.com/Mochazz/ThinkPHP-Vuln
ThinkPHP5.0在没有启用路由的情况下典型的URL访问规侧是:
http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参数名/]
thinkphp接收变量的写法
input(‘?get.id’);
input(‘?post.name’);通过thinkphp内置的写法可以过滤注入语句。(内置过滤)
thinkphp查询数据库语法
Db::table(‘think user’)->where(‘status’,1)->select();(即使数据接收没有过滤,带入数据库查询的时候仍进行过滤,内置过滤)
appplicaton/config.php配置文件中含有app_debug和app_trace两个字段,开启用来调试验证。
在这里插入图片描述

用到TP框架找漏洞
1、看写法
2、看历史漏洞->版本
版本获取知道?
黑盒:
判断是不是tp返回数据包
怎么看版本-报错
经验:URL地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/481943
推荐阅读
相关标签
  

闽ICP备14008679号