雷锋网 AI 开发者按:如今,越来越多的软件开发者通过重用问答网站分享的代码片段来解决一些实际问题,如 Stack Overflow 平台就包含了大多代码来源。尽管复现源代码有助于快速原型化;然而最近的研究表明,你所用的很多共享代码片段可能质量很低,甚至包含大量漏洞!研究人员通过对 10 年内共享堆栈溢出 C++代码段中的安全漏洞进行深入拆解,发现在堆栈溢出中 69 个易受攻击的代码段在 GitHub 上共计 2859 个项目中被重用。
众包代码示例中安全漏洞的性质和普遍性到底是什么?面对这些漏洞,我们又该如何选择安全的代码段?为了帮助提高共享代码段质量,研究者也开发了一个工具,允许堆栈溢出用户在将代码段上载到平台时检查其中的漏洞。雷锋网(公众号:雷锋网) AI 开发者将该研究核心内容及结论整理编译如下,或许能够给广大开发者重用共享代码时些许启发。
研究背景
一直以来,软件开发的一个主要目标是以及时和经济高效的方式交付高质量的软件;所以代码重用也被视为一种公认的实践方式,共享代码片段和代码示例也是一种常见的学习方式。新手甚至更高级的开发人员利用在这些平台上共享的代码示例和解释,学习如何执行新的编程任务以及使用某些 API。
其中,这些重用的代码片段来自许多不同的源代码和不同的形式,例如:第三方库、开源软件和问答(Q&A)网站等。但近来有研究表明,在问答网站以及 GitHub 中托管的开源软件存储库的知识流和知识共享中,一些代码片段不仅质量差,而且还是有病毒的;这些片段甚至还在 GitHub 上共计 2859 个项目中被重用。
安全性是质量的一个重要方面,如果易受攻击的代码片段从堆栈溢出迁移到应用程序,这些应用程序将容易受到攻击。
历史发现及现状
此前,有很多研究人员通过对重用代码片段进行检测,发现了这些问题:
Xia 等人表明大量开源系统重用过时的第三方库,这可能会对软件造成有害影响,因为它们可能会在软件中引入安全缺陷。
Abdalkareem 等人检查了 f-droid 存储库,并确定了堆栈溢出 post 和 android 应用程序之间的克隆。他们发现,从 so posts 复制的代码会对应用程序的质量产生不利影响。
Yang 等人分析了托管在 GitHub 上的 909k 个非 fork python 项目,其中包含 290m 个函数定义,以及在堆栈溢出中捕获的 190 万个 python 片段,并对块级代码克隆堆栈内和堆栈间溢出以及 GitHub 进行了定量分析。
Akanda Nishi 等人研究了两种流行的软件开发信息源之间的代码复制:堆栈溢出问答站点和软件开发教程,以了解重复信息随时间的演变。
安等人调查了 399 个 Android 应用程序和堆栈溢出帖子之间的克隆。他们发现了 1226 个代码片段,这些代码片段被 68 个 Android 应用程序重用。代码片段的重复使用导致 1279 例潜在的许可证冲突。
Fischer 等人发现从堆栈溢出复制到 196403 个Android 应用程序的不安全代码片段,已在 google play 上发布。
Zhang 等人通过检查 API 调用的误用,研究了堆栈溢出代码片段的质量。他们报告说,大约 31% 的分析代码片段可能包含可能导致失败和资源泄漏的 API 误用。
Rahman 等人检测到七种安全气味,表明 IAC 脚本中存在安全漏洞,并识别出 21201 次安全气味,包括 1326 次硬编码密码。
Zahedi 等人研究了 GitHub 存储库中的问题主题,发现其中只有 3% 与安全性相关。这些安全问题中的大多数是密码问题。
Pletea 等人研究了 GitHub 的安全相关讨论,并报告它们代表 GitHub 的所有讨论的大约 10%。他们还报告说,与安全有关的讨论往往与消极情绪有关。
Acar 等人对活跃的 GitHub 用户进行了一项实验,以检验安全相关研究中招募便利样本的有效性。他们发现,参与者的自我报告状态(即学生或专业开发人员)和参与者的安全背景都与他们成功完成安全任务的能力无关。
但目前,大多数在堆栈溢出上的代码片段安全性方面研究集中于 Java 和 Python;忽略了 C++——最流行的第四种编程语言(https://www.tiobe.com/tiobe-index/)。
它是嵌入式资源受限程序的首选语言,并广泛应用于大型和分布式系统中;因此 C++非常容易出现误用(例如:内存损坏错误),这很容易导致易受攻击的代码和可开发的应用程序,这表明 C++代码段中的漏洞可能会产生更严重的影响。本文则旨在填补 C++语言代码共享的安全性研究空白,并帮助更多开发者了解堆栈溢出时共享的代码示例中安全漏洞的性质和普遍性。
研究维度及问题
研究人员发现,堆栈溢出问题是在编程问答(Q&A)社区被问得最多的。因此,对堆栈溢出的研究在软件界具有重要意义。为了使得研究结果更具代表性,研究人员从以下两个维度对堆栈溢出中共享的代码示例中的 C++漏洞进行了实证研究:
普遍性 主要对堆栈溢出数据集中包含的某个称为 StoTrOrm 的 C++漏洞类型进行了深入研究;并分析了它们随时间,特别是它们迁移到 GitHub 项目中的演化过程。
传播度 研究如何在 GitHub 存储库中重用易受攻击的代码片段。
了解在源代码示例中 C++漏洞的普遍性和传播度
围绕源代码示例中 C++漏洞的普遍性和传播度两个维度,研究人员探讨了以下问题:
1. 堆栈溢出代码段中的 C++漏洞有多普遍?
2.GitHub 存储库中如何重用易受攻击的堆栈溢出 C++共享代码?
研究过程及数据集
案例研究的总体步骤
为了研究堆栈溢出 posts 的演变及其与 github 的关系,使用了 sotorrent 数据集版本 2018-09-23。
这个版本的 sotorrent 包含了从 2008 年到 2018 年的帖子。总共有 41472536 个问答帖子和 109385095 个帖子版本,其中 206560269 个帖子版本包含 6039434 个软件项目链接。有 3861573 个链接指向公共 GitHub 存储库。
Sotorrent 提供对堆栈溢出内容十年的版本历史的访问。如图 2 所示,可以独立访问整个 post、单个文本或代码片段。
Sotorrent 提供的历史数据
研究结果
最终,研究人员从至少一个 GitHub 项目中重用的 72483 个 C++代码片段中,发现了属于 29 种不同类型的漏洞达到 69 个;而这 69 个易受攻击的代码片段,用于 Github 文件中的有 2589 个,并且从堆栈溢出传播到 Github 的最常见漏洞是 CWE150。
这里,CWE(Common Weakness Enumeration)是社区开发的通用软件安全弱点列表。它可以作为一个软件安全工具的测量棒,以及作为识别、缓解和预防弱点的基线。CWE 的目的是促进在程序分发给公众之前,有效地使用能够识别、发现和解决计算机软件中的错误和漏洞的工具。
问题一、堆栈溢出代码段中的 C++漏洞有多普遍?
总体上,所有 C++回答从 2008 到 2018 的分布如下图所示。2013 年既是 C++回答最多的一年,也是 C++在 GITHUB 项目中迁移最多的时候。
C++中按年份分布的回答
研究人员对代码片段的手动检查发现,69 个回答中存在 99 个易受攻击的代码片段。通过查看易受攻击回答的分布,他们发现最易受攻击的答案是在 2011 年创建的,如下图所示。
每个回答中的 CWE 频率
代码片段中 CWE 的频率如下图所示,可以看到 CWE-1006 和 CWE-754 是最常见的安全隐患。
代码片段中 CWE 的频率
下表说明了已找到的 CWE 列表。有关 CWE 的完整说明,请参见(https://cwe.mitre.org/)。
不同类型的 CWE C++漏洞及其频率,如我们在堆栈溢出数据集中所观察到的,X 轴上的每一个刻度表示一年的最后一个/两个字母,例如 2016 对应 16,2008 对应 8
下面是研究人员所检查代码片段中发现的一些漏洞示例。
漏洞示例一
下面这个代码片段可能很危险。
显示由于使用不正确的使用方法的 RAND 函数而导致的脆弱性(CWE-1006、CWE-477、CWE-193、CWE-754)
具有计数参数(如「len」)的函数应将终止的「null」作为额外字符考虑在内。但这个函数实际上是在执行 s[len]=0 时写入字符'len+1'。这就是 CWE-193:OffbyOne 错误漏洞,它可能导致不可预测的行为、内存损坏和应用程序崩溃。如果产生一个特殊的并且总是在最大长度上传递一个小于期望值的数字,函数就正常工作,否则就可能崩溃。
CWE-193:OffbyOne 错误漏洞
https://cwe.mitre.org/data/definitions/193.html
行's[i]=alphanum[rand()%size of(alphanum)-1]'也有问题,因为'alphanum'的大小是'63',其中索引第 69 个字符串的最后一个字符是'null'。因此,偶尔会在生成的「随机」字符串中包含一个空值。此漏洞可归类为「CWE-754:异常或异常情况的不正确检查」,其中不正确的数字可用于返回导致崩溃或其他意外行为的函数。另一个合适的类别是「CWE-1006:错误的编码实践」。换句话说,使用此算法生成的随机字符串也会使得在字符串中间包含「null」。
CWE-754:异常或异常情况的不正确检查
https://cwe.mitre.org/data/definitions/754.html
此外,在 C 和 C++中,「反汇编」是一个过时的函数。因此,另一个漏洞类别是「CWE-477:使用过时功能」,这是软件质量退化的一个主要原因。还有一个漏洞存在于代码中,因为开发人员在调用函数之前没有使用随机种子。因此,生成的随机数根本不是「随机」的。此外,「rand()%mod」不是一个好的做法,因为它返回的低位不再是随机的。
rand()%mod:
http://c-faq.com/lib/randrange.html
漏洞示例二
显示了由于在不检查返回特殊条件的情况下使用 malloc 函数而导致的漏洞(CWE-1006、CWE-252、CWE-789、CWE-476)
此回答中的代码片段使用「malloc」分配内存,并将其指针传递给 qt 库中需要有效指针的函数。如果 malloc 失败,malloc 返回指针可以设置为空。因此,即使请求的内存量很小,也必须检查 malloc 的返回指针 [54]。在本例中,不检查 malloc 的返回值。此漏洞称为 CWE-252[55];未经检查的返回值。如果 malloc 失败,则会发生空指针取消引用。
malloc 返回指针
https://docs.microsoft.com
CWE-252
https://cwe.mitre.org/data/definitions/252.html
漏洞示例三
显示了由于用户输入是 volved 而导致操作系统命令注入的漏洞(CWE-78,CWE-1019)
所示的函数易受代码注入(OS 命令注入)攻击,因为用户输入的命令是输入的,而不是检查的。换言之,任何具有程序特权级别的命令都可以在没有任何错误或警告的情况下执行。
漏洞示例四
显示由于此函数中的第二个参数可能包含多个由「;」分隔的路径而导致的漏洞(CWE-754、CWE-252、CWE-426)
以编程方式处理系统路径,或程序搜索的不同路径。这个操作很危险,应该小心操作。例如,此函数中的「path」可以包含由「;」分隔的多个路径,如:「/usr/share/lua/foo/bar/evil/path」。在路径中有一个不受信任的搜索路径会产生以程序权限执行任意代码的可能性,并重定向到可能触发崩溃的错误文件。此漏洞称为 CWE-426:不受信任的搜索路径。搜索可能导致程序执行,进而导致异常或异常情况;即 CWE-754:对异常或异常情况的不当检查。此外,不检查代码段中函数的所有返回值。因此,代码片段还具有 CWE-252:未检查的返回值。
CWE-426:不受信任的搜索路径
https://cwe.mitre.org/data/definitions/426.html
漏洞示例五
显示了由于越界读取和缺少检查变量大小而导致的漏洞(CWE-20、CWE-125、CWE-1019)
在漏洞示例五所示的代码中,由于「current index+size of(t)」可能会大于「vec」的大小,而存在 CWE1019:validate inputs 漏洞。此外,当索引超过限制时,可能会发生信息泄漏或 CWE125;存在「越界读取」漏洞。
漏洞示例六
如果包含空值的输入字符串(CWE-158,CWE-1019)失败,则所有定义的函数都有漏洞
所示关于如何验证文件名是否以「.txt」结尾的代码中,包含了 answer post 原始代码片段中六个方法的函数代码及其基准。此代码段中定义的其他函数的漏洞与这两个易受攻击的函数完全相同。但如果函数中的文件名包含空字符,则以上所有方法都将失败。这是绕过 web 应用程序防火墙和文件上传程序的常见技巧。示例:对于以上所有函数,验证「shell.txt/0.php」将返回 true。
问题二、复制到 GitHub的易受攻击的代码示例频率
我们发现的大多数易受攻击的代码段都是函数或函数的一部分。因此,研究人员使用了基于 sourcerercc 等克隆检测工具的一些启发式方法,在链接的 GitHub 项目中搜索并找到 10 个类似的代码。
下面给出了两种方法(选择关键字和随机关键字)的结果,并将其与基线方法进行了比较。
结果
69 个易受攻击的答案的 GitHub 文件总数为 2859 个 GitHub 链接,这些链接显示在下表中,由 CWE 定义分隔。研究人员通过相关的算法发现 287 个 GitHub 易受攻击的文件都可能存在安全漏洞。
GitHub 存储库中使用所选关键字算法的 CWES 检测
问题三、修复复制的易受攻击代码示例的概率
研究人员创建了一个新的 web 应用程序,使评审过程更加高效和系统。通过审查系统,他们评估了迁移到 GitHub 的易受攻击的堆栈溢出代码段是已修复还是仍包含该漏洞。
结果
在被检查的 287 个 GitHub 文件中,有 34 个文件中的漏洞得到了纠正,其他 253 个 GitHub 文件仍然存在漏洞。如下图代码所示,更正了 CWE-789 和 CWE-252 两个漏洞。
在 GitHub 文件中,堆栈溢出中回答的修复与部分代码改进
CWE-252
https://cwe.mitre.org/data/definitions/252.html
CWE-789
https://cwe.mitre.org/data/definitions/789.html
如下图代码所示,对 cwe-125、cwe-category-1019 和 cwe-20 进行了更正。
在注释提到的 GitHub 文件中修复了代码
CWE-125
https://cwe.mitre.org/data/definitions/125.html
CWE-category-1019
https://cwe.mitre.org/data/definitions/1019.html
CWE-20
https://cwe.mitre.org/data/definitions/20.html
用户对代码中存在漏洞的看法
下图中显示了一些用户对其项目中的漏洞的响应。可以看到,有很多开发者在重用这些代码片段时,并没有注意到其中所包含的潜在威胁。
用户对其代码中的安全漏洞的响应
用户也针对自动检测漏洞的有用性,进行了个人看法的讨论。大部分人都认为检测漏洞是一个非常有用且重用的事情。
用户对有助于未来开发的自动漏洞分析的意见
用户也发表了对漏洞处理的最佳方法,大多数实践者同意使用自动安全机制来检测代码中的漏洞。他们表示,使用浏览器扩展和脱机工具运行临时堆栈溢出方法比其他方法更有效,可以将代码示例中的漏洞告知用户。
如何告知开发人员代码示例中的潜在漏洞意见
解决方案
在我们收到的针对 GitHub 所有者的 117 个问题的 15 个响应中,40% 指出了代码中存在漏洞的可能性,前提是他们的输入数据不是动态的,13.3% 承认代码中存在漏洞,但不愿意修复。
GitHub 所有者选择对其代码中存在的漏洞进行了注释
为了告知用户代码中存在的漏洞,研究人员也开发了浏览器扩展。该浏览器扩展旨在防止开发人员重用此类易受攻击的代码段,并向他们推荐更好的替代方案,即在其他堆栈溢出帖子中使用不易受攻击的代码段。
当开发人员访问堆栈溢出 post 时,扩展将被激活。该扩展参考堆栈溢出中易受攻击的 C++代码片段的数据库,以确定在 POST 中提供的解决方案是否是不安全。如果确实发现提供的解决方案易受攻击,则扩展将向开发人员显示一条警告消息,并解释代码片段易受攻击的原因。
警告消息截图
然后,扩展将推荐来自其他堆栈溢出帖子的不易受攻击的类似代码段,以便开发人员可以重用这些安全代码段,而不是易受攻击的代码段。不过,该扩展目前也存在一定的有效性威胁,这也与之前所使用的检测方法有关,使用这一启发式方法来检测从堆栈溢出到 GitHub 的易受攻击的C++代码片段,可能会存在部分代码丢失的情况。
因此,在面对复制而得的代码时,只有小心严谨才是王道啊!!!
论文地址:
https://arxiv.org/pdf/1910.01321.pdf
浏览器扩展:
https://github.com/paper-materials-crowd-sourced/materials
相关资讯:
https://fossbytes.com/copying-codes-from-stack-overflow-leads-to-vulnerable-github-projects/
雷锋网 AI 开发者