收藏 分享(赏)

基于mozilla的安全性漏洞再修复经验研究.doc

上传人:无敌 文档编号:146636 上传时间:2018-03-22 格式:DOC 页数:18 大小:117KB
下载 相关 举报
基于mozilla的安全性漏洞再修复经验研究.doc_第1页
第1页 / 共18页
基于mozilla的安全性漏洞再修复经验研究.doc_第2页
第2页 / 共18页
基于mozilla的安全性漏洞再修复经验研究.doc_第3页
第3页 / 共18页
基于mozilla的安全性漏洞再修复经验研究.doc_第4页
第4页 / 共18页
基于mozilla的安全性漏洞再修复经验研究.doc_第5页
第5页 / 共18页
点击查看更多>>
资源描述

1、基于 Mozilla 的安全性漏洞再修复经验研究 张凯 孙小兵 彭鑫 赵文耘 复旦大学软件学院 复旦大学上海市数据科学重点实验室 摘 要: 相较于其他类型的漏洞, 安全性漏洞更容易发生再修复, 这使得安全性漏洞需要更多的开发资源, 从而增加了这些安全性漏洞修复的成本。因此, 减少安全性漏洞再修复的发生的重要性不言而喻。对安全性漏洞再修复的经验研究有助于减少再修复的发生。首先, 通过对 Mozilla 工程中一些发生再修复的安全性漏洞的安全性漏洞类型、发生再修复的原因、再修复的次数、修改的提交数、修改的文件数、修改的代码行数的增减、初始修复和再修复的对比等数据进行分析, 发现了安全性漏洞发生再修

2、复是普遍存在的, 且与漏洞发生原因的识别的复杂程度和漏洞修复的复杂程度这两个因素有关;其次, 初始修复涉及的文件、代码的集中程度是影响再修复的原因之一, 而使用更复杂、更有效的修复过程可有效避免再修复的发生;最后, 总结了几种安全性漏洞发生再修复的原因, 使开发人员有效地识别不同类型的安全性漏洞再修复。关键词: 安全性漏洞; 再修复; 漏洞修复; 经验研究; 作者简介:张凯 (1993-) , 男, 硕士生, 主要研究方向为软件维护;作者简介:孙小兵 (1985-) , 男, 博士, 主要研究方向为软件分析、维护与演化;作者简介:彭鑫 (1979-) , 男, 博士, 教授, CCF 高级会员

3、, 主要研究方向为需求工程、自适应软件、软件产品线、软件维护、逆向工程;E-mail:;作者简介:赵文耘 (1964-) , 男, 硕士, 教授, CCF 高级会员, 主要研究方向为软件复用、软件产品线、软件工程。收稿日期:2016-10-07基金:国家自然科学基金 (61402396, 61370079) Empirical Study of Reopened Security Bugs on MozillaZHANG Kai SUN Xiao-bing PENG Xin ZHAO Wen-yun Abstract: Compared to other types of bugs, secu

4、rity bug reopens more often, moreover, they need more development resources to fix it, which adds an extra cost to fix them.Hence, the empirical study of reopened security bugs is important.Our study collected the reopened security bugs from the Mozilla project, and analyzed them from the times of t

5、heir reopening and commits, files which were modified to fix them, lines of added and deleted code, and comparison of the original fixing and reopened fixing.The empirical results show that security bug reopening often happen and it relates to the complexity of recognizing the reason that a security

6、 bug happens and fixing bugs.In addition, the locality of the files and code in the original security bug fixing is one of the causes to influence its re-fixing for bug reopens, and using more complex and effective fixing process can help reduce the security bug reopens.Finally, we summarized severa

7、l causes for security bug reopens to help developers more easily identify the reopens of different types of security bugs.Keyword: Security bug; Reopens; Bug fixing; Empirical study; Received: 2016-10-071 引言在软件开发和维护过程中, 开发人员常常遇到程序运行状态与预期不符的情况, 如输出值不正确、程序死机、数据丢失等, 这种现象来源于程序的漏洞 (bug) 。开发人员如果在程序中发现漏洞的存

8、在, 则必定会停止开发工作来修复漏洞, 或者投入专门的人力和物力进行漏洞修复。不论是哪种应对方案, 都会不可避免地消耗开发资源, 使开发成本变得更加昂贵, 直接导致开发软件的利润变得更小, 软件竞争力下降。在众多漏洞类型中, 安全性漏洞是软件开发者在软件维护与更新的过程中重要的关注点之一1-3。安全性漏洞是指能被攻击者利用, 以在计算机系统中获取未经授权的访问或进行超出权限的行为的一种软件漏洞, 会导致安全性缺陷, 使计算机系统陷入危险之中。安全性漏洞不一定会导致程序崩溃或停止运行, 但其一旦被攻击者利用, 则可能会造成不可挽回的损失。有时, 漏洞的修复不能一蹴而就, 开发人员也不可避免地会发

9、生修复漏洞错误的情况。开发人员完成漏洞修复之后会关闭漏洞, 但如果发现这个漏洞未被完全修复, 为了使之修复正确, 需要重新打开 (reopen) 该漏洞来对其进行再修复, 以避免在开发人员自认为修复正确的情况下, 安全性漏洞却悄悄造成重大的损失。Zaman 等人4发现, 安全性漏洞相比于其他漏洞更常发生再修复。因此, 对安全性漏洞的再修复进行研究, 找出再修复与初次修复的隐含关系, 对于安全性漏洞再修复的预测和提供修复意见十分重要。本文主要通过对 Mozilla 工程中发生再修复的安全性漏洞的各项数据进行统计分析, 找到安全性漏洞在再修复时存在的各种修复规律, 如修改文件和代码较为分散的安全性

10、漏洞较容易发生再修复, 一些类型的安全性漏洞再修复会包含初始修复的修改模式、修复过程和修改的文件与代码。这些规律可为开发安全性漏洞再修复预测和自动化修复的工具提供经验支持。本文第 2 节介绍经验研究的一些背景知识;第 3 节介绍研究的设计, 包括数据来源、研究的数据和数据分类方式;第 4 节给出对数据分析的结果以及得到的规律;第5 节介绍相关工作;最后总结全文。2 背景知识2.1 漏洞生命周期一个漏洞通常遵循图 15所示的生命周期。图 1 漏洞生命周期 下载原图一个漏洞在被发现后会被发现者报告出来, 此时漏洞发生的根本原因、漏洞类型等信息还不确定, 这便是未确认 (UNCONFIRMED) 阶

11、段。下一阶段就是通过错误信息对漏洞发生的原因进行分析, 如果是新的漏洞, 就进入这个新漏洞的各种信息获取阶段 (NEW and ASSIGNED) ;如果与已有漏洞相同, 就标注为重复 (DUPLICATE) 。获取完漏洞信息之后, 即对漏洞进行修复, 修复完成则进入解决 (RESOLVED) 阶段。解决阶段之后就是对修复进行验证 (VERIFIED) 的阶段, 该阶段主要负责验证修复是否正确, 最后关闭 (CLOSED) 漏洞。在解决阶段和关闭阶段之后, 都有可能因为修复不正确或不完整需要重新打开 (REOPENED) 漏洞来重新对其进行修复。这个重新打开阶段承担的工作就是本文要研究的安全性

12、漏洞再修复。2.2 安全性漏洞分类OSVDB (Open Sourced Vulnerability Database) 是一个为安全性漏洞提供准确、详细、及时、公正的信息的独立且开源的数据库。OSVDB 为安全性漏洞分类提供了参考。结合对数据的分析及 OSVDB 的参考分类, 我们将研究中的安全性漏洞分为 7 类6:信息泄露、拒绝服务攻击、跨站脚本攻击 (XSS) 、缓存溢出、内存泄露、使用非法内存及其他。信息泄露是指在程序运行过程中, 一些数据应该被保护或加密, 未经授权的用户不能得到这些数据, 但这些数据在某些安全性漏洞存在的情况下会被恶意用户获取, 从而给系统或正常用户造成损失。拒绝服

13、务攻击是指使目标电脑的网络或资源过载或耗尽, 从而使服务暂时中断或停止, 导致其对客户不可用。跨站脚本攻击是代码注入的一种, 指在网站应用程序中存在安全性漏洞恶意用户通过这些漏洞在网页中插入恶意代码, 而当用户进入、使用该网站时恶意代码会被执行。恶意代码包括 JavaScript, Java 等。恶意代码执行完之后, 可能会获取更大的权限, 窃取隐私信息等, 给正常用户造成影响和损失。程序在运行时都会分配一定大小的缓冲区, 而当写入的内容超过缓冲区大小时, 就会造成缓存溢出。若这种缓存溢出未被系统或程序察觉, 则攻击者可能破坏程序的运行、获得程序甚至系统的控制权, 进而运行恶意代码进行一些破坏

14、性的操作。内存泄露是指在程序中一些已经使用过且不再需要的内存未被释放, 使得程序的可用内存越来越少, 最后导致程序因缺少内存而使部分功能被迫停止, 甚至程序崩溃。这种内存的减少并不是物理上的内存减少, 而是可分配使用的内存数量越来越少。程序中经常使用指针来储存和操作数据, 但如果这些指针是空指针、指向地址已经被释放或指向程序堆栈之外即不属于程序的内存地址, 则会使程序停止运行或崩溃, 这就是使用非法内存。通过这些安全性漏洞分类, 可针对每类安全性漏洞进行分析, 研究各类安全性漏洞自身的特点。2.3 安全性漏洞的修改模式安全性问题通常是因为攻击者非法对数据进行访问而引起的。在对安全性漏洞的分析中

15、, 安全性漏洞的修复大多并不复杂, 根据程序系统对数据处理的 3 个阶段 (数据的预处理、数据处理、数据确保) 对安全性漏洞的修复, 总结了如表 1 所列的一些修改模式。表 1 安全性漏洞的修改模式 下载原表 在数据进入程序阶段, 即数据预处理阶段, 通常会对数据做一些检测和筛选, 来防止外部数据对程序进行攻击。在数据处理阶段, 即程序对数据进行操作的阶段, 需要保证数据被正确、安全地处理。在数据被程序处理完成后, 系统通常会根据这些数据输出一些我们想要的结果, 而这些结果也可能因为处理过程的不理想而出现一些错误。针对这种情况, 需要进行数据确保工作, 以防止错误的处理结果对程序造成影响。在数

16、据确保阶段, 最常用的修改模式是添加 IF 模块, 对结果进行判断, 确认其为正确合法的结果。安全性漏洞的修改模式相较于其他类型的漏洞更为简单, 通常是针对数据的修改。安全性漏洞的修改模式不涉及对软件功能性的修改, 只是对可能产生安全性问题的数据在程序传播的各个阶段进行检查、确认, 针对不同的安全问题与传播阶段添加相应的防护机制, 使数据的使用变得更加安全。同时, 安全性漏洞的修改模式更具通用性, 能够将相同的修改模式应用于不同的安全性漏洞的修复, 而非安全性漏洞则难以总结出一些统一的修改模式, 只能针对不同的功能模块得出不同的修改方法。针对以上修改模式, 可以观察安全性漏洞再修复与初始修复使

17、用的修改模式之间的区别和联系。3 研究设计本文的研究主要围绕以下几个问题展开:(1) 安全性漏洞再修复的发生是否频繁, 以及与什么因素有关?(2) 哪种类型的安全性漏洞容易发生再修复且修复的难度较大?(3) 初始修复与再修复在修改模式、修复过程、修改内容方面有什么联系?3.1 数据来源本文选定 Mozilla 作为研究安全性漏洞再修复的数据来源, 它维护的全部都是Mozilla 产品的安全性漏洞, 且信息全面、清晰, 还能在 git 上找到对应的提交信息, 使得研究数据丰富且全面。在对安全性漏洞的修复工作中, Mozilla 维护了一个安全性漏洞管理的社区, 管理了 2005 年至今 Mozi

18、lla 发现的所有安全性漏洞的相关信息。漏洞报告中包含许多信息, 其中对研究有用的是以下几类信息:漏洞 id、漏洞描述、漏洞修改历史记录、漏洞修复评论。在漏洞修复评论中, 可以了解到修复人员的思考过程, 从中得出该安全性漏洞产生的原因、修复时对错误信息的分析、使用该种修复方式的原因、对漏洞再修复的原因、修复完成后进行了何种测试等信息。通过对这些信息进行分析, 明确了安全性漏洞修复的全过程, 从而得出安全性漏洞的类型、漏洞再修复的原因、漏洞每次修复使用的修复方式及原因、每次修复之间的关系等。漏洞修改历史记录 (见图 2) 中包含在每个时间点该漏洞处于何种状态的信息, 图 2 中表的第 5 列出现

19、“REOPEN”表示该安全性漏洞被再修复, 而在接下来的状态中第 5 列出现“FIXED”则表示该再修复完成。图 2 bug 修改历史 下载原图对安全性漏洞再修复进行分析时, 每次修复时代码的提交信息是必不可少的。Mozilla 将他们的项目提交到 git 上, 通过 git 可以得到 Mozilla 工程每次提交的漏洞 id、代码、提交者、提交时间、修改的文件、本次提交与上次提交的代码更改信息、修改相关信息等。但是, git 上的 Mozilla 工程只持续到 2011年, 因此能得到的提交信息年份为 2005-2011。通过 Mozilla 安全性漏洞社区和 git 项目数据, 总共获取到

20、 48 个可用的发生过再修复的安全性漏洞的相关数据, 这些安全性漏洞的 id 范围为 312278-672485。3.2 研究内容对这些安全性漏洞数据的分析主要包括 3 方面:漏洞的整体情况、初始修复和再修复的对比数据、修复过程中用到的数据。漏洞的整体情况数据包括:漏洞的 id, 漏洞的类型, 发生再修复的原因, 在 git上这个漏洞的修复提交的总次数, 所有修改的文件数, 所有修改增加和减少的代码行数, 发生再修复的次数。这些数据有助于分析安全性漏洞的基本信息中隐含的修复规律。初始修复与再修复的对比数据包括:两次修复时间的长短对比, 两次修复使用的修改模式的对比, 修改者的对比, 两次修复使

21、用的修复过程的对比, 两次修复修改的文件和文件中修改内容的对比。通过这些修复的对比数据可以得到再修复和初始修复之间的关系, 可通过初始修复推断再修复的修改模式、修改文件与内容、修复时需要注意的事项, 从而提供更方便的再修复方法。而通过修复过程的数据 (如评论、提交的代码) 对比, 可以得到修复者的思路, 并可从中找出安全性漏洞类型、再修复原因、修改模式、修复过程等。以上两方面数据, 有些通过对修复过程中的数据进行统计和分析获得。本文研究通过两种方式进行分类:安全性漏洞的类型和安全性漏洞再修复的原因。根据安全性漏洞的分类方式, 可以统计安全性漏洞再修复发生的次数、再修复的原因、这类安全性漏洞提交

22、的总次数、总的文件修改数、增加的代码行数和删除的代码行数。在这些数据的支持下, 对以下问题进行研究:安全性漏洞整体情况的分析;不同类型的安全性漏洞较容易发生哪种再修复;不同类型的安全性漏洞在修改时修改文件、修改的代码数量等有什么规律。通过对安全性漏洞再修复的原因进行分类, 收集初始修复与再修复两方面的数据:使用的修改模式, 修复过程, 修复所用的时间, 修改者, 两次修改对文件及代码的影响。通过收集到的数据, 研究如下问题:安全性漏洞再修复的原因;再修复和初始修复使用的修复过程有什么联系;两次修复的修改时间和修改者有什么联系;两次修复使用的修改模式有什么联系;两次修复修改的文件和内容有什么联系

23、。4 数据分析4.1 基础数据统计实验共收集到 721 条安全性漏洞信息和 48 条发生再修复的安全性漏洞。在Mozilla 工程中, 安全性漏洞发生再修复的概率约为 6.7%, 再修复的概率较高4。安全性漏洞在所有 id 和时间段都有发生再修复, 由此可见, 安全性漏洞发生再修复是一个普遍存在且发生概率比较高的问题。通过对安全性漏洞再修复的信息进行分析, 找到减少再修复、预测再修复、帮助再修复的方法, 有助于提高程序的安全性, 减少开发、维护的资源消耗, 使得程序员在对安全性漏洞进行修复时更加全面、正确, 减少对安全性漏洞再次修复的次数。如表 2 所列, 在 48 个发生再修复的安全性漏洞中

24、, 37 个发生了 1 次再修复, 10 个发生了 2 次再修复, 只有 1 个发生了 3 次再修复, 未见超过 3 次的再修复。在修复安全性漏洞时, 发生 1 次再修复可能是对漏洞的理解有遗漏;发生 2 次再修复就需要程序员特别注意自己的修复以及对漏洞的理解是否正确;唯一一次发生了 3 次再修复的漏洞是对漏洞进行登记和测试, 因此通常情况下不会发生超过 2 次的再修复。多次发生再修复不仅会对资源造成浪费, 还会加大系统的危险性, 给攻击者更多机会。表 2 安全性漏洞修复基础数据统计 下载原表 发生 2 次再修复的安全性漏洞大多是缓存溢出, 发生 1 次再修复的大多是跨站脚本攻击, 其他的比例

25、都比较接近。而这几种类型的安全性漏洞 git 提交的平均次数都比较接近, 使用非法内存修改的文件数最多, 内存泄露最少。在减少和增加的代码行数方面, 内存泄露和缓存溢出分别为减少和增加代码行最多的, 缓存溢出和内存泄露分别为减少和增加代码行最少的。缓存溢出和内存泄露虽然涉及的文件数较少, 但是修改的代码行数却较多, 说明这两类安全性漏洞问题比较集中, 修复时所涉及功能的关联性比较强。而使用非法内存和跨站脚本攻击涉及的文件较多, 但是修改的代码行数较少, 说明这两种安全性漏洞涉及的功能较为分散, 修改的文件范围较广, 修复时较容易有遗漏, 考虑得不够全面。4.2 安全性漏洞再修复的原因在对数据进

26、行分析后, 得到以下几个发生再修复的原因:加强漏洞填补 (范围加强、强度加强) ;减弱漏洞的填补;填补原来没有考虑到的漏洞 (线性关系、并列关系) ;对修复进行登记或测试;以前修复无效或错误而重新修复;怀疑修复造成了错误, 后来发现不是 (误诊) 。实验中统计的 48 个发生了再修复的安全性漏洞中, 每种类型的再修复数量如表3 所列。表 3 再修复类型统计 下载原表 从统计数据可知, 除了减弱漏洞的修复数量较少以外, 其他再修复的原因数都比较平均, 再修复时一般会修复得比较适度或未修复完全, 修复过强的情况比较少。修复过强则表示安全性漏洞发生的原因分析正确, 且修复方式也正确, 只是限制过于强

27、烈, 避免这种再修复最好的方法是衡量好限制的强度与影响。而在填补原来未考虑到的漏洞中, 线性关系的安全性漏洞也比较少, 这种再修复的发生是对数据源头判断得不准确或未考虑数据的来源, 修改比较简单, 只要找出数据的源头并添加保护机制即可。上面的数据中有些类型再修复数据量较少, 对发现普遍性规律有一定的影响, 使得偶然性大大增加。4.2.1 加强漏洞的填补在修复安全性漏洞时, 有时可能是临时性填补, 安全性还不够高, 还存在着一些安全隐患, 后续需要对漏洞重新修复, 从而提供更高的安全性防护;又或者可能是修复的范围不够广, 同一个问题在不同的地方出现, 此时只要将修复延伸至更大的范围即可。这些再修

28、复就是对漏洞填补的加强。加强漏洞的填补可根据加强的再修复和原修复之间的关系分为强度加强和范围加强。可以对安全性漏洞进行临时性填补是安全性漏洞修复的一个特点。临时填补是为了在没有时间和资源进行完全修复时, 尽量减少安全性漏洞的作用力和危害, 甚至用一些非常糟糕、后期难以识别维护的修复来修复漏洞。当然, 这样做只是暂时使软件能继续运行, 不至于因为软件停运造成损失, 在有时间和资源时重新对漏洞进行修复, 以保证修复的完整性与安全性, 这就是加强漏洞修复的强度。例如, 对于安全性漏洞 329385, 攻击者可以利用这个安全性漏洞进行强制性鼠标操作。初始修复时对 UI 进行修改, 使得与这个漏洞相关的

29、 UI 界面暂时停止相关功能。这样修复虽然可以解决问题, 但是会造成一些功能无法使用, 且真正能够强制操控鼠标操作的原因并没有找到。而在再修复中找到了真正的原因, 并对其进行了修复, 也使得 UI 的相关功能得以正常运行。另一种对漏洞修复的加强是范围的加强, 即对某个安全性漏洞的修复方式是正确的, 但是修复作用的范围未完全包含所有出问题的地方, 再修复时只需要将之前的修复作用于剩下的地方即可完成完整的修复。例如, 对于安全性漏洞 370127, 其传递了某个不安全的方法作为新方法的父方法, 而这个新方法如果被调用, 则会由于父方法产生安全性问题。一开始的判断是 js 代码会调用到这个新方法,

30、因此初始修复是在 js 调用该新方法时做一些安全性防护, 以保证调用时不会传入不安全的父方法;后来却发现不但 js 代码会调用该新方法, C+代码某功能也会调用这个新方法, 因此再修复要做的就是将原来的防护方法作用于 C+的调用, 使得不论是哪种调用都能安全完成。4.2.2 减弱漏洞的填补与增强相反, 减弱漏洞的填补也是安全性漏洞再修复的原因之一。在修复安全性漏洞时, 如果对漏洞的防护太强, 可能会导致一些功能被限制, 一些合法数据被阻拦过滤, 这样依旧会导致安全性问题。例如, 对于安全性漏洞 419848, js 通过导入一些脚本作为其内容来使用, 这样可能会导入不安全的脚本, 在系统权限下

31、对程序造成危害。因此, 初始修复就对 js 能导入的脚本进行了限制, 使得某些 url 的脚本不能被导入。但这种限制太强, 导致一些合法的脚本因含有相应的 url 而不能被导入, 程序不能正常运行。再修复就是导入一些程序必须但不能获得系统权限的脚本, 以保证程序安全地正常运行。4.2.3 填补原来没有考虑到的漏洞一个安全性漏洞的发生可能是因为多个地方有安全性问题, 这些不同地方的安全性问题导致了同样的安全性漏洞。而在安全性漏洞的修复过程中, 如果只修复了其中一部分安全性问题, 另一部分未发现或被忽略, 那么这个安全性漏洞就是修复不完整, 因此会发生再修复。因为填补原来没有考虑到的漏洞而发生的安

32、全性漏洞再修复, 可以根据具体的安全性问题之间的关系分为两种情况。1) 原修复和再修复是线性关系。这就好比一条河流发生洪水, 如果在中流抗洪, 并不一定能达到最好的效果, 而如果找到发生洪涝的源头, 在源头治洪, 效果会好很多。例如, 安全性漏洞 312278 发生的原因是某变量在未使用之前就被垃圾收集器释放了它所指向的内存地址, 因此在后面使用该变量时就是使用非法内存。第一次修复是在发现内存被垃圾收集器释放的地方管理那个变量, 使之不能被释放掉。但是后来发现这个变量被释放的源头不是这里, 变量在被管理起来之前就有可能已被垃圾收集器释放。因此, 再修复就是找到变量的源头, 在源头对变量进行管理

33、, 使得变量不会被释放。2) 初始修复与再修复是并列关系。初始修复和再修复解决的安全性问题不是相同的方法或功能, 它们的修复方式可能不一样, 但是都会导致安全性漏洞。这些并列的安全性问题可能是因为难以全部找到或者经常容易被忽略, 从而导致再修复的发生。例如, 安全性漏洞 360529 是因为可以通过某些方法获得浏览器的权限来运行一些恶意代码, 是跨站脚本攻击。针对这个安全性漏洞的修复, 自然是找出这些方法并对它们进行保护, 防止其被攻击者利用。初始修复是对Array.prototype 和 document.write 进行保护, 并认为成功修复了这个漏洞。但是后来发现 appendChild

34、 () 和 removeAttribute () 也会有这种问题, 因此第二次修复就是对这些方法进行保护, 但其实对每个方法进行保护的方式并不相同。这种再修复原因与加强漏洞修复的范围的区别在于, 用到的修复方式不同。加强漏洞修复范围中, 初始修复和再修复运用的修复方法是一样的, 只是作用的地方发生了变化;而填补原来没考虑到的漏洞 (并列关系) 则是初始修复和再修复运用的修复方式可能不同, 针对的安全性问题也不同, 但是这些安全性问题都会导致同一个安全性漏洞。4.2.4 对修复进行登记或测试有时重新打开安全性漏洞并不是因为原来的修复存在问题, 而是对完成的修复进行登记, 比如验证、加入实际项目中;又或者是对其进行测试, 以保证修复的安全性与正确性。这种再修复不涉及到原修复的改动, 而是对原修复做一些操作。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 学术论文 > 期刊/会议论文

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报