写点什么

为什么 StackOverflow 上的代码片段会摧毁你的项目

  • 2020-11-27
  • 本文字数:2585 字

    阅读完需:约 8 分钟

为什么StackOverflow上的代码片段会摧毁你的项目

本文最初发布于Mahdhi Rezvi个人博客,经原作者授权由 InfoQ 中文站翻译并分享。


在 StackOverflow 上你会惊奇地发现,上面分享的一些解决常见问题的代码居然存在安全漏洞。


包括我在内,现在 StackOverflow 已经成为许多程序员的救星。我们中的大部分人甚至从未访问过 StackOverflow 的主页。我们访问该网站的唯一方式,是通过谷歌搜索某个我们遇到的问题或 bug,然后直接进入该问题的讨论区。


尽管去 StackOverflow 上寻找问题解决办法的习惯很实用,但与此同时我们可能也会无意中使用一些包含严重 bug 或者安全缺陷的代码。众所周知,直接从 StackOverflow 上复制代码来用是不合适的,但开发人员仍会这么做,这里引用 Ryan Donovan 的一句话:


代码复制本身并非坏事,代码重用能提高软件开发效率。为什么已经被完美解决的问题,还要再去重新解决一次呢?但是当开发人员不加理解就去使用示例代码时,那么问题就来了。


你可能会认为那些安全恐慌都只是都市传说,但我可以向你保证并不是。


最近我遇到的几件事,引起了我对这个问题的关注,下面我把这几件事简单说明下。



插图Mateusz Kupilas提供


StackOverflow 上拷贝次数最多的 java 代码片段,一直都存在缺陷。


首次知道这个信息是在一篇博客中读到的,而这篇博客的作者正是那个 java 代码的提供者,点击这里查阅博客原文。


Andreas Lundblad 是这段代码的作者,他是 Palantir 的 Java 开发人员,同时也是 StackOverflow 上排名最高的贡献者之一,他在博客中承认了此代码的缺陷。


2018 年,Sebastian Baltes 在《实证软件工程》期刊上发表了一篇研究论文。该论文指出 Andreas 在 StackOverflow 上发布的一段 Java 代码是 StackOverflow 上被拷贝次数最多的 Java 代码,甚至被多次使用在开源项目中,在 GitHub 上至少有 6000 多个 Java 项目使用了该代码片段。


该段代码是为了回答于 2010 年发布在 StackOverflow 上的这个问题。它的功能是将字节计数转换为更易于阅读的格式。例如,它将 1024 字节转换为 1kB 或将 1048576 字节转换为 1 MB。


Andreas 在被 Sebastian Baltes 告知这段代码的惊人传播量后,重新评审了这段代码。且随后在其个人博客中发布了更正后的版本,同时在博客的最后还给出了一些有价值的建议:


  • StackOverflow 上的代码段可能存在 bug,即使它们有成千上万的赞成投票。

  • 测试所有的边缘情况,特别是从 StackOverflow 复制的代码。

  • 在复制代码时,一定要包括其来源和贡献者,当出问题时,能快速定位。


尽管这个 bug 是一个微不足道的边缘情况,只会导致对文件大小计算的不精确,但实际情况可能会更糟,我们来看更多的例子。


StackOverflow 上流行最广的 c++代码片段存在重大安全缺陷


2019 年,Morteza Verdi 等人发表了一篇研究论文。该论文指出,过去 10 年里,StackOverflow 上流行最广的 c++代码片段中有 69 个存在重大安全漏洞。这 69 个经确认易受攻击的代码片段被使用到了 2589 个 GitHub 项目中。据研究者指出,从 StackOverflow 传播到 GitHub 上的这些代码中,最常见的安全漏洞是CWE150:


CWE 是社区开发的常见软件和硬件安全缺陷列表。它是一种通用语言,是安全工具的衡量标准,同时也是缺陷识别、规避和预防的基础。


CWE150 指的是空间、元空间或控制空间出现不适当中和的情况。


该论文的研究人员还开发了一个 chrome 扩展,当开发者查看 StackOverflow 代码片段时可以提醒开发者当前阅读的代码是否存在安全漏洞。虽然这个扩展一般用途不大,不过如果感兴趣的话,可以点击这里查看它的源代码。


不能在 Windows 上同时运行 Docker 和 Razer Synapse 驱动管理工具,因为他们存在 StackOverflow 式的 bug


大约 2 年前,在 Windows 上运行 Docker 时有个奇怪的现象,即用户无法在 Windows 系统的机器上启动 Docker。这个奇怪的现象后来被人以问题的方式在 Github 提了出来。随后有很多其他人也说遇到了相同的问题。直到 Reddit 上的这篇文章发布之前,都没人知道根本原因是什么。


该文章指出,当 Windows 后台启动了 Razer Synapse 时,此时再去启动 Docker 就会触发此问题。其原因是,在 Razer Synapse 运行的时候,Docker 会认为已经有一个 Docker 实例正在运行中,所以 Docker 不会再启动一个实例。


两个应用程序各自都只允许同时启动一个自己的实例,这个需求看上去是个再合理不过的需求了。但是现实却是,这个限制确实是该 bug 的根本原因。下面是引发问题的代码片段:


var name = string.Format("Global\{0}", (object) Assembly.GetExecutingAssembly().GetType().GUID);
复制代码


从上面的代码可以发现,问题就出在返回的 GUID 类型上。此处返回的 GUID 类型是 System.Reflection.RuntimeAssembly(系统层面的运行时程序集),而不是 Windows 中对应 Docker 程序集中定义的类型。


译者注:以上代码说明,在控制同一时间只允许运行一个实例,Docker 的处理方式是通过判断 GUID 是否存在,但获取在 GUID 时,用的是系统层面的而非自己独立程序集里面的。


更有趣的事情是:


如果只有一个应用程序使用了上面的错误代码,那么上述问题根本就不会出现。但现实是,很多应用程序都使用了该错误代码,结果不允许两个实例同时运行。


你认为上面两个应用程序包含的错误代码片段是从哪里来的呢?


我想你已经猜到了,没错,正是来自于 StackOverflow。


在.net2.0中应用如何通过程序拿到GUID,这篇不正确的 StackOverflow 文章,就是这些应用程序错误代码的来源。


你现在去看问题的答案,已经看不到有缺陷的回答了。他们已经重新编辑了答案。如果你想自己手动去查找,可以通过Wayback Machine来查看历史文章,查询结果如下图:



截图由Кекек Мачан提供


对开发人员的重要启示:


  • 考虑一下如何在自己的程序中找到这个 bug

  • 你所拷贝的代码表面上似乎能正确的运行,但其实你没有意识到的是,此代码本身就是缺陷代码——因为你的程序中没有引发错误的场景


所以,我们该避免拷贝吗?


并非如此,直到今天,Stack Overflow 对于任何程序员来说,都是必不可少的。但在项目中因拷贝代码引起的大多数问题都是基本的安全问题。因此如果你能事先弄懂你所拷贝的代码,那么是可以正确使用的。即使如此,当准备在生产环境中使用这些代码时,也最好先做好充分的测试,特别是一些边缘场景,下面引用 Ryan Donovan 的一句话:


“如果你引用别人的代码,但你却不理解所引用代码的内容;那么您就会陷入重用具有潜在漏洞的代码的陷阱,同时这些包含漏洞的代码也就被你传播开了。”如果您要重用代码,那么请您先理解这些代码。


祝您编程愉快!


原文链接:


Why Code Snippets From Stack Overflow Can Break Your Project


2020-11-27 17:001948

评论

发布
暂无评论
发现更多内容

又是一季金三银四,Spring之AOP知识要点总结

Java你猿哥

spring Spring Boot ssm aop

超实用VS Code for Windows快捷键

SEAL安全

vscode 企业号 4 月 PK 榜

慕了!17年阿里架构师把Spring Boot的精髓都总结出来了

Java你猿哥

Java spring Spring Boot Spring MVC Java工程师

版本控制 | 告别繁琐,P4VJS带来全新的Diff体验

龙智—DevSecOps解决方案

版本控制 版本管理

想拿到10k-40k的offer,这些技能必不可少!作为程序员的你了解吗

Java你猿哥

Java 面试 架构师 面经 Java工程师

SSD 存储领域厂商大普微加入龙蜥社区,完成与龙蜥操作系统适配

OpenAnolis小助手

开源 操作系统 龙蜥社区 CLA 大普微

龙智荣获Perforce公司颁发的2022年度销售与技术两项大奖

龙智—DevSecOps解决方案

版本控制

“ONE”有引力,4月21日见!

博睿数据

智能运维 博睿数据 发布会 Bonree ONE

HummerRisk 使用教程:镜像检测

HummerCloud

镜像安全 云原生安全

前端里那些你不知道的事儿之 【window.onload】

京东科技开发者

前端 京东云 京东技术 京东科技 企业号 4 月 PK 榜

Go flag 标准库源码解读

江湖十年

后端 命令行 Go 语言

【ChatGPT系列话题】金融行业大语言模型应用落地

易观分析

人工智能 金融 模型

Hive 和 Spark 分区策略剖析

vivo互联网技术

spark hive

机器学习实战系列[一]:工业蒸汽量预测(最新版本下篇)含特征优化模型融合等

汀丶人工智能

人工智能 数据挖掘 机器学习 LightGBM

​openEuler 23.03 正式发布,聚集社区创新力量,增强基础技术能力,协同全场景创新

openEuler

Linux 运维 操作系统 openEuler 桌面开发

你kin你擦!阿里终于肯把内部高并发编程高阶笔记开源出来了

Java你猿哥

Java nginx 高并发 SpringCloud 面经

如何打造企业专属A/B平台?火山引擎DataTester开放平台技术揭秘

字节跳动数据平台

大数据 AB testing实战 开放平台 企业号 4 月 PK 榜 企业增长

集成华为运动健康服务干货总览

HarmonyOS SDK

HMS Core

龙智被SmartBear评为2022年“最具动力营销团队”

龙智—DevSecOps解决方案

自动化测试 UI测试 UI测试自动测试

AI大模型已经出现不可预测的能力

Baihai IDP

人工智能 深度学习 NLP 大模型 ChatGPT 企业号 4 月 PK 榜

DAMS大会 | 博睿数据分享《一体化智能可观测平台建设之路》

博睿数据

可观测性 智能运维 博睿数据 Bonree ONE

以 100GB SSB 性能测试为例,通过 ByteHouse 云数仓开启你的数据分析之路

字节跳动数据平台

大数据 数据仓库 云原生 数据仓库服务 云数仓

自动化测试理解

测试 自动化测试

户外LED显示屏对恶劣环境的防护措施!

Dylan

LED显示屏 全彩LED显示屏 户外LED显示屏

阿里架构师花近十年时间整理出来的Java核心知识pdf(Java岗)

Java你猿哥

Java java面试 Java工程师 Java面经 春招

PyTorch深度学习实战 | 预测工资——线性回归

TiAmo

深度学习 线性回归 PyTorch 梯度下降法

selenium源码通读·1 | 源码目录

Python 源码 自动化测试 selenium

既然有了MySQL,为什么还要有MongoDB

Java你猿哥

Java MySQL 数据库 mongodb Java工程师

如何选择合适的云数据库架构与规格

NineData

数据库 阿里云 AWS RDS 数据库架构设计

为什么StackOverflow上的代码片段会摧毁你的项目_语言 & 开发_Mahdhi Rezvi_InfoQ精选文章