基本信息
- 原书名:Secure Coding in C and C++, Second Edition
- 原出版社: Addison-Wesley Professional

【插图】

编辑推荐
C/C++安全编程领域的“标准”著作,资深安全专家撰写,美国CERT主管亲自作序推荐,权威性毋庸置疑
详细阐述C/C++语言及其相关库固有的安全问题和陷阱,系统总结导致软件漏洞的常见编码错误,并给出了应对的解决方案
对C/C++软件中常见漏洞的危害、被利用方式、检测方法和应对之道进行了全方位讲解,包含大量编码练习,实践性强
内容简介
计算机书籍
《C和C++安全编码(原书第2版)》是C/C++安全编码领域的权威著作,被视为“标准”参考书,由国际资深软件安全专家撰写,美国CERT主管亲自作序推荐。本书结合国际标准C11和C++11,以及C和C++语言的最新发展,既详细阐述了C/C++语言及其相关库固有的安全问题和陷阱,系统总结了导致软件漏洞的各种常见编码错误,并给出了应对错误的解决方案;又对C/C++软件中常见漏洞的危害、被利用方式、检测方法和应对之道进行了全方位讲解,包含大量编码练习,实践性强。
本文从C和C++语言的各个部分分别介绍了可能导致安全问题的软件漏洞:第1章介绍安全术语和概念,并指出为何C和C++程序中存在如此多的漏洞。第2章描述C和C++中的字符串操作、常见的安全缺陷以及由此导致的漏洞。第3章介绍任意内存写漏洞利用方式,它允许攻击者对内存中任意位置的一个地址进行写操作。第4章描述动态内存管理,讨论了动态分配的缓冲区溢出、写入已释放内存,以及重复释放漏洞。第5章讨论整数安全问题(即与整数操作相关的安全议题),包括整数溢出、符号错误以及截断错误等。第6章描述格式化输出函数的正确和错误的用法,对因这些函数的错误使用所导致的格式字符串和缓冲区溢出漏洞都有讨论。第7章重点介绍并发和可能导致死锁、竞争条件和无效的内存访问序列的漏洞。第8章描述和文件I/O相关的常见漏洞,包括竞争条件和检查时间与使用时间漏洞。第9章推荐一些可以整体改善C/C++应用程序安全性的具体开发实践,这些建议是对每一章中用于解决特定漏洞问题的推荐做法的补充。
作译者
目录
译者序
序
前言
致谢
第1章 夹缝求生 1
1.1 衡量危险 4
1.1.1 损失的现状 4
1.1.2 威胁的来源 6
1.1.3 软件安全 7
1.2 安全概念 8
1.2.1 安全策略 9
1.2.2 安全缺陷 10
1.2.3 漏洞 10
1.2.4 漏洞利用 11
1.2.5 缓解措施 12
1.3 C和C++ 12
1.3.1 C和C++简史 13
1.3.2 C存在的问题 14
1.3.3 遗留代码 17
译者序
我曾经编写过C和C++代码,对这两门编程语言都深有感触。C和C++语言是实现许多操作系统和服务器软件的开发语言,支撑着许多为数以万计的用户提供服务的重要应用程序,必须坚实可靠才能持续不断地正常运行。特别是移动互联网的发展,大大增加了应用程序的种类和数量,不安全的应用程序也会造成安全漏洞迅速地大面积传播。因为C和C++语言产生的年代较早并且设计为与底层设备打交道,所以对效率要求很高,这使得这两种语言存在固有的安全问题,虽然语言标准的制定者意识到了这个问题,并提出了许多更加安全的解决方案,但大量的遗留代码中仍然包含不安全的实现和库函数调用,这些都会不时引发安全问题。许多安全检测工具可以帮助人们检查出代码的漏洞,但却不能帮助他们把它们修改正确,而且对C语言中某些功能理解上的偏差往往会导致误用。总而言之,编写安全代码完全是开发人员的责任,而开发人员若要具备这方面的技能,就得掌握相关的理论并在实践中自觉加以运用。
本书涵盖安全编码各个方面,人们普遍能意识到指针是C和C++中最灵活的功能,也是程序员最容易犯错的地方,为强调其重要性有人曾说过“不会用指针的C程序员不是真正的C程序员”,这是因为指针直接对内存地址进行读、写访问,它的重要性不言而喻。但与此同时,这两门语言的另一些要点却常常被忽视。然而编写安全代码的从业人员,则需要全面地了解字符串、整数、内存管理、格式化输入与输出、文件操作中的安全陷阱,并学会规避之法。此外,现代应用程序绝大多数具备并发访问能力,因此本书新增了这些方面的内容,使之更符合实际需要。本书每个主题都配有实例,读者能从中了解产生安全漏洞的缘由和正确的做法。本书还总结了安全编码的实施指南,指出软件开发组织应用这些规程可以提高安全软件的开发效率并更能保证产品符合安全要求。本书引用了许多相关著作,以便于读者进一步了解某个主题的细节。总之,本书值得每个从业人员在开始实际编程活动前阅读。
此外,本书作者Robert C. Seacord是业界著名的安全专家,著有多本安全编程著作。他所领导的CERT项目定期发布安全报告,并与软件厂商合作解决安全问题,在安全领域硕果累累。本书很多内容引用自实际的安全问题,并结合了国际标准C11和C++11展开叙述,实用且跟踪了C和C++语言的最新发展。因此,我郑重向您推荐此书,希望它能在检测及修复安全漏洞上对您有所帮助!
感谢机械工业出版社谢晓芳编辑邀请我翻译本书并对译文细致地审查和润色。感谢本书第1版译者荣耀和罗翼先生做出的贡献,他们的辛勤工作保障了本书的顺利完成。
感谢我的妻子李颖一如既往的支持和儿子卢〇一的鼓励,他们是我工作的动力。
希望这本书能对读者有所帮助。由于译者经验和水平有限,译文中难免有不妥之处,恳请读者批评指正!
卢涛
前言
CERT最初的工作重点是对各种网络事件做出快速响应和分析。这里所说的事件既包括得逞的攻击(如系统受损与拒绝服务等),也包括未得逞的攻击企图、探测和扫描。自1988年以来,CERT共已接到逾22 665个报告计算机安全事件或咨询有关信息的热线电话,已处理逾319 992起计算机安全事件,而且每年报告的事件数目呈持续增长的态势。
虽然对事件做出及时响应必不可少,但是这还不足以保护互联网和互联的信息系统的安全。分析表明,大部分计算机安全事件是由特洛伊木马、社会工程学(social engineering)以及软件漏洞利用(exploitation)造成的,包括软件缺陷、设计决策、配置决策以及非预期的系统间交互等。CERT监控漏洞信息的公共来源并且经常性地收到漏洞报告。自1995年以来,CERT已经收到超过16 726份漏洞报告。每收到一份报告,CERT就会分析报告所述的可能的漏洞,并与软件制造者协作,通知其产品中存在安全缺陷,促进并追踪其对问题的响应。
和事件报告相似,漏洞报告也以惊人的速度持续增长。虽然对漏洞的管理抑制了这一进程的发展,但是对于解决互联网和信息系统的安全问题来说,这同样远远不够。为了解决日益增加的漏洞和事件问题,必须采取相应的措施:在源头有效地控制它们,即必须在软件的开发阶段和随后的维护工作中避免引入软件漏洞。对现有漏洞的分析表明,大部分漏洞都是由少数根本原因导致。本书旨在传授开发者有关这些根本原因的知识,并介绍避免引入漏洞的措施。
本书读者对象
对任何采用C和C++开发或维护软件的人来说,本书都是非常有价值的。
如果你是一位C/C++程序员,本书将教你如何识别会导致软件漏洞的常见编程错误,理解这些错误是如何被利用的,并以安全的方式实现解决方案。
如果你是一位软件项目经理,本书将教你识别软件漏洞的风险及导致的后果,对投资开发安全软件给出指导。
如果你是一位计算机专业的学生,本书将教你有用的编程实践,帮助你避免不良的开发习惯,使你能够在职业生涯中开发出安全的程序。
如果你是一位安全分析师,本书对常见的漏洞提供了细致的描述,并提供了检测漏洞的方法和实用的规避措施。
本书组织和内容
本书提供了C和C++编程中关于安全实践方面的实用指导。安全的程序需要安全的设计,然而,如果开发者不了解C和C++编程中许多固有的安全陷阱,那么即便是最佳设计也可能最终导致不安全的程序。本书对C和C++中常见的编程错误提供了详细的解释,并描述了这些错误是如何导致有漏洞的代码的。本书重点讨论C和C++编程语言以及相关库固有的安全问题,而不强调和外部系统(如数据库和Web服务器等)的交互中牵涉的安全问题。这些方面话题丰富,应单独讨论。希望本书对于涉及开发安全的C和C++程序的任何人都有所裨益,而不管具体开发何种应用。
本书围绕着软件工程师经常实现的、可能会导致安全问题的功能(例如,格式化输出和算术运算等)组织内容。每一章都描述了一些会导致漏洞的不安全编程实践和常见的错误、这些编程缺陷如何被利用、这种恶意利用所导致的后果,以及替代的安全做法等。对于软件漏洞的根源问题,例如,缓冲区溢出、整型范围错误和无效的格式字符串等,都有详细的解释。每一章都包含检测既有代码中漏洞的技术,以及如何安全地实现所需功能的措施。
本书包含以下各章。
第1章:概述问题,介绍安全术语和概念,并对为何C和C++程序中存在如此多的漏洞发表看法。
第2章:描述C和C++中的字符串操作、常见的安全缺陷以及由此导致的漏洞(包括缓冲区溢出攻击和栈溢出攻击),还介绍了代码注入(code injection)和弧注入(arc injection)两种漏洞利用方式。
第3章:介绍任意内存写(arbitrary memory write)漏洞利用方式,它允许攻击者对内存中任意位置的一个地址进行写操作。该章描述这些漏洞利用方式如何用于在受害机器上执行任意的代码。由“任意内存写”导致的漏洞在稍后的章节中讨论。
第4章:描述动态内存管理,讨论动态分配的缓冲区溢出、写入已释放内存,以及重复释放(double-free)漏洞。
第5章:讨论整数安全问题(即与整数操作相关的安全主题),包括整数溢出、符号错误以及截断错误等。
第6章:描述格式化输出函数的正确和错误的用法。对因这些函数的错误使用所导致的格式字符串和缓冲区溢出漏洞都有讨论。
序言
尽管今天互联网上的攻击行为大多不过是恶作剧,但是越来越多的证据表明,罪犯、恐怖分子以及其他心怀叵测的人已将软件系统中的漏洞视作达成其不可告人目的的手段。近年来,每年发现的软件漏洞已逾4000个。这些漏洞的成因包括:在设计和实现方面对如何保护系统考虑不周,在开发实践方面对消除会导致安全缺陷的实现瑕疵关注不够。
伴随着软件漏洞的日益增加,攻击手段也与时俱进,变得越发老练、有效。入侵者在发现软件产品中的漏洞后,可以迅速开发出利用漏洞的脚本,继而使用这些脚本威胁计算机的安全。更糟糕的是,他们还将这些脚本与其他攻击者共享。这些脚本与一些“自动扫描网络以窥探脆弱系统”的程序联合起来,攻击那些脆弱系统,危害其安全,甚至利用它们进一步传播攻击。
由于每年都会发现大量的漏洞,系统管理员为了给既有系统打补丁日益疲于奔命。打补丁有时并非易事,并可能会导致意想不到的副作用。在供应商发布一个安全补丁后,可能需耗时数月乃至数年的时间,90%~95%的受影响计算机才能完成修补工作。
互联网用户已经严重依赖于这样一种解决方式:互联网社区作为一个整体,对发生的安全攻击快速做出反应,以确保将损害降至最低,并将攻击迅速击溃。然而,显而易见,如今的“反应式解决方案”已经达到其效力的极限。虽然个体响应组织都在为将漏洞处理过程的精简化和自动化而努力工作,但是今天商业软件产品中的漏洞数目,已经多至只有财力雄厚的组织才能应对漏洞修复工作,其他组织实质上已心有余而力不足。
没有任何证据表明大多数产品中的安全问题得到了改善,很多软件开发者尚未很好地理解从各种漏洞成因中获得的教训,或者尚未运用能够起作用的缓解策略,CERT/CC不断在同一软件产品的更新版本中发现早期版本已存在的同类漏洞就是明证。
这些因素交织在一起,预示着我们完全可以相信,很多攻击甚至会在我们实际希望的最短响应时间内造成巨大的经济损失和服务崩溃。
虽然积极且协调的反应仍然不可或缺,但我们还必须构建出不易被破坏的、更安全的系统。
关于本书
本书致力于解决C和C++中已经导致危险的、破坏性的常见软件漏洞的基本编程错误,这些漏洞自CERT 1988年创立以来就记录在案。针对导致这些漏洞的编程错误,本书既出色地给出了深度工程分析,又提出了缓解策略,可以富有成效地降低或消除漏洞被恶意利用的风险。
自Robert于1987年4月加入SEI以来,我就一直与他共事。Robert是一位知识渊博、技术熟练的软件工程师,他在软件漏洞细节分析和表达洞察成果方面卓尔不凡。作为研究结果,本书细致而精确地分析了软件开发者面临的常见问题,并提供了实用的解决方案。Robert在软件开发方面具备的宽广背景,也使得他擅长在性能、易用性以及其他在开发安全代码过程中必须考虑的质量特性之间进行权衡。除了Robert外,本书还凝聚了CERT积累和提炼的知识,以及CERT/CC漏洞分析小组、CERT操作人员、SEI编辑和工作人员的杰出工作。
Richard D. Pethia
CERT主管
书摘
夹缝求生
To live without evil belongs
only to the gods.
—Sophocles, Fragments, l.683
计算机系统并不易受攻击,易受攻击的是我们人类,只不过遭受的攻击通过计算机系统完成罢了。
2003年8月11日爆发的W32.Blaster.Worm蠕虫病毒很好地例证了软件中的安全缺陷是如何让我们变得易受攻击的。Blaster可以在毫无用户参与的情况下感染任何一台连接到互联网且未打补丁的计算机系统。微软提供的数据显示,至少有800万个Windows系统被该蠕虫感染[Lemos 2004]。Blaster的主要破坏力在于使用户无法正常使用自己的机器,并且能够渗透整个局域网,感染的用户必须设法删除该蠕虫并且升级系统才能正常工作。
Blaster蠕虫作恶前后的一系列事件,如图1.1所示,揭示了软件厂商、安全研究人员、发布漏洞利用代码者以及恶意攻击者之间错综复杂的关系。
图1.1 蠕虫时间表
首先,LSD研究小组发现了RPC(可通过TCP/IP交换信息)中存在一个缓冲区溢出漏洞,成因在于对“畸形”消息的错误处理。该漏洞影响监听RPC端口的一个分布式组件对象模型(DCOM)接口,后者处理由客户机发送给服务器的对象激活请求。对该漏洞的成功利用允许攻击者在受感染的系统上以本地权限执行任意的代码。
在这种情况下,LSD小组遵循了负责任的披露原则,在公开该漏洞前与软件厂商进行了合作,以寻求解决问题的办法。2003年7月16日,微软发布了微软安全公告MS03-026,LSD发布了一个特别报告,而CERT协调中心(CERT/CC)则发布了一个漏洞说明VU#568148,详细描述了该漏洞,并提供相应的补丁和应急方案的信息。第二天,CERT/CC还发布了名为“Buffer Overflow in Microsoft RPC”(微软RPC缓冲区溢出)的CERT公告CA-2003-16。
9天后,也就是7月25日,一个名为Xfocus的安全研究小组以安全公告板和补丁的形式发布了该漏洞的利用代码。Xfocus自称是“一个在1998年创立于中国的非营利和自由技术组织,致力于研究和展示网络服务与通信安全方面的弱点”。实质上,Xfocus对微软提供的补丁程序进行了逆向工程,研究了该漏洞的原理,并且开发了相应的攻击该漏洞的方法,并将其公之于众[Charney 2003]。
H.D. Moore(Metasploit项目的创始人)改进了Xfocus的代码,使其可以对更多版本的操作系统生效。很快就有漏洞利用工具发布了,这使得黑客可以通过IRC网络发送命令。8月2日就已经发现了这些攻击的蛛丝马迹[de Kere 2003]。
由于DEF CON黑客大会将于8月2日~3日召开,因此大家普遍预计将会有针对该漏洞的蠕虫发布(并不是说参加DEF CON的人会这么做,而是由于该大会会引起人们对黑客技术的关注)。DHS(Department of Homeland Security,美国国土安全部)于8月1号发布了一个预警,FedCIRC(Federal Computer Incident Response Center,联邦计算机事故响应中心)、NCS(National Communications System,美国国家通信系统)以及NIPC(National Infrastructure Protection Center,美国国家基础设施保护中心)也在对漏洞利用行为积极进行监测。8月11日,也就是补丁程序发布后的第26天,发现Blaster蠕虫首次在互联网上传播。24小时后,Blaster感染了336 000台计算机[Pethia 2003a]。截至8月14日,Blaster已经感染了超过100万台计算机,在高峰期,它每小时感染100 000个系统[de Kere 2003]。
Blaster是一个通过TCP/IP进行传播的贪婪的蠕虫,它利用了Windows的DCOM RPC接口中的一个漏洞。当Blaster执行时,它首先检测计算机是否已感染以及蠕虫是否正在运行,如果是这样,它就不会重复感染该计算机,否则,Blaster将:
加入注册表的
键中,这样,每当启动Windows,该蠕虫程序都会运行。接下来,Blaster产生一个随机的IP地址,并试图感染具有该地址的计算机。该蠕虫利用Windows 2000或Windows XP上的DCOM RPC漏洞通过TCP 135端口发送数据。Blaster监听UDP端口69,以接收可以通过DCOM RPC漏洞利用连接的机器的请求。一旦接收到请求,随即将msblast.exe文件发送到对方计算机并且执行该蠕虫[Hoogstraten 2003]。
蠕虫利用cmd.exe建立一个远程shell进程“后门”,该后门监听TCP端口4444,从而允许攻击者在受危害的系统上发出远程命令。Blaster同时还试图对Windows Update网站发起拒绝服务(Denial-of-Service,DoS)攻击,以阻止用户下载补丁。蠕虫会在一个特定的日期以SYN洪水(SYN flood)的形式对windowsupdate.com的80端口发起DoS攻击。
1.1 衡量危险
即便Blaster不能成功地感染目标系统,DCOM RPC缓冲区溢出漏洞利用蠕虫也会终止其扫描到的Windows NT、Windows 2000、Windows XP以及Windows 2003系统上运行的svchost.exe进程。对于Windows 2000和Windows NT而言,这会导致系统不稳定甚至挂起;而对于Windows XP和Windows 2003,默认情况下会造成系统重启。