You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
17 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 32 | 如何评估代码的安全缺陷?
我自己有一点小小的强迫症,遇到事情,喜欢自己动手整个清楚明白。我的大部分失眠,都要拜这点强迫症所赐。时间永远都不够用。如果上天给我一个机会,我是不是可以借上五百年?其实,借上五百年,时间一定还是不够用的。
我经常被问到三个问题:
1. 有什么事情是你必须要做的?
2. 哪些事情是只有你能做的?
3. 哪些事情是别人可以帮你做的?
这就是一种时间管理的思路,隐含的意思是:
1. 识别并且选择最重要的事情;
2. 确定自己最擅长的事情,全力以赴地做好;
3. 选择你的帮手,充分信任并授权。
评估软件的缺陷就是这个思路运用得最广泛的一个场景。作为程序员,我们需要了解软件存在的问题,以及问题的严重程度。那么,我们该如何评估软件存在的问题,以及代码的安全问题呢?
## 关注用户感受
软件缺陷的定义方式和衡量方式有很多种。**从用户感受的角度出发,定义和计量软件缺陷**,是其中一个比较好的、常用的软件缺陷评估体系。我个人比较倾向一种观点,**软件缺陷的严重程度应该和用户的痛苦程度成正比**。
从用户感受出发,衡量软件缺陷有两个最常用的指标:
1. **缺陷影响的深度**,软件缺陷带来的问题的严重性:软件缺陷导致的最严重的问题是什么?
2. **缺陷影响的广度**,软件缺陷带来问题的可能性:软件缺陷导致问题出现的频率是多大?
比如说一个外卖系统只要订餐金额超过32766元就无法提交订单因为软件系统允许的最大金额为32766元。这种事情 一旦发生就是一个非常严重的错误订单无法提交影响的深度。但是在外卖系统里金额超过3万元的订单数量应该不多该错误发生的几率并不大影响的广度
如果我们把每个指标都划分高、低两种程度,就能得到如下四种情况:
1. 高严重性,高可能性;
2. 高严重性,低可能性;
3. 低严重性,高可能性;
4. 低严重性,低可能性。
依据这四种情况,我们就可以定义软件缺陷的优先等级了:
1. 高优先级 P1 高严重性、高可能性;
2. 中优先级 P2 高严重性、低可能性; 低严重性、高可能性;
3. 低优先级 P3 低严重性、低可能性。
![](https://static001.geekbang.org/resource/image/35/b4/355170caae4a69136f6c4974c03359b4.png)
上述外卖系统的软件缺陷的优先级应该是中等优先级P2高严重性、低可能性
## 缺陷,需要从外向内看
假设这个外卖系统有一个bug订餐金额可以是0或者负数。如果订餐金额是负数餐厅不仅需要送餐上门还需要倒贴钱。这可是一个好玩的bug当然不能坐视不管。
过一段时间bug修好了。大部分餐厅都能接受新系统。可是有一个商家表达了不同意见。原来他们有一个“寻找美食家”的活动餐厅不仅不要顾客的钱还倒贴同等餐费请客人品尝最新餐品。负数金额正是他们倒贴钱的“定价”。 美其名曰“你尝,我负”。该商家声称,新系统存在一个严重的缺陷,定价无法使用负数,导致这个活动无法进行。
如果你是这个外卖系统的工程师这个bug你修不修
你是否认可和接受这个缺陷报告背后反映的就是你看待这个软件缺陷的态度。如果从用户感受的角度出发定义和计量软件缺陷这就是一个符合条件的bug。这个问题对该商家的影响非常大无法开展正常的商业活动。但这个问题发生的可能性比较小大概只有这么一个商家使用负数定价。那么这个软件缺陷的优先级是中等优先级P2高严重性、低可能性
你看, 这个外卖系统的代码变更本身并不存在真正的缺陷,但是,如果从用户角度来看,又的确存在一个中等优先级的缺陷。我们当然可以认为,这个缺陷应该在用户那里得到校正。但是有时候,用户并没有校正这种缺陷的机会和能力。
你会不会觉得这个例子有点离奇、离谱,甚至有点搞笑?其实处理这种事情,是我日常工作中非常重要的一部分。 一旦Java的接口规范和规范实现发布我们并不知道在现实世界中用户如何运用他们的聪明才智发挥他们的创造性灵活地使用这些接口和实现。而无论用户怎么使用在软件升级变更中我们都没有充分的理由打断用户的应用运转和商业运营。所以软件的升级或者变更处处充满了乐趣和挑战步步惊心。
**在一个好的软件缺陷评估体系中,不是只有代码错误才会被关注,没有错误的代码,也可能存在需要变更或者改进的“缺陷”**。这就是我们要强调的,从用户的感受出发,定义和计量软件缺陷。缺陷,需要从外向内看。
很多时候,程序员认为是严重的缺陷,用户可能一点儿都感受不到;程序员认为无关紧要的事情,放到了用户的使用场景中,可能就是非常严重的事故。从外向内看缺陷,要求我们站在用户的角度思考问题,看待缺陷。这是一个可以让我们深切关注用户感受的视角。**从用户视角出发的决策,可以让我们的时间使用得更有市场价值。**
## 细化的优先级
在一定程度上,作为软件的原作者或者维护者,我们被各种各样的软件缺陷包围着,永远存在修补不完的缺陷,永远存在无法修复的问题。上述软件缺陷的优先等级的定义,稍显粗糙。我们可能需要更细致一些的等级划分,以便更好地安排我们的时间和区分做事情的轻重缓急。
如果我们把每个指标都划分高、中、低三种程度,就可以得到九种情况,定义五种优先等级。五种等级,是一个常用的优先级数目。太少了,显得粗糙;太多了,容易迷糊。
1. 第一优先级 P1 高严重性、高可能性;
2. 第二优先级 P2 高严重性、中可能性;中严重性、高可能性;
3. 第三优先级 P3 高严重性、低可能性;中严重性、中可能性;低严重性、高可能性;
4. 第四优先级 P4 中严重性、低可能性;低严重性、中可能性;
5. 第五优先级 P5 低严重性、低可能性。
![](https://static001.geekbang.org/resource/image/80/24/80fd5d616f4d315565d9a0156bf33324.png)
你自己试试看,上面我们讨论过的外卖系统的软件缺陷属于第几优先级?
## 优先级的灵活性
**软件缺陷优先等级的定义是为了帮助我们更好地解用户的感受程度,以及安排时间和处理事情。**
由于时间和资源有限,在大多数情况下,特别是对于职业的程序员来说,并不能在一定时间内修复所有的缺陷,满足所有的变更要求。
实际工作中,我们有时候需要调节软件缺陷的优先等级,比如说:
1. 如果已经存在应对办法,优先等级可以下调;
2. 如果软件缺陷引起广泛的公开关注,优先等级应该上调;
3. 如果软件缺陷影响了重要的客户,优先等级应该上调;
4. 如果软件缺陷影响了重要的商业运营,优先等级应该上调。
对于一般的软件缺陷管理五个等级是一个恰当的优先级分割。然而除非特别注明仅从优先级别来看我们并不清楚P3缺陷的严重性是高是低或者发生的可能性是高是低而且问题的严重性在哪儿体现可能性又是如何度量的 这些也都是模糊的地方,可能受主观影响比较大。但是有一些软件缺陷,需要对这些问题有一个更加清晰的认识和感受,比如软件安全漏洞。应该如何评估软件的安全漏洞? 我们会在稍后的接着聊这个话题。
## 管理好自己的时间
好了,我们定义了软件缺陷的优先级,是时候看看如何使用它管理我们的时间了。还记得开头提到的三个问题吗?
1.有什么事情是你必须要做的?
P1的事情需要我们立即全力以赴、必须完成P2的事情需要我们协调资源尽快完成P3的事情需要我们密切关注尽量完成。
2.哪些事情是只有你能做的?
只有你能够修复的bug你可以记到自己名下负责修复这些缺陷。
3.哪些事情是别人可以帮你做的?
适合别人修复的bug如果还没有记到别人名下你可以琢磨下谁是最合适的人选然后和他商量看他有没有时间愿不愿意负责这个缺陷。当然别人也可能会问你愿不愿意修复另外一些缺陷。
相信我,大部分情况下,在得到足够的尊重以及有适当时间的前提下,人们愿意做些有意义的事情。
如果P1、P2、P3的问题修复完了你就可以放心休假去了。休完假充分从疲劳中恢复过来后你就可以考虑是不是可以看看P4和P5的问题了。
## 安全漏洞,需要大范围协作
在软件缺陷中,安全漏洞是一个奇异的存在。软件的安全漏洞,常常会导致非常严重的后果,以及恶劣的影响,甚至会直接导致一个公司的破产。
**由于编写安全代码本身的挑战性,以及消除安全漏洞的复杂性,业界通常需要进行大范围的合作,以便准确、快速、周全地解决安全缺陷问题。**大规模协作需要标准的描述语言,以及对安全问题的准确认知。[通用缺陷评分系统CVSS](https://www.first.org/cvss/)就是一种评判安全缺陷优先等级的标准。
对于安全缺陷,我们还可以使用上面提到过的严重性和可能性两种指标进行衡量。对这两种指标进行细化,才能更符合安全缺陷的特点。
对于安全缺陷的严重性,有四个互相独立的测量维度(量度):
1. 对私密性的影响Confidentiality
2. 对完整性的影响Integrity
3. 对可用性的影响Availability
4. 对授权范围的影响Authorization Scope
> 题外话:
> 私密性、完整性以及可用性,是描述信息安全的最基本的三个元素。
> 私密性指的是数据未经授权,不得访问,解决的是“谁能看”的问题。
> 完整性指的是数据未经授权,不得更改,解决的是“谁能改”的问题。
> 可用性值得是数据经过授权,可以访问,解决的是“可以用”的问题。
对于安全缺陷的可能性,有四个互相独立的测量维度(量度):
1. 安全攻击的路径Attack Vector
2. 安全攻击的复杂度Attack Complexity
3. 安全攻击需要的授权Privileges Required
4. 安全攻击是否需要用户参与User Interaction
由于这些测量维度都是相互独立的,二维的平面图已经不足以表示这么多维度了。通用缺陷评分系统使用了**标识符系统**和**计分系统**,通过标识符来标识测量维度的指标,通过十分制的计分来衡量安全问题的严重程度。由于测量维度的增多以及评分计算的复杂性,我们通常使用工具来记录和查看安全缺陷问题的等级。
比如,本文评审案例的那个缺陷,并不是一个安全问题。 如果我非要使用通用缺陷评分系统来描述它这个计分应该是0.0分,[直观描述](https://www.first.org/cvss/calculator/3.0#CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N)看起来如下图:
![](https://static001.geekbang.org/resource/image/e9/bd/e9476045a739a8b96f67fdb163d60cbd.png)
我们曾经谈到过"[goto fail](https://time.geekbang.org/column/article/77048)"这个安全问题如果使用通用缺陷评分系统计分是7.2[直观描述](https://www.first.org/cvss/calculator/3.0#CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N)如下图所示:
![](https://static001.geekbang.org/resource/image/c6/90/c6a735042e72364a2ad1689c79869690.png)
今天我给你介绍了通用缺陷评分系统的一些最基本的概念,先帮你形成一个基本的印象,算是一块敲门砖。你可以进一步了解[通用缺陷评分系统](https://www.first.org/cvss/)的有关[规范](https://www.first.org/cvss/specification-document)和[工具](https://www.first.org/cvss/calculator/3.0)。
## 安全漏洞和软件缺陷优先级
为了方便管理,安全漏洞和软件缺陷通常使用同一个代码缺陷管理系统。我们要注意两点:第一点是安全漏洞细节不可泄露;第二点是和普通软件缺陷相比,安全漏洞要优先考虑。
### 安全漏洞细节不可泄漏
我们反复强调过,软件的安全漏洞常常会导致非常严重的后果,以及恶劣的影响。最糟糕的是,我们并不能总是预料到谁可以利用这些漏洞,以及由此带来的后果有多严重。所以处理安全漏洞的态度,一定要保守。
安全漏洞不能像普通的代码缺陷那样,可以公开细节、公开讨论。相反,安全漏洞的知情人员一定要控制在一个尽可能小的范围内,知道的人越少越好。如果安全漏洞和普通缺陷共享一个代码缺陷管理系统,一定要想办法做好安全漏洞信息的权限管理。
### 安全漏洞要优先修复
一旦发现一个安全漏洞,不管是来源于外部情报,还是内部发现,我们都要考虑最快地修复,不要等待,更不要拖沓。即使我们全力以赴地修复,在系统修复之前,安全攻击随时都有可能发生。我们能做的,就是尽最大努力,缩短这段时间。
所以大部分的安全漏洞问题都是属于P1级别的缺陷。有一小部分深度防御的安全问题优先级可以是P2。安全问题不要使用P3及以下优先级。另外在所有的同级缺陷中安全问题要优先考虑。
## 小结
今天,我们讨论了如何评估软件存在的问题。软件的缺陷问题,要考虑缺陷影响的深度(严重性)和广度(可能性)。为了更好地认识安全漏洞,我们还要了解安全缺陷的评价标准。
有了软件缺陷的优先级,我们就可以更好地管理我们的工作和时间。下面的三个问题可以帮助你做好安排:
1. 有什么事情是你必须要做的?
2. 哪些事情是只有你能做的?
3. 哪些事情是别人可以帮你做的?
## 一起来动手
我们要想掌握安全编码的技术,熟练修复软件漏洞的实践,需要先过三道关。
第一道关是意识Conscious。也就是说要意识到安全问题的重要性以及意识到有哪些潜在的安全威胁。
第二道关是知晓Awareness。要知道软件有没有安全问题安全问题有多严重。
第三道关是看到Visible。要了解是什么样的问题导致了安全漏洞该怎么修复安全漏洞。
比如我们上一次谈到的Equifax公司的信用记录泄漏的安全问题首席信息官和首席安全官之所以退休我们从外部可以猜测到的原因就是意识不够强烈没有及时更新安全修复。之所以没有及时地更新大概率是不知道有安全问题或者不知道安全问题有多严重。
系统管理员,最少需要过两关(意识和知晓);而软件开发工程师,需要过三关(意识、知晓和看到)。这三关并不容易过。
记得我们前面讨论的“安全漏洞细节不可泄漏”的实践吗?知道安全漏洞的人越少越好。这样保守的安全防范实践,和培养优秀的软件工程师所要求的实践,就成了悖论。
掌握编码安全技术,要培养意识,要知道得更多,要看到问题的细节。而“安全漏洞细节不可泄漏”的实践,却要求尽量不要公开安全细节。但是看不到细节的时候,我们就很难掌握这些技术,很难认识到威胁的严重性,从而阻碍了安全意识的培养。面对这一对几乎不可调和的矛盾,我们该怎么办?!
有数据披露2019和2020两年全球信息安全专业人员的缺口会有300多万。资源不足需求强劲我们怎样才可以学好安全代码的编写技能提升自己的价值
欢迎你在留言区留言、讨论,分享你的经验。我们一起来学习、思考这些老难老难的现实问题!
如果你觉得这篇文章有所帮助,欢迎点击“请朋友读”,把它分享给你的朋友或者同事。