原文: What’s Up With All of These Software Security Vulnerabilities? https://www.simplethread.com/whats-up-with-all-of-these-softw…
当你在读这篇文章的时候,你可能曾经据说了最近产生在 log4j 库的一个破绽。或者也可能是在几年当前,又发现了另一个微小的软件破绽,有人把这篇文章发给你,心愿能帮忙你解释产生了什么。无论哪种形式,你可能都会想到底产生了软件世界中产生了什么,使得这些要害的未发现的破绽可能埋伏多年,而后忽然被发现并导致整个技术界个体失控。我将从一个相当根本的层面来解释到底产生了什么,如果你是一个软件工程师,你可能不会有什么播种。然而如果你并不在 IT 行业,而你又想了解到底产生了什么,那你就来对中央了。
什么是软件?
咱们都大抵晓得什么是软件。咱们晓得它在咱们的计算机上运行。但实际上,它到底是什么?好,在你电脑上运行的所有货色都是软件,当你的计算机启动时,你所登录的操作系统,你启动的应用程序,如 word。你收到五年内没有更新你的反病毒软件的小弹出窗口揭示。它们都是软件。
所有的这些软件都只是由一堆文件组成,你的计算机晓得如何解决。桌面上 word 图标是一个非凡的图片文件,Word 应用程序自身由一堆文件组成,你敌人发送给你的图片也是一个文件。所有都只是你的计算机能够与之交互的不同类型的文件。
你桌面上的 word 图标和你敌人发给你的图片惟一的不同的是,你的计算晓得当你点击 word 图标,须要启动的是 word 应用程序。
在这个层面上,这就是你须要晓得的全副。你计算机上上的所有都由成千上万个文件组成。而你的计算晓得如何与其中大多数文件进行交互。点击一个图像文件,你的计算机会关上一个解决图像的应用程序。点击一个网站链接,你的计算机会关上一个网络浏览器。
文件,一切都是文件。
但这可能有点简单,当你在浏览器上关上一个网站,比方应用 chrome 浏览器、edge 浏览器,拜访网站失去的数据是一个计算机通过互联网发送给你的数据。
其余计算机,被称为服务器,躺在这个星球的某个中央。当你输出”www.google.com“时,谷歌的服务器会向你发送一系列文件,而你的浏览器则利用这些文件来显示一个网页给你。这相当酷。然而,他们依然是一堆文件,只是这次他们通过网络发送给你。
但这些文件由什么组成?
所以你的计算机只是由一堆文件组成,这些文件外面实际上是什么,这有点难以解释,但我会尝试阐明一下。软件被程序语言书写。编程语言只是一堆文本,能够被转化为一组你计算机了解的操作。上面有一个编程语言的小代码块:
import "fmt"
func main() {fmt.Println("hello world")
}
这就是人们常说的代码。这段代码是做什么的并不重要,只有晓得所有的软件都是由一堆文件组成,这些文件有大量的文本,就像你下面看到的。而却要晓得,某个人在某个中央必须编写所有这些文本。
为了让这些文本能够被你的计算机辨认,须要一个被称为“编译器”的非凡程序。编译器将这些文本转化为你的计算机能够运行的一堆指令,并将这些指令塞入一个文件 (或一堆文件)。所以当你启用应用程序像 chrome,你的计算机会找到被编译后的 chrome 文件,关上的,而后运行指令。这就是你的电脑所做的所有,终日都是如此。它只是躺在那里,关上一个又一个文件,读出指令,而后一遍一遍地运行它们。一整天,每天。
我还是没了解安全漏洞是什么意思
我晓得,我晓得,再忍受一下,咱们在靠近答案了。所以咱们的计算机上有一堆非凡的文件,外面是编译器创立的一堆指令。咱们的计算机只需依照这些指令执行操作。这些指令非常简单,他们并不像“显示 chrome 窗口给用户看”这些简单,而是一些简略的指令,像是将两个数相加,或者在屏幕的某个地位画一个点。理论的指令会更原始,但我想你会明确我的意思。指令是十分根本的,而应用程序须要大量的这些指令能力做任何事件。
这些指令必须非常简单,这样你就能够用各种不同的形式组合大量指令,从而能够让你的计算机简直能够做所有事件。
如果这些指令像“在屏幕上画一个按钮”这样简单的话,那么你须要大量十分具体的指令能力实现简直任何你想让它执行的工作。你须要绿色按钮指令去绘制绿色按钮,红色按钮指令去绘制红色按钮。很快就会失去管制。相同,咱们有的只是一堆根本的指令,那咱们就能够将其组合起来去绘制红色按钮或绿色按钮。这些非常简单的指令驱使计算机逐像素的去绘制按钮的每个局部。
因为应用了非常简单的指令,咱们能够有限组合它们让这些指令能够在屏幕上绘制任何货色,包含您当初正在浏览的字母。为了生产所有这些指令,咱们须要大量的代码。您的计算机相当愚蠢,终日只是坐在那里执行指令。因而,咱们编写的代码须要以及其具体的形式告诉您的计算机须要做每一件事件 ……,具体到令人苦楚的水平。
例如,让咱们回顾一下之前提到的网络浏览器示例,您在浏览器中输出了谷歌的地址,为了让你浏览到网页产生了什么?如果我告诉您,您可能不会置信,产生了不可胜数的事件。这包含读取您按下键盘的键位在屏幕上绘制字母,再通过互联网向 Google 发送申请的所有。然而每个动作都是由成千上万个非常简单的指令组成。
真不堪设想,是嘛?不要放心,即便是程序员也难以了解其中的每一个细节。这件事是如此简单,以至于很难齐全了解。这简直是所有软件工程师共享的一个重要机密之一。咱们之中的大多数人对于它的杰出工作,感觉诧异不已。它是令人难以置信的简单,而且没有人真正了解这所有。
是不是开始感觉像纸牌屋了
当初你应该晓得软件工程师的感触了。兴许您会对这个问题有疑难,如果要实现非常简单的工作须要数百万条指令,那么计算机是如何实现世界上不拘一格的所有呢?我很快乐你这么问,因为软件工程师不用编写他们应用程序的所有代码。如果软件工程师不得不编写古代应用程序的每一行代码,那么即便是最简略的应用程序也须要破费数年,即便是一个团队,也不例外。
起因在于每个应用程序都利用了成千上万其余工程师编写的代码。成千上万?是的,举个例子,应用程序应用了大量您操作系统的代码,这就是运行在 Windows 上的应用程序,运行在 Mac OS 的程序也很类似的起因。这些应用程序和操作系统协同工作,在屏幕上绘制,连贯到互联网,弹出告诉。您计算机上的操作系统,代码量是微小的。Windows 10 大概有 5000 万行代码,是的,5000 万行!假如一本小说每页有 20 行文字,那么咱们就须要 250 万页来包容这么多代码,相当于超过 11000 本《哈利. 波特》第一部的页数。堆积起来的高度将和埃菲尔铁塔一样高,或者帝国大厦的三分之二。这些代码也不仅仅是英语文本,而是通过有数人编写和批改的粗疏简单的计算代码。
这一点很难让人置信,不是吗?
而这只是作为 Windows 一部分的软件。咱们的应用程序也须要实现很多类似利用实现的工作。
比方解决图片文件,显示 PDF,显示页面,播放音乐,领取等,简直是你能设想的任何性能。利用共享性能,程序语言应用称为”库“的非凡文件。库是蕴含应用程序须要应用的性能的一捆文件。咱们能够将其设想为应用程序的工具箱,你的利用须要个锤子? 那么本人制作一个锤子是不值当的,咱们这个库外面有这个锤子,那么就用这个锤子吧。
独立开发者能够利用成千上万个库来执行各种工作。软件工程师利用这些库,如果他人曾经为你编写了这些代码,你为什么还要本人再写一遍呢?所以一些利用外面,代码库的代码要比利用本身的还要多。从这个角度来看,假如我有一个绝对比拟小的应用程序,咱们团队编写的代码在大概 50000 行左右。我可能应用了数百万行代码的内部库,而且我还要在由数千万行代码组成的操作系统上运行。古代应用程序利用了大量的内部代码,破绽就可能产生在这些代码中。
终于达到了安全漏洞
在这数百万行代码中,安全漏洞可能埋藏在任何一处。实际上,我所指的安全漏洞,指的是代码中有些缺点,导致代码以一种不应该的形式运行,
举个例子,在这数百万行代码中,假如有一个程序员编写的指令: “ 如果来自用户的文本值是以 hacked: 结尾,那么将前面的内容将被视为链接 ”。所以如果有人拜访你的利用输出: hacked: www.google.com,它将会导致你的利用拜访 www.google.com. 听起来如同没有那么蹩脚,除非代码支还反对获取该地址的内容,而后然尝试去做一些事件。兴许这个程序的用意是加载特定地位的内容,并尝试将其作为应用程序的一部分运行?
而后用户输出 ”hacked:www.myevildomain.com” , 让你的应用程序将他们的恶意代码加载到你的应用程序。如果这个应用程序像 facebook、google、Instagram 的运行模式一样等,那么攻击者可能会利用该破绽运行代码,从而获取用户存储的数据,这时就会呈现安全漏洞的状况。
然而为什么有人这么做呢?
这个例子十分牵强。没有程序员会提供一种形式将他人的代码记录进本人的利用。这是软件根底的利用常识。应用程序常常要从用户那里获取数据,无论是浏览器的表单中的文本,还是用户上传的图片。应用程序从用户那里接管了大量的数据,而后以某种形式对其进行解决。有大量的用户须要清理来确保数据安全。通过接管和解决这些数据,会为特意结构的某个数据片段提供很多机会,使程序以程序员未曾意料的形式运行。
咱们假如一个黑客将文件上传到图片共享服务,这个文件看起来像是一个图片文件,但实际上外面填充的是黑客心愿运行的一些命令。黑客晓得他们正在上传文件操作的网站应用了一些特地的库来解决图片上传,他们晓得库会查看文件结尾的一组特定值,而后依据这些值执行一些非凡的命令,并将图片文件数据传递进来。这种状况常常产生在解决上传到网站的图像上,用于调整大小、叠加成果、增加滤镜等等。如果该库在确保图片数据有效性方面不够审慎,就可能意外执行黑客传递给它的命令,相似的状况在过来产生了很多。
这就是大多数软件安全漏洞的源头,解决来自用户的数据,图片,文件,文本,而后被诱导以不失当的形式来解决。因为大多数利用应用了数百万行代码,因而不可能对其进行全面的审计来所有的缺点。这些缺点之所以不经常出现起因在于大多数利用有相当不错的平安实际,并且大多数库都有很多人审计代码。然而偶然就会有一个奥妙的谬误进入到一个库中,并且因为它很少被应用,这个谬误可能在多年间被疏忽,这就是产生在 log4j 身上的状况。
log4j 呢
log4j 的安全漏洞和我下面形容的网站例子十分相似。log4j 库在应用程序外面被用于向日志文件外面写入信息。日志文件记录了利用做的所有,被用于定位问题。日志文件外面的内容像上面这样
06:42:16.423Z INFO cool_app: start
06:42:16.427Z INFO cool_app: responding to request from 52.38.16.32 path /hello
06:42:16.433Z INFO cool_app: responding to request from 12.22.18.45 path /whatever
06:42:16.438Z INFO cool_app: something weird happened
Log4J 有个个性就是容许在日志文件外面搁置一个非凡的文本片段,log4j 会这个非凡文本做非凡操作,它可能像上面这样:
“${my_value}”
这容许开发者在日志信息外面插入一个非凡的值,用其余值去代替这个非凡的文本片段
“${date:MM-dd-yyyy} - My Log Message”
实际上写入文件内容的如下所示:
09-12-2021 - My Log Message
这是十分实用的性能,容许你在日志音讯中替换值,而无需事后晓得这些值。这些替换能够和另一个被称为 JNDI 的库联合起来应用,JNDI 是另外一个库。
JNDI 容许以多种形式查找值,其中一些形式是容许你通过网络来发送申请获取数据,看起来像上面这样。
“${jndi:ldap://www.mywebsite.com/somepath}”
它将对 ldap://www.mywebsite.com/somepath 进行拜访,甚至运行从这个地址返回的代码。这可能是个有用的性能,然而这些代替该当只在应用程序提供的文本上产生,而不是由用户提供的文本上。在很长一段时间里,Log4j 容许这些替换在可能呈现在日志中的任何用户提供的文本中产生。所以用户只需对可能导致某个值被写入日志的网站执行一个操作,就能够使这个性能运行起来。因为这只是一个大型库的一个小性能 (log4j 有超过 17.5w 行代码,散布在 2000 个文件中),所以很长时间没有被留神到了 (为什么一个将日志写入文件的库有 17.5w 行的代码,可怜的是这是另外一个话题了)
当初你曾经晓得了软件行业的秘辛了
软件难以相信的简单建设在数百万行代码上,没有人有能力可能审计所有的代码。软件工程师依赖于一些风行的库,像 log4j,如果他们想要本人开发就须要破费大量的工夫。软件工程师也喜爱 log4j 这样的库,因为被数百万开发者应用,有这么多的使用量和这么多眼睛盯着一个软件,能够帮忙发现很多平安问题。然而,每隔一段时间就会产生这样的事件,一个被宽泛应用的库,在这个库外面有一个很少被应用的性能,在这个性能里有一个奥妙的缺点,这个缺点可能很多年都没被留神到。
当初的人会不可避免的搜寻 log4j 相似的库,寻找相似的破绽,而后可能会找到一些。有大量的安全漏洞在等着被发现。软件工程师社区创立了一个叫 CVE 的我的项目,CVE 是 Common Vulnerabilities Exposures(通用安全漏洞) 的缩写,用于揭示软件工程师在他们应用的库外面发现的缺点。即便是十分小的安全漏洞也会取得一个 CVE 编号,并通过大多数软件工程师应用的工具报告。如此,软件工程师就可能晓得何时更新他们的库来保障用户的平安。