本节首先介绍信息安全漏洞的概念,软件安全漏洞是信息(系统)安全漏洞的一个重要方面,重点介绍软件漏洞的概念、特点及成因。
信息系统安全漏洞是信息安全风险的主要根源之一,是网络攻防对抗中的重要目标。由于信息系统安全漏洞的危害性、多样性和广泛性,在当前网络空间的各种博弈行为中,漏洞作为一种战略资源而被各方所积极关注。如何有效发现、管理和应用漏洞相关信息,减少由于漏洞带来的对社会生活和国家信息安全的负面影响,即对漏洞及相关信息的掌控,已经成为世界各国在信息安全领域工作的共识和重点。
ISO/IEC 15408-1《信息技术—安全技术—IT安全评估标准》( Information technology—Security techniques—Evaluation criteria for IT security ,2009年第3版,2014年修正版,GB/T 18336.1-2015参照本)中给出的定义是:“Vulnerability:weakness in the TOE(Target Of Evaluation)that can be used to violate the SFRs in some environment”。漏洞是存在于评估对象中的、在一定的环境条件下可能违反安全功能要求的弱点。
美国国家标准与技术研究院NIST在内部报告《信息安全关键技术语词汇表》( Glossary of Key Information Security Terms ,NISTIR 7298,2013年第2版)中给出的定义是:“Vulnerability:weakness in an information system, system security procedures, internal controls, or implementation that could be exploited or triggered by a threat source”。漏洞是存在于信息系统、系统安全过程、内部控制或实现过程中的、可被威胁源攻击或触发的弱点。
ISO/IEC 27000《信息技术—安全技术—信息安全管理系统—概述和词汇》( Information technology—Security techniques—Information security management systems—Overview and vocabulary,2016年第4版)中给出的定义是:“Vulnerability:weakness of an asset or control that can be exploited by one or more threats”。漏洞是能够被一个或多个威胁利用的资产或控制中的弱点。
以上这些关于信息安全漏洞的定义或者解释的角度虽各不相同,但对漏洞的认识却有以下三个共同特点。
●漏洞是信息系统自身具有的弱点或者缺陷。
●漏洞存在环境通常是特定的。
●漏洞具有可利用性,若攻击者利用了这些漏洞,将会给信息系统安全带来严重威胁和经济损失。
软件(安全)漏洞是信息系统安全漏洞的一个重要方面。分析、理解软件漏洞对于了解当下的安全威胁非常关键。
什么是软件漏洞(Software Vulnerability)?与软件“漏洞”相关的术语很多,包括错误(Error/Mistake)、缺陷(Defect/Flaw/Bug)及失效(Failure)等,那么软件错误、软件缺陷与软件漏洞的关系是什么呢?
根据ISO/IEC/IEEE 24765:2010《系统和软件工程—词汇表》( Systems and software engineering—Vocabulary ),软件中的错误、缺陷、故障和失效可以用图2-1来区别它们在软件生命周期各个阶段的表现。
图2-1 软件中的错误、缺陷、故障和失效在软件生命周期各个阶段的表现
软件错误(Error)是指在软件开发过程中出现的不符合期望或不可接受的人为差错,其结果将可能导致软件缺陷的产生。在软件开发过程中,人是主体,难免会犯错误。软件错误主要是一种人为错误,相对于软件本身而言,是一种外部行为。
软件缺陷(Bug/Defect)是指由于人为差错或其他客观原因,导致软件隐含能导致其在运行过程中出现不希望或不可接受的偏差,例如软件需求定义,以及设计、实现等错误。在这种意义下,软件缺陷和软件错误有着相近的含义。当软件运行于某一特定的环境条件时出现故障,这时称软件缺陷被激活。软件缺陷存在于软件内部,是一种静态形式。
软件故障(Fault)是指软件出现可感知的不正常、不正确或不按规范执行的状态。例如,软件运行中因为程序本身有错误而造成的功能不正常、死机、数据丢失或非正常中断等现象。
软件失效(Failure)是指软件丧失完成规定功能的能力的事件。软件失效通常包含三方面的含义:软件或其构成单元不能在规定的时间内和条件下完成所规定的功能,软件故障被触发及丧失对用户的预期服务时都可能导致失效;一个功能单元执行所要求功能的能力终结;软件的操作偏离了软件需求。
为了简化理解,本书此处仅讨论软件错误(Error)和软件缺陷(Bug/Defect)。
软件错误是软件开发生命周期各阶段中错误的真实体现。软件安全错误是软件错误的一个子集,软件安全错误可能包含以下几种情况。
●需求说明错误。由于软件开发生命周期需求分析过程的错误而产生的需求不正确或需求的缺失,如用户提出的需求不完整,用户需求的变更未及时消化,以及软件开发者和用户对需求的理解不同等。
●设计错误。由于设计阶段引入不正确的逻辑决策、决策本身错误或者由于决策表达错误而导致的系统设计上的错误,如缺少用户输入验证,这会导致数据格式错误或缓冲区溢出漏洞。
●编码错误。如语法错误、变量初始化错误等。
●测试错误。如数据准备错误、测试用例错误等。
●配置错误。由于软件在应用环境中配置不当而产生的错误,如防火墙采用默认口令。
●文档错误。如文档不齐全,文档相关内容不一致,文档版本不一致,以及缺乏完整性等。
软件缺陷也称软件Bug,是指计算机软件或程序中存在的某种破坏正常运行能力的问题、错误,或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。
需要说明的是,安全缺陷或者说Bug是一个需要考虑具体环境、具体对象的概念。举例来说,一般的Web应用程序没有使用HTTPS协议(超文本传输安全协议)来加密传输的状态并不能算作是Bug,而对于网上银行或电子商务等应用,不采用HTTPS协议进行加密传输就应当算作一个Bug。如同使用HTTPS来对传输内容进行加密那样,积极主动地加强安全性的措施,也就是增加安全性功能,可以尽可能地消除Bug。安全性功能实际为软件系统的一种需求,所以也被称为安全性需求。是否将安全性功能加入到项目需求中,还需要根据项目的具体情况考虑,如项目经费等。
还需要注意的是,Bug的发现和消除是有一个过程的,一定时期即使修正了所有Bug,也不能保证软件系统的绝对安全,因为很可能还有未知Bug尚未发现。
知识拓展:软件Bug
1947年9月9日,格蕾丝·霍珀(Grace Hopper)博士正在哈佛大学对Mark II计算机进行测试。然而过程并不顺利,霍珀博士始终没能得到预期的结果。最后她终于发现了原因所在。原来一只飞蛾飞进了计算机里。霍珀博士于是将这只飞蛾夹出后粘到了自己的笔记本上(如图2-2所示),并写到:“最早发现的Bug实体”(First actual case of bug being found)。
这个发现奠定了Bug这个词在计算机世界的地位,变成无数程序员的噩梦。从那以后,Bug这个词在计算机世界表示计算机程序中的缺陷或者疏漏,它们会使程序计算出莫名其妙的结果,甚至引起程序的崩溃。
这是流传最广的关于计算机Bug的故事,可是历史的真相是,Bug这个词早在发明家托马斯·爱迪生的年代就被广泛用于表示机器的故障,这在爱迪生本人1870年左右的笔记里面也能看得到。而电气电子工程师学会IEEE也将Bug这一词的引入归功于爱迪生。
图2-2 软件史上的第一虫
漏洞(Vulnerability)又称脆弱点,这一概念早在1947年冯·诺依曼建立计算机系统结构理论时就有涉及,他认为计算机的发展和自然生命有相似性,一个计算机系统也有天生的类似基因的缺陷,也可能在使用和发展过程中产生意想不到的问题。20世纪80年代,由于早期黑客的出现和第一个计算机病毒的产生,软件漏洞逐渐引起人们的关注。在历经30多年的研究过程中,学术界及产业界对漏洞给出了很多定义,漏洞的定义本身也随着信息技术的发展而具有不同的含义与范畴。
软件漏洞通常被认为是软件生命周期中与安全相关的设计错误、编码缺陷及运行故障等。本书并不对软件漏洞/脆弱点、软件缺陷及软件错误等概念严格区分。
软件漏洞一方面会导致有害的输出或行为,例如,导致软件运行异常;另一方面漏洞也会被攻击者所利用来攻击系统,例如,攻击者通过精心设计攻击程序,准确地触发软件漏洞,并利用该漏洞在目标系统中插入并执行精心设计的代码,从而获得对目标系统的控制权,进而实施其他攻击行为。
本书中关于漏洞的定义为:软件系统或产品在设计、实现、配置和运行等过程中,由操作实体有意或无意产生的缺陷、瑕疵或错误,它们以不同形式存在于信息系统的各个层次和环节之中,且随着信息系统的变化而改变。漏洞一旦被恶意主体所利用,就会造成对信息系统的安全损害,从而影响构建于信息系统之上正常服务的运行,危害信息系统及信息的安全属性。
本定义也体现了漏洞是贯穿软件生命周期各环节的。在时间维度上,漏洞都会经历产生、发现、公开和消亡等过程,在此期间,漏洞会有不同的名称或表示形式,如图2-3所示。从漏洞是否可利用且相应的补丁是否已发布的角度,可以将漏洞分为以下三类。
图2-3 漏洞生命周期时间轴
●0day漏洞是指已经被发现(有可能未被公开)但官方还没有相关补丁的漏洞。
●1day漏洞是指厂商发布安全补丁之后但大部分用户还未打补丁时的漏洞,此类漏洞依然具有可利用性。
●历史漏洞是指距离补丁发布日期已久且可利用性不高的漏洞。由于各方定义不一样,故用虚线表示。
从漏洞是否公开的角度来讲,已知漏洞是已经由各大漏洞库、相关组织或个人所发现的漏洞;未公开/未知漏洞是在上述公开渠道上没有发布、只被少数人所知的漏洞。
漏洞作为信息安全的核心元素,它可能存在于信息系统的各个方面,其对应的特点也各不相同。下面分别从时间、空间和可利用性三个维度来分析漏洞的特点。
(1)持久性与时效性
一个软件系统从发布之日起,随着用户广泛且深入地使用,软件系统中存在的漏洞会不断暴露出来,这些被发现的漏洞也会不断地被软件开发商发布的补丁软件修补,或在以后发布的新版软件中得以纠正。而在新版软件纠正旧版本中的漏洞的同时,也会引入一些新的漏洞和问题。软件开发商和软件使用者的疏忽或错误(如对软件系统不安全的配置或者没有及时更新安全补丁等),也会导致软件漏洞长期存在。随着时间的推移,旧的漏洞会不断消失,新的漏洞会不断出现,因此漏洞具有持久性。相关数据表明高危漏洞及其变种会可预见地重复出现,对内部和外部网络构成持续的威胁。
漏洞具有时效性,超过一定的时间限制(例如,当针对该漏洞的修补措施出现时,或者软件开发商推出了更新版本系统时),漏洞的威胁就会逐渐减少直至消失。漏洞的时效性具有双刃剑的作用,一方面,漏洞信息的公开加速了软件开发商的安全补丁的更新进程,能够尽快警示软件用户,减少了恶意程序的危害程度;另一方面,攻击者也可能会尽快利用漏洞信息实施攻击行为。
(2)广泛性与具体性
漏洞具有广泛性,会影响到很大范围的软件和硬件设备,包括操作系统本身及系统服务软件、网络客户和服务器软件、网络路由器和防火墙等。理论上讲,所有信息系统或设备中都会存在设计、实现或者配置上的漏洞。
漏洞又具有具体性,即它总是存在于具体的环境或条件中。对组成信息系统的软硬件设备而言,在这些不同的软硬件设备中都可能存在不同的安全漏洞,甚至在不同种类的软硬件设备中,同种设备的不同版本之间,由不同设备构成的信息系统之间,以及同种软件系统在不同的配置条件下,都会存在各自不同的安全漏洞。
(3)可利用性与隐蔽性
漏洞具有可利用性,漏洞一旦被攻击者利用就会给信息系统带来威胁和损失。当然,软件厂商也可以通过各种技术手段来降低漏洞的可利用性,例如微软公司通过在Windows操作系统或应用软件中增加内存保护机制(如DEP、ASLR和SafeSEH等),极大地降低了缓冲区溢出等漏洞的可利用性,本书将在第3章介绍这些保护机制。
漏洞具有隐蔽性,往往需要通过特殊的漏洞分析手段才能发现。尽管随着程序分析技术的进步,已有工具可以对程序源代码进行静态分析和检查,以发现其中的代码缺陷(如strcpy等危险函数的使用),但是对于不具备明确特征的漏洞而言,需要组合使用静态分析和动态分析工具、人工分析等方法去发现。本书的后面部分会着重讲述这些漏洞分析技术。
软件作为一种产品,其生产和使用过程依托于现有的计算机系统和网络系统,并且以开发人员的经验和行为作为其核心内涵,因此,软件漏洞是难以避免的,主要体现在以下几个方面。
现今的计算机基于冯·诺依曼体系结构,其基本特征决定了漏洞产生的必然。表2-1说明了漏洞产生的原因。
表2-1 冯·诺依曼体系容易导致漏洞产生的原因
在内存中,代码、数据和指令等任何信息都是以0、1串的形式表示的。例如,0x1C是跳转指令的操作码,并且跳转指令的格式是1C displ,其表示跳转到该指令的前displ字节的地址处开始执行,则串0x1C0A将被解释成向前跳转10字节。如图2-4所示,如果在一串指令中存储数值7178(十六进制为1C0A),将与控制程序跳转的功能是相同的。
虽然计算机指令能够决定这些串如何解释,但是攻击者常常在内存溢出类攻击中,将数据溢出到可执行代码中,然后选择能够被当作有效指令的数据值来达到攻击的目的。本书将在第3章中介绍内存溢出类攻击。
图2-4 内存中数据和指令的存储
现代软件功能越来越强,功能组件越来越多,软件也变得越来越复杂。现在基于网络的应用系统更多地采用了分布式、集群和可扩展架构,软件内部结构错综复杂。软件应用向可扩展化方向发展,成熟的软件也可以接受开发者或第三方扩展,系统功能得到扩充。例如,Firefox和Chrome浏览器支持第三方插件;Windows操作系统支持动态加载第三方驱动程序;Word和Excel等软件支持第三方脚本和组件运行等。这些可扩展性在增加软件功能的同时,也加重了软件的安全问题。研究显示,软件漏洞的增长与软件复杂性、代码行数的增长呈正比,即“代码行越多,缺陷也就越多”。
作为互联网基础的TCP/IP协议栈,以及众多的协议及实现(如OpenSSL),在设计之初主要强调互联互通和开放性,没有充分考虑安全性,且协议栈的实现通常由程序员人工完成,导致漏洞的引入成为必然。当今软件和网络系统的高度复杂性,也决定了不可能通过技术手段发现所有的漏洞。
伴随信息技术的发展出现了很多新技术和新应用,如移动互联网、物联网、云计算、大数据和社交网络等。随着移动互联网、物联网的出现,网络终端的数量呈几何倍数增长,云计算和大数据的发展极大提高了攻击者的计算能力,社交网络为攻击者提供了新的信息获取途径。总之,这些新技术、新应用不仅扩展了互联网影响范围,提高了互联网的复杂度,也增大了漏洞产生的概率,必然会导致越来越多的漏洞的产生。
安全协议实现,以及云计算、移动智能终端中出现的新型软件漏洞分析,请扫描封底的二维码获取内容查看 。
网络技术拓展了软件的功能范围,提高了其使用方便程度,与此同时,也给软件带来了更大风险。由于软件被应用于各种环境,面对不同层次的使用者,软件开发者需要考虑更多的安全问题。同时,黑客和恶意攻击者可以比以往获得更多的时间和机会来访问软件系统,并尝试发现软件中存在的安全漏洞。
当前黑客组织非常活跃,其中既包括传统的青少年黑客、跨国黑客组织,也包括商业间谍黑客和恐怖主义黑客,乃至国家网络战部队。以前的黑客多以恶作剧和破坏系统为主,包括对技术好奇的青少年黑客和一些跨国黑客组织;现今的黑客则多为实施商业犯罪并从事地下黑产,危害已经不限于让服务与系统不可用,更多的是带来敏感信息的泄露和现实资产的损失。尤其是近些年,一系列APT攻击的出现及美国“棱镜”计划曝光,来自国家层面的网络威胁逐渐浮出水面。
传统软件开发更倾向于软件功能,而不注重对安全风险的管理。软件开发公司工期紧、任务重,为争夺客户资源、抢夺市场份额,经常仓促发布软件。软件开发人员将软件功能视为头等大事,对软件安全架构、安全防护措施认识不够,只关注是否实现需要的功能,很少从“攻击者”的角度来思考软件安全问题。
如果采用严格的软件开发质量管理机制和多重测试技术,软件公司开发的产品的缺陷率会低很多。在软件安全性分析中可以使用缺陷密度(即每千行代码中存在的软件缺陷数量)来衡量软件的安全性。以下各类软件代码缺陷的统计数据也说明了这个情况。
●普通软件开发公司开发的软件的缺陷密度为4~40个缺陷/KLOC(千行代码)。
●高水平的软件公司开发的软件的缺陷密度为2~4个缺陷/KLOC(千行代码)。
●美国NASA的软件缺陷密度为0.1个缺陷/KLOC(千行代码)。
国内大量软件开发厂商对软件开发过程的管理不够重视,大量软件使用开源代码和公用模块,缺陷率普遍偏高,可被利用的己知和未知缺陷较多。
软件公司中,项目管理和软件开发人员缺乏软件安全开发知识,不知道如何更好地开发安全的软件。实施软件的安全开发过程,需要开发团队所有的成员及项目管理者都具备较高的安全知识。软件开发人员很少进行安全能力与意识的培训,项目开发管理者不了解软件安全开发的管理流程和方法,不清楚安全开发过程中使用的各类方法和思想;开发人员大多数仅学会了编程技巧,不了解安全漏洞的成因、技术原理与安全危害,不能更好地将软件安全需求、安全特性和编程方法相互结合。
软件开发生命周期的各个环节都是人为参与的,经验的缺乏和意识的疏忽都有可能引入安全漏洞。为此,本书用以培养软件开发人员的安全开发意识,增强对软件安全威胁的认识,提高安全开发水平,提升IT产品和软件系统的抗攻击能力。本书将在后续章节中展开介绍。