在网络安全领域应用机器学习的困难和对策

安全 机器学习
网络安全领域的独特对抗属性给人工智能应用落地带来了重重困难,但我们并不认为这最终会阻碍人工智能成为网络安全利器。

网络安全领域的独特对抗属性给人工智能应用落地带来了重重困难,但我们并不认为这最终会阻碍人工智能成为网络安全利器。我们尝试分析了人工智能在网络安全应用里的潜在困难,并试着解决它们。

基于机器学习、深度学习的网络安全应用研究是近年来网络安全领域里的一个热门研究方向。从可见的资料上来看,安全专家已经在异常进程行为检测、恶意代码检测、网络入侵检测等方面进行了广泛的学术研究。但是我们的直观感受是,主流安全厂商并没有大规模部署和使用这些技术,市面上声称采用的机器学习、深度学习的安全产品也相当有限。相比于机器学习、深度学习在人脸识别、推荐系统、舆情监督等方面的大规模成功应用,其在网络安全领域表现平平必然存在某些特殊的原因。本文将深入探讨机器学习、深度学习等技术在网络安全领域的应用面对的困难及其相应对策。虽然这些困难并没有使机器学习、深度学习成为网络安全领域的一个不合适的工具,但这些困难却是导致业界没能大规模采用机器学习、深度学习技术的主要原因。同时又由于近年来媒体的报道更倾向于夸大人工智能技术的成果,而忽略它们所存在的缺陷和困难,显得导向偏颇。对此,与决策者而言不应该只被其表面的光鲜所迷惑,而应该对人工智能技术有足够清晰的认知,希望本文能为这方面的认知提供一个可探讨的方向。

注: 为了便于下文的表述,以下的内容将采用“人工智能系统”指代依靠机器学习或是深度学习实现的安全防护或检测系统。

[[327331]]

困难1:确定一个真正需要用到人工智能的任务

人当人工智能上升为国家战略,深度学习成为新兴技术。对于公司决策层而言当前应思考在结合目前公司发展在当前阶段是否真正需要用到人工智能技术。

  • 首先,需要对人工智能技术有足够清晰和深入的了解。在当前阶段,人工智能的实现是由数据驱动的。优秀的人工智能是建立在海量行业数据的支撑下。
  • 其次,人工智能开发和应用阶段都是计算密集型的。虽然所需的软、硬件计算环境与传统的软件开发有着很大的区别,但其带来的好处也是相对可观。以机器学习为代表的人工智能具备高效、自动化、可拓展的特点,极大程度上可代替人工处理日常事务。

开启一项人工智能项目,最大的难题是如何确定一个真正需要用到人工智能技术且可具备顺利研发并落地条件的任务。

对策

决策者需要在了解人工智能工作机制和其优缺点的基础上去思考并确定是否要在特定任务中运用人工智能技术。而在时机、成本、团队、可行性、预期效果等方面则需要重点考虑。

  • 时机。思考在解决某特定任务时运用传统技术是否遇到瓶颈和缺陷,进而不得不需要研发下一代技术。对此任务,除了人工智能方案是否有其他更行之有效且简便的方法可以解决。如果没有其他可行方案,是否已经为采用人工智能技术方案而做好了采集相关数据的工作,或随时可以进行数据采集。只有充分思考这些问题后才能基本确定是否运用人工智能技术的作为解决问题的方案。人工智能不是万能药,却是一种有效但更为复杂的灵丹。
  • 成本。永远别低估人工智能系统的成本投入。无论是开发还是维护人工智能系统都需要大量的持续投入,包括算力资源投入、人力资源投入以及数据收集、整理、存储成本投入等。很多组织没有足够的资金承担这样大规模投放,所以导致项目中途夭折,前期心血付之东流;因此在项目开始前期,需慎重思考是否有足够的能力承担应有的成本投入。
  • 团队。人工智能系统的软件工程团队包括问题领域的专家(主题专家)、数据科学家、数据架构师等专业人才。这些团队成员带来了算法选择、模型构建、模型定制和数据管道管理等方面的技能,而这些技能构成了人工智能系统的核心。他们共同把控着人工智能系统的性能、可伸缩性、带宽、资源管理和版本控制等方面的高要求。
  • 可行性。可行性的评估需要决策者对特定任务的本质有足够深刻的理解。某项任务能否通过人工智能技术实现自动化,基本上取决于这项任务的本质、能采集到的数据,以及这两者之间的关系。深度学习知名人物吴恩达曾经提过一个经验的规律:“如果一个普通人做某项任务的过程中,只需要思考不超过一秒钟时间就可以想通,那么这项任务很有可能可以用 AI技术自动化,现在或者就在不远的将来”,那么对于网络安全领域,如果一个专业水平在平均值以上的安全技术人员在某项任务中经过短暂的思考时间就能想通,那么这项任务大概率也可以通过AI技术实现自动化。
  • 预期效果。对于预期效果的预判,前提是你对自己定义的任务和问题主题理解足够清晰。思考并确定人工智能系统可接受的性能和效率下限,以便工程师迅速接受指令并明确地向此目标优化系统。当然优化后的系统也会不可避免的出现误报和漏报状况,为此需要尽早确定该任务对误报和漏报的敏感度、风险成本的承担范围和处置机制。人工智能系统同样存在被绕过的风险,对抗性在网络安全领域无处不在,为避免对抗样本发生,怎样保护人工智能系统免受攻击也是一个需要提前思考的问题。

困难2:数据泛滥,难以获取高质量的训练数据集

网络安全领域往往不缺乏数据。每天都有无数攻击事件发生,安全厂商的后台数据库每天都能收录无数的攻击数据。但是单单依靠数据的数量不足以支撑开发一个人工智能系统,况且这些数据中不可避免存在着显著的冗余。数据的质量才是真正人工智能的基石。当前人工智能还处于弱人工智能的发展阶段,人工智能来自于从海量数据中学习规则、模式、特征和经验。在机器学习实现的人工智能工程中,最大的性能改进一般来自于更高质量的数据,而不是更复杂的算法。对于所有人工智能系统来说,其训练数据集的质量包括三个层面:

  • 一是数据的多样性,这要求所收集的数据包含所研究范围的各种类型数据;
  • 二是数据的可靠性,即数据被准确标识为是何种类型何种属性的数据;
  • 三是数据的数量,即在数据采集清理加工去重后,可靠的数据的数量。数量太少则无法训练出可靠的模型,尤其是采用深度学习等参数众多的复杂模型的时候。 

数据的收集、清理、标注、保护、监视和维护统称为人工智能项目的数据管理,这将贯穿着从项目立项到项目落地、维护、迭代的整个生命周期,且需消耗巨大的时间和精力,这需要占整个项目8成以上的时间。有别于其他领域,网络安全领域的人工智能系统项目的数据管理,其成本和难度更大,主要是因为以下原因:

(1) 变化的环境。变化的环境一方面体现在业务的多样性,导致的是白样本的多样性;另一方面体现在对抗环境下,导致的是恶意样本的对样性;

(2) 私有、公开数据少,且公开数据有效性不好。因为不同场景不同用户的数据有差异,公开的数据的场景和你所面对的环境和场景可能差异巨大而不可用。算法工具通常是开源的,但是好的数据集通常是专有的。安全领域更是如此。安全厂商倾向于“隐藏”与安全相关的数据,因此通常无法获得具有代表性的准确标记数据(尤其是涉及流量数据)。拥有庞大优质的特定领域数据集可以成为竞争优势的重要来源。

(3). 数据加工清洗标注专业性高。标注人脸识别、猫狗分类、垃圾邮件等任务的数据,但凡受过基础教育的人就能胜任,而网络安全则属于专业性高的行业,标注网络安全检测相关数据集需要专业的安全工程师才能胜任。

(4) 黑样本种类稀缺,难以集全。这对于后续系统的可靠性造成很大的影响。IBM的肿瘤专家顾问系统Watson for Oncology由于提出的治疗方案及其相关建议不安全,被迫终止。经过研究人员研究发现,正是由于该软件只针对少数假设癌症患者—而非实际患者数据训练而成,采用的黑样本种类稀少,因此在可靠性方面存在严重的问题。在网络安全领域,如果数据的黑样本不够全面将导致类似的可靠性问题。

(5) 数据的非结构性。网络安全领域所要处理的数据无论是网络流量、恶意代码还是恶意文件,大多都是非结构化的数据,对此数据的加工处理比结构化数据要复杂困难。

(6) 数据清洗,自动化困难,工具少。

对策

(1) 商业合作框架下的数据资料共享

当然这前提是自己已经有相当的数据积累,合作共享才会成为可能,在网络安全领域的数据共享要避免触犯《网络安全法》等法律法规;

(2) 依赖现有检测工具实现一定程度的自动化数据采集与标注

现有的威胁检测工具对于相应的任务必然还是有相当的检测能力的,如果将其改造为自动化标注工具则可对应解决此问题;

(3) 随时应变,因地适宜

对于先收集数据还是先确定任务课题的问题,没有标准答案,不同组织选择可能不一样。有的组织在收集到大量数据后才去考虑能用这些数据做什么,有的组织先确定任务,列出所需的数据类型,再收集这些数据。对此顺序只要是可行的都是可以的。

困难3:需要付出昂贵的出错成本

在网络安全领域,人工智能往往应用于风险检测。与许多其他人工智能应用相比,风险检测出错的相对代价非常高。误报需要分析师花费昂贵的时间去核查所报告的风险事件,以确定它是否是良性的。即使是很小的误报率也会使风险监测系统失去实用性。如表1所示,假设我们开发出了一个准确率高达99%的风险监测模型,这样的准确率已在众多人工智能系统中属于高水准程度。那么,设想我们在某场景下部署了该模型,部署期间产生良性事件样本999900个,恶性事件样本100个,这是相对合理的设想,风险事件的发生相比于正常事件总是极小概率事件。而在这基础上,将会发生9999起错误的告警,这将导致一系列后果:轻则耗费分析师的时间成本,重则可能影响业务系统的正常运行。

表1:某99%准确率检测系统告警数量

一方面,漏报产生的损害是直接的。绕过检测的风险可能对受防护的系统产生直接的损害,影响正常业务的开展,甚至会严重损害IT基础设施。我们认为如此高的出错成本是安全厂商需谨慎使用机器学习技术的最大原因。对此让我们进一步对比人工智能在其他领域产生错误分类的影响,相比之下可能会更有启发。

电商的推荐系统是运用人工智能最成功的领域之一。推荐系统很容易容忍错误,因为这些错误不会产生直接的负面影响。虽然对卖家来说好的推荐有可能增加销售额,但坏的建议除了失去交易机会需要做出更具诱惑力的推荐策略外,对于消费者而言并没有任何的伤害。

OCR技术相比之下也更容易容忍错误。通常可以用拼写和语法检查来剔除明显的错误,使用统计语言模型将概率与结果联系起来并对OCR系统的初始输出进行后处理。此外,用户还接受了培训,这可保证当输出文本有差异时,一定程度上可以让用户进行人工校对。相比手动验证安全事件告警,验证校对文字的识别结果并不需要专业的知识,这相比验证安全告警的成本和难度都低得多。

在不同行业不同场景中,人类对于人工智能在概率表现方面的期望值有所不同(在安全行业期望值高容错率低),这也是造成人工智能产品或技术在网络安全领域普及不够广泛的原因。总的来说,网络安全检测系统对错误数据的容忍更加严格,其他领域运用人工智能是在做加法,而网络安全领域运用人工智能更像是在做减法,挑战更加巨大。

表2:某恶意软件检测算法研究的预测精度

另一个挑战是模型复杂度与效率的矛盾。一般来说为了得到较低出错率的模型,模型的复杂度就不能太低,这样相应的复杂模型的运算量也较大。天下没有免费的午餐,如表2所示,更深入本质的特征虽然能带来更好的准确率,但是获取难度大,效率低。两者之间的取舍是一个巨大的挑战,尤其在安全风险监测系统,往往要求对风险能够快速实时响应。

对策

限制误报量是任何威胁检测系统的首要任务。朝着减少错误的方向迈出的最重要的一步是缩小系统的范围,也就是定义一个明确的检测目标。没有一个明确的目标,任何威胁检测系统都无法在不影响其检测率的情况下,获得可容忍的误报量。另外,使用更粗粒度的特征在适当的时间间隔内聚合或平均特征对于减少误报也是有用的。最后,我们可以通过在附加信息的支持下对它们进行后处理来减少误报。如果我们发现自动化后处理是不可行的,我们仍然可以通过向分析员提供额外的信息来加速人工检查过程,从而降低出错成本。

困难4:对抗环境

人工智能系统本身就是一个软件系统,难免存在可利用的漏洞,也是被攻击的天然目标,尤其是作为网络安全检测防护系统的一份子的时候,可以认为是处于对抗环境中。相比之下,OCR系统的用户不会试图在输入中添加干扰,甚至会主动提供更高质量的输入数据;淘宝用户也不会有太多的动机去误导商品推荐系统,这对他们毫无意义。然而在网络安全领域则恰恰相反,那些破坏、绕过、欺骗人工智能检测系统攻击者为了能够达到他们入侵的目的,他们有充分的动机。至少能从三个层面体现在对抗环境下机器学习系统的风险。

数据层面,典型的是投毒攻击。投毒攻击(poisoning attack)主要是对人工智能系统在训练模型时对需要的训练数据进行投毒,是一种破坏模型可用性和完整性的诱发型攻击。攻击者通过注入一些精心伪造的恶意数据样本,这些样本通常带有错误的标签和攻击的性质,用于破坏原有的训练数据的概率分布,从而使训练出的模型的分类或者聚类精度降低,达到破坏训练模型的目的。由于实际中应用人工智能系统的原始训练数据大多是保密的,一般不会被攻击者轻易修改,但很多系统为了增强适应能力需要定期收集新数据,进行重新训练实现模型更新,这时也就给了攻击者可趁之机。

 

图 1:一种投毒攻击示意图

模型层面,模型的绕过风险,即存在对抗样本攻击。攻击者通过产生一些可以绕过人工智能检测系统的对抗样本,这些是可以成功地逃避安全系统检测的对抗样本,实现对系统的恶意攻击,给系统的安全性带来严重威胁。作为安全风险检测模型的存在的时候,人工智能系统的模型的输入数据变化很大,具有易变性。我们很难限制待检测的恶意软件的大小,没有理由限制待检测的恶意代码样本的行数,没办法限制要检测的网络流量的数据包内容,因此这就给了对抗样本更大的发挥空间。这个层面的对抗是最容易发生的,也是人工智能检测系统在对抗中最薄弱的环境,对抗之下会产生层出不穷的新攻击手法、攻击样本,因此网络安全领域应用的模型的迭代频率要比其他领域要高得多。试想,千百年以后,今天训练的猫狗分类模型到那时候也许还能用,但是对应的恶意软件、木马文件、攻击流量也在当前模型的能力范围之外产生了多个新形式。

框架层面,深度学习框架通常是包含数十万代码和众多依赖的复杂软件,几乎不可避免地存在已知或未知的bug。在国家信息安全漏洞库,能查到2019年上报的tensorflow相关漏洞信息8个(如图2所示)。Torch、Caffe等框架也存在漏洞,以及这些框架的常见依赖包numpy、opencv等均存在不少漏洞。对此,相关的安全研究已经复现了这些漏洞将会造成的拒绝服务、绕过检测和系统危害等风险。

 

 

 

图 2: tensorflow历史漏洞

 

所以,网络安全领域持续进行着一场军备竞赛:攻击者和防御者各自改进他们的工具和技术,以应对另一方设计的新技术。

对策

使用人工智能技术对于攻击者而言实际上是带来更多攻击面如算法、数据等。

在防护方面,可以考虑以下几点:

(1) 对模型的输入做严格限制,设置进入模型的样本过滤条件。过滤条件根据任务的专业领域知识和模型训练过程中的设置总结。比如,某识别php类型webshell的模型可将输入设置为文件后缀.php或.txt且内容包含

(2) 从模型本身训练其辨别良性、恶意数据的能力。将已知对抗样本或自己构造的对抗样本数据添加到模型的训练数据集然后训练模型。

(3)  在上线部署前,在对抗环境下测试和评估人工智能系统。在对抗性情景下或极端情况下测试系统,而不仅仅只是使用正常事件测试。比如使用噪声数据训练和测试评估模型的泛化能力和抗噪能力,在对抗环境下或使用投毒数据评估系统的对抗能力。当然也不用对对抗环境带来的风险过度担心,因为在绕过一个人工智能系统,攻击者需要付出大量的努力、时间和专业知识,这往往比绕过正则规则难得多。

困难5:模型可解释性及该如何取合

人工智能系统的输出比大多数其他系统需要更多的解释。因为人工智能系统引入的不确定性在用户的某些任务和场景下可能是不可接受的,往往需要跟客户沟通做出这种输出判断的依据和缘由。而在其他机器学习的应用中,解释性的问题可能就没那么重要。大多数图像类别识别的机器学习都可以忽视可解释性,因为图像属于什么类型是直观的,普通人可以毫不费劲地辨别结果的对与错。同样,垃圾邮件检测器将邮件归为垃圾邮件,也是很直观的任务并没有太大的解释空间。然而,作为安全风险检测应用,其检测结果往往是不直观的,至少对非网络安全专业的客户来说,这时候的解释输出是取得客户信赖的必要工作。假设人工智能系统能准确地发现以前未知的web服务器漏洞,而只报告为“主机的HTTP流量与正常配置文件不匹配”,即使对它的警报足够信任,运维人员也需要花费大量的额外精力来弄清楚发生了什么。

[[327333]]

安全风险检测往往需要进一步指导相关人员快速评估和响应制定风险处置方案,且这过程附带着极高的出错成本,因此对检测结果的必要解释和正确解释是安全风险检测应用的一个基本要求,而这也保障了其的可用性。然而这里一切的困难在于我们如何向用户展示人工智能系统输出结果的信息,使他们能够正确的接收并理解这些信息,同时我们又不能展示过多信息,以防暴露过多模型信息给竞争对手或是被攻击者利用。更困难的是,人工智能模型的原始解释是包含一系列检测逻辑的数学术语,例如某变量超过给定阈值,对于非建模人员而言这些并不好理解,对于输出结果的利用也作用有限。怎样将这些数学语义的解释与业务的语义相互联系是一个更大的难题。

对策

(1) 重新设计输出结果的解释性

现有的机器学习、深度学习模型输出解释技术往往是对特征的归因,如果直接展示这些信息很容易变相地为竞争对手或是攻击者提供模型的敏感信息,增大模型被绕过的风险。我们可以对结果重新归纳设计,隐含模型相关的细节,特别是数值相关信息要避免呈现,对于输出结果的可靠性程度和不确定性避免使用数值描述,我们可以用“低、中、高”等分级表述。

(2) 解释结果的最重要的方面是理解它们的起源

一个好的解释常常需要在一个非常低的层次上把输入和输出联系起来。

困难6:难以全面评估

对于网络安全领域的人工智能系统而言,设计合理完整的评估方案并不容易,事实上可能比构建识别模型本身还更困难。全面评估的最重要的一步是获取适当的数据。在网络安全领域,评估人工智能系统面临的最重大挑战是缺乏适合的、公允的、且足够数据量的现成公共数据集。即使企业自己创建测试数据集,也是很难得到足够数量和足够全面的数据。以互联网流量为例,这是网络安全典型的检测对象。互联网流量是企业和组织的重要的私有资源,不会轻易共享。对于不同的组织不同的业务,网络流量具有多样性。在小型实验室网络中的流量特征和大型业务系统的流量会显著不同。即使在单个网络中,网络的最基本特征,如带宽、连接持续时间和应用程序组合,也会表现出巨大的变化性,使它们在短时间(从几秒到几小时)内流量特征差异也可能极大。更何况,大多数企业或组织并没有获取相当规模的网络流量的条件,即使通过模拟来采集,也会因为数据的真实性和相关性等对后续的人工智能系统带来难以评估的不利影响,小环境分析得出的结论往往不能推广到大环境分析。所以数据的不全面带来的是模型性能评估的不全面,也就是人工智能系统能检测到什么,不能检测到什么,可靠性是多少等等难以全面评估。

对策

不幸的是,目前对于解决缺乏评估数据的问题,并没有一个较好的方案。对于任何研究来说,需要承认自己的评估数据集可能带来的缺点。尽管很难,还是需要从大范围的环境中获取包含真实网络流量的数据集。理想情况下,我们获取了大量来自不同的网络的数据,因为没有数据集是完美的,所以在评估检测系统时,通常需要多个数据集来做支撑。要证明系统能够通过学习适应不同的环境,也需要使用来自多个来源的数据进行评估。对于类似于互联网流量多样性问题,一种可行的方法是采用聚合。虽然流量特征在中、小时间间隔内高度可变,但在较长时间段(小时到天,有时是周)内观察到的流量特征往往更加稳定。

困难7:机器学习难以部署和维护

精心设计研发的机器学习模块是与现有安全防护系统的其他部分集成,这会产生一系列问题和风险。

  • 首先是兼容性问题。机器学习、深度学习研发和部署工具的推出时间往往比实现现有其他安全防护系统模块的工具时间要晚。Tensorflow 是2015年推出的,PyTorch是2017年才推出的,如果现有防护系统已运行多年,那么在集成中出现底层技术不兼容概率很大。
  • 其次是安全业务流程的改变。目前的机器学习应用水平通常难以独立发展成一个成熟的安全防护应用,大多数时候会涉及与现有防护模块的互补和协作,这将需要重新设计相关的业务流程。
  • 最后是保护机器学习模块的完整性和可用性。这可能需要依赖现有的系统保护机器学习模块核心组件不被破坏、篡改、偷窃等。因为对手获取越多关于模型的信息,绕过模型的成本越低,防护效果就越差。
[[327334]]

网络安全是一个瞬息万变的领域。攻击者会变,他们的手段也不会总是相同,程序语言会升级换代,攻击武器也层出不穷。唯有模型跟着变化才能充分应对这些变化。所以从维护层面上而言,最核心的难题是更新频率高。在高频的更新要求下,人工智能系统的变化率和整个系统中的其他模块是不一致的。数据和模型频繁地更改,这意味着系统的其他部分也需要进行更改。收集数据、在需要时标记数据、不断调查和学习网络安全领域将是维护ML工具的持续需求。而在迭代过程中我们将面临着系统本来能识别检测的威胁在模型更新后反而检测不到的问题。考虑图3的简化模型,假设黑色圆圈是威胁样本,我们的第一个模型F(X)的准确率是(3+4)/10=70%,我们迭代模型到第二个模型G(X),其准确率是(5+4)/10=90%,准确率显然是提高了,但是左下角的黑圆圈样本是能被F(X)检测到的,反而准确率更高的G(X)却识别不出来。这在机器学习项目中经常出现。由于算法的优化目标是在指定数据集上准确率等指标做出全局最优解,在迭代过程中可能由于数据集增大了、减少了或是黑样本变多了,数据均衡和分布规律和之前不一样了,又或是模型的超参数做了调整等都会改变模型的决策边界从而导致这类情况发生。

 

 

 

图 3:模型迭代效果示意图

 

对策

开发团队应该充分在架构设计上考虑好安全性、可用性、可靠性、性能、可伸缩性等核心需求。尽可能实现松散耦合的部署方案,可以扩展或替换,以适应不可避免的数据和模型的变化和算法创新,从而减少每次的更新对系统其他模块或是系统基础结构的影响和更改。实现收集反馈闭环,跟踪人工智能系统生产环境下的输出,形成反馈工作流程,定期分析、反馈检测结果和性能指标,进行发现薄弱环境以指导下一步的迭代。应该尽可能使用自动化的方法来获取系统输出的人类反馈,并改进(即重新训练)模型。即时监控用户体验、尽早发现问题,例如以系统延迟或降低准确性的形式降低性能。即使是在低交互系统中,也要确保持续的人类参与,以监测计算机是否因无法编码而进行评估的判断(实际的、道德的、道德的、信任的、与风险相关的),以及是否存在模型篡改或系统误用的迹象。

 

责任编辑:赵宁宁 来源: FreeBuf
相关推荐

2018-06-26 12:17:19

2023-07-06 13:37:43

2020-01-17 20:57:24

人工智能AI网络安全

2023-12-12 11:25:51

2022-10-20 14:44:50

2022-03-02 09:11:09

机器学习网络

2021-11-30 22:51:36

机器学习大数据技术

2016-01-22 12:27:15

2021-12-14 11:17:08

首席安全官网络安全首席信息官

2024-08-26 00:10:45

2023-04-06 10:12:04

2024-03-14 15:11:54

2019-12-19 14:33:08

人工智能网络安全机器学习

2021-07-26 09:58:14

人工智能机器学习网络安全

2011-02-28 18:03:35

2022-07-12 11:25:53

人工智能网络安全

2023-03-20 11:16:00

2020-09-22 07:00:00

AI机器学习网络安全

2024-01-30 00:55:23

2020-10-29 10:16:30

AIML网络安全
点赞
收藏

51CTO技术栈公众号