编辑推荐
C语言安全编程的难度可能超乎许多有经验的程序员的想象。为了帮助编程人员编写更安全的代码,本书提供了CERT C安全编码标准第二个正式发行版本的完整文档。这个新版本中的规则有助于确保程序员的代码完全遵循新的C11标准;它也处理早期版本(包括C99)的问题。
新标准列举了当前C语言软件漏洞的根源,按照严重性、利用的可能性和补救成本排定优先级。书中的98个指导方针都包含了不安全代码和对应的C11相容安全实现。如果统一应用,这些指导方针将消除导致缓冲区溢出、格式字符串漏洞、整数溢出和其他常见漏洞的严重编码错误。
内容简介
本书是业界最广泛采纳的编程指导原则汇编 ,它紧扣各个版本的C语言标准,分门别类地介绍了各种可能引发可利用安全漏洞的未定义行为、未指定行为,提出了安全编码的规则和建议,在每条规则和建议上都用现实的相容及不相容代码示例加以说明,本书是该标准文档的第2版,加入了对最新的C11标准的支持,对于所有有志于C语言软件开发的技术人员来说,都是不可或缺的参考书。
全书共14章,包括98条编码规则,每条规则都由一个标题、一段说明和不相容/相容的代码示例组成。第1章讲述与预处理器相关的规则;第2章介绍的规则与声明和初始化相关;第3章介绍的是与表达式相关的规则;第4~7章讲述的规则分别与整数、浮点数、数组及字符和字符串相关;第8章介绍与内存管理相关的规则;第9章讲解的规则与输入/输出相关;第10章介绍的规则与环境相关;第11~13章分别讲解与信号、错误处理和并发性有关的规则;第14章讲述几条杂项规则。最后提供3个附录,分别包括本书使用的词汇表、未定义行为和未指定行为。
作者简介
Robert C. Seacord 是卡内基-梅隆大学软件工程研究所(SEI)CERT计划的安全编码技术经理。CERT项目是运营相关网络安全研究和对美国网络安全挑战创新/及时响应的可信提供商。安全编码倡议和软件开发人员及软件开发组织合作,在部署之前消除由于编码错误造成的安全漏洞。Robert还是卡内-基梅隆大学计算机科学学院和信息网络学院的副教授。他曾经撰写过8本书籍,包括《Secure Coding in C and C++》第2版和《Java Coding Guidelines: 75 Recommendations for Reliable and Secure Programs》等。他还发表过40篇软件安全性、基于组件的软件工程、基于Web系统设计、遗留系统现代化、组件储存库和搜索引擎以及用户界面设计和开发方面的论文。
精彩书评
在Cisco,我们已经采用CERT C编码标准作为所有C语言开发人员的内部安全编码标准。它是我们的安全开发生命期的核心组成部分。本书描述的编码标准将复杂的软件安全主题分解为容易遵循的规则以及优秀的现实示例。这是任何希望编写安全、有弹性软件的C/C++开发人员必不可少的参考书。
——Edward D. Paradise,Cisco Systems工程、威胁响应、智能和开发副总裁
目录
译者序
前言
贡献者简介
第1章 预处理器(PRE)
1.1 PRE30-C. 不要通过连接创建通用字符名称
1.2 PRE31-C. 避免不安全宏参数的副作用
1.3 PRE32-C. 不要在类函数的宏调用中使用预处理器指令
第2章 声明和初始化(DCL)
2.1 DCL30-C. 声明具有正确存储持续期的对象
2.2 DCL31-C. 在使用前声明标识符
2.3 DCL36-C. 不要声明具有冲突链接类别的标识符
2.4 DCL37-C. 不要声明或者定义保留标识符
2.5 DCL38-C. 使用正确语法声明灵活数组成员
2.6 DCL39-C. 避免在结构填充中泄露信息
2.7 DCL40-C. 不要创建相同函数或者对象的不兼容声明
2.8 DCL41-C. 不要在switch语句第一个条件标签之前声明变量
第3章 表达式(EXP)
3.1 EXP30-C. 不要依赖求值顺序以避免副作用
3.2 EXP32-C. 不要通过非易失性引用访问易失性对象
3.3 EXP33-C. 不要读取未初始化的内存
3.4 EXP34-C. 不要对null指针进行解引用
3.5 EXP35-C. 不要修改具有临时生命期的对象
3.6 EXP36-C. 不要将指针转换为更严格对齐的指针类型
3.7 EXP37-C. 用正确数量和类型的参数调用函数
3.8 EXP39-C. 不要通过不兼容类型的指针访问变量
3.9 EXP40-C. 不要修改常量对象
3.10 EXP42-C. 不要比较填充数据
3.11 EXP43-C. 使用restrict限定的指针时避免未定义行为
3.12 EXP44-C. 不要向sizeof、_Alignof或者_Generic传递有副作用的操作数
3.13 EXP45-C. 不要在选择语句中执行赋值
第4章 整数(INT)
4.1 INT30-C. 确保无符号整数运算不产生回绕
4.2 INT31-C. 确保整数转换不会造成数据丢失或者错误解释
4.3 INT32-C. 确保有符号整数的运算不造成溢出
4.4 INT33-C. 确保除法和余数运算不会造成0除数错误
4.5 INT34-C. 不要用负数或者不小于操作数位数的位数对表达式进行移位
4.6 INT35-C. 使用正确的整数精度
4.7 INT36-C. 将指针转换为整数或者将整数转换为指针
第5章 浮点数(FLP)
5.1 FLP30-C. 不要使用浮点变量作为循环计数器
5.2 FLP32-C. 避免或者检测数学函数中的定义域和值域错误
5.3 FLP34-C. 确保浮点数转换在新类型的范围内
5.4 FLP36-C. 将整数值转换为浮点指针类型时保持精度
第6章 数组(ARR)
6.1 ARR30-C. 不要形成或者使用超限的指针或者数组下标
6.2 ARR32-C. 确保变长数组的大小参数在有效范围内
6.3 ARR36-C. 不要进行两个不引用相同数组的指针之间的减法或者比较
6.4 ARR37-C. 不要在指向非数组对象的指针上加或者减一个整数
6.5 ARR38-C. 保证库函数不形成无效指针
6.6 ARR39-C. 不要在指针上加或者减一个按比例调整的整数
第7章 字符和字符串(STR)
7.1 STR30-C. 不要企图修改字符串字面量
7.2 STR31-C. 保证字符串存储有足够的空间容纳字符数据和null结束符
7.3 STR32-C. 不要向要求字符串参数的库函数传递非null结束字符序列
7.4 STR34-C. 在转换为更大的整数尺寸之前将字符转换为unsigned char类型
7.5 STR37-C. 字符串处理函数的实参必须可以表示为unsigned char
7.6 STR38-C. 不要混淆窄和宽字符串及函数
第8章 内存管理(MEM)
8.1 MEM30-C. 不要访问已释放内存
8.2 MEM31-C. 在不再需要时释放动态分配的内存
8.3 MEM33-C. 动态分配和复制包含灵活数组成员的结构
8.4 MEM34-C. 只释放动态分配的内存
8.5 MEM35-C. 为对象分配足够的内存
8.6 MEM36-C. 不要通过调用realloc()修改对象的对齐方式
第9章 输入/输出(FIO)
9.1 FIO30-C. 从格式字符串中排除用户输入
9.2 FIO31-C. 不要打开已经打开的文件
9.3 FIO32-C. 不要在只适合文件的设备上执行操作
9.4 FIO34-C. 区分从文件读入的字符和EOF/WEOF
9.5 FIO37-C. 不要假定fgets()或者fgetws()在成功时返回非空字符串
9.6 FIO38-C. 不要复制FILE对象
9.7 FIO39-C. 不要在没有中间刷新或者定位调用的情况下在一个流中交替输入和输出
9.8 FIO40-C. 在fgets()或者fgetws()失败时重置字符串
9.9 FIO41-C. 不要用有副作用的流作为实参调用getc()、putc()、getwc()或者putwc()
9.10 FIO42-C. 在不再需要时关闭文件
9.11 FIO44-C. 对fsetpos()只使用fgetpos()返回的值
9.12 FIO45-C. 避免访问文件时出现TOCTOU竞争条件
9.13 FIO46-C. 不要访问已关闭文件
9.14 FIO47-C. 使用有效格式字符串
前言/序言
Preface 前 言本书为C语言编码提供了规则。这些规则的目标是开发安全、可靠和稳固的系统,例如,消除可能导致程序意外行为和可利用漏洞的未定义行为。遵循本标准定义的编码规则是确保C语言开发的软件系统安全、可靠、稳固的必要条件(但不是充分条件)。安全和稳固的设计也是必要的,安全性关键系统通常会提出比编码标准更严格的要求,例如,要求所有内存都是静态分配的。然而,应用本编码标准将产生高质量的系统,这些系统可靠、健壮并且能够抵御攻击。
每条规则都由一个标题、一段说明和不相容/相容的代码示例组成。标题是规则的简洁描述,但是有时候不够精确。说明提出了规则的规范要求。不相容代码示例是违反规则的代码示例。搭配的相容解决方案展示了等价的代码,这些代码不违反该规则或者该编码标准中的任何其他规则。
具有良好文档、可以实施的编码标准是C语言编码必不可少的要素。编码标准鼓励程序员遵循由项目需求和组织确定的一组统一规则,而不是简单地采用程序员熟悉的方法。一旦确定,这些标准可以作为评估源代码(使用人工或者自动化过程)的指标。
CERT编码规则为业界广泛采纳。Cisco系统公司在2011年10月的Cisco年度SecCon会议上宣布在其产品开发中采用CERT C安全编码标准作为基准编程标准。最近,Oracle将所有CERT安全编码标准整合到现有的安全编码标准中。注意,这是长期协作中的最新步骤:CERT和Oracle以前合作编写了《The CERT Oracle Secure Coding Standard for Java》(Addison-Wesley,2011)。
范围本书是为如下标准中定义的C语言版本开发的:
ISO/IEC 9899: 2011,Programming Languages-C, Third Edition [ISO/IEC 9899: 2011]ISO/IEC 9899: 2011/Cor.1: 2012,Technical Corrigendum 1本书在第1版的基础进行更新或替换(Addison-Wesley,2008)。本书第1版的范围是C99(C语言标准第2版)[ISO/IEC 9899: 1999]。虽然本书中的规则是为C11开发的,但是它们也适用于C编程语言的较早版本(包括C99)。在C语言标准各版本之间的差异影响这些规则的正常应用时,本书将在合适的地方进行标注。
大部分规则都有一个不相容代码示例程序与C11兼容,以确保规则所识别的问题在标准范围内。但是,编码问题的最佳解决方案往往与平台相关。在许多情况下,本标准提供兼容POSIX和Windows操作系统的相应解决方案。以ISO/IEC技术报告或者技术规范形式发布的语言和程序库扩展常常优先使用,例如ISO/IEC TR 24731-2《Extensions to the C Library-Part II: Dynamic Allocation Functions》[ISO/IEC TR 24731-2: 2010]描述的扩展。在许多情况下,还有为Linux或者OpenBSD等平台提供的兼容解决方案。我们偶尔还会描述有趣或者直观的特定实现行为。
原理C语言编码标准专注于C语言标准(C11)和C11之后的相关技术报告,可以在最长的时期内创造最高的价值。
C语言标准尽可能记录现有的实践方法。也就是说,大部分功能必须先在某个实现中测试,才能包含在标准中。本书有不同目的:确定一组最佳实践,有时候需要介绍尚未广为人知或者在现有方法无能为力时使用的新方法。换一种说法,本书试图推动变化,而不只是记录它们。
例如,C11中引入了可选而规范的附件K“Bounds-Checking Interfaces”(边界检查接口),对它的支持正在日益增加,但是目前只有少数供应商实现了这一接口。该接口引入了memcpy_s()等函数,目的是为API添加目标缓冲区大小,提供安全性服务。这一文档具有前瞻性,没有道理仅因为这些函数没有广泛实现而忽略它们。基本C语言标准的实现比附件K更广泛,尽管附件K还没有广泛实现,但它是行业发展的方向。新型C语言代码的开发人员尤其需要这样一本指南,指导他们使用正在开发的编译器和工具,从而最大限度地利用其能力。
有些供应商对C进行了扩展,有些则只实现了C语言标准的一部分便停止开发。因此,不可能倒退回去仅讨论C99、C95或者C90。供应商的支持方程非常复杂,无法确定一条基线,声称某个编译器具体支持某个标准。不管选择哪个分隔点,不同的编译器对于该语言的不同部分都可能出现相反的结果。要支持所有可能性,就必须对每个产品测试语言的每个特性。因此,我们选择了最近的一个分隔点,使标准定义的规则适用时间尽可能长。由于支持的种类不同,当程序员只使用C99规定的功能时,源代码的可移植性得到加强。这是C语言编程固有的安全性/可移植性之间的权衡。
前瞻性信息的价值随着时间的推移而提高,之后开始下降。而回溯性信息的价值从一开始就立刻下降。
由于以上这些原因,本书首先支持使用尚未加入C语言标准的C11及C11之后的技术报告进行的新代码开发。其次支持对C99旧代码及技术报告的纠正。
在效果显著且不会影响其他优先事项的时候,本书将为支持旧编译器做出贡献。这样做的目的不是捕捉所有偏离C语言标准的情况,而是捕捉少数几种重要的情况。
没有解决的问题对于一些问题,本书没有提供解决方案。
编码风格:编码风格是一个主观的问题,实践证明,无法开发公认的正确风格指南。因此,本标准对于具体采用哪一种风格不作要求,只建议开发组织定义或者采用风格指南,并一致地应用这些方针。一致地应用某种编码风格的最简方法是使用代码格式化工具。许多交互式开发环境(Interactive Development Environment,IDE)都提供这种功能。
有争议的规则:一般来说,CERT编码标准试图避免包含缺乏广泛共识的争议规则。
本书的读者本书主要是为C语言程序开发人员而编写的,但是也可以供软件采购者使用,以定义定制软件的需求。本书特别有利于对构造可靠、健壮、可以抵御攻击的高质量系统感兴趣的程序员。
本书虽然不是专门针对C++程序员的,但是对他们仍然有一定的价值,因为C语言程序的大部分问题在C++程序中也存在,不过在许多情况下,两者的解决方案不同。
历史CERT安全编码标准的思路起源于C语言标准委员会(更正式的叫法是ISO/IEC JTC1/SC22/WG14)在德国柏林召开的2006春季会议[Seacord 2013a]。C语言标准是权威文档,但其受众主要是编译器实现者,而且,许多人注意到,它的语言模糊,往往很费解。安全编码标准主要针对C语言程序员,为使用该语言安全编码提供实用指南。
CERT C安全编码标准在CERT安全编码wiki(http://www.securecoding.cert.org)上,按照基于社区的开发过程开发。来自该社区的专家(包括WG14 C语言标准委员会成员)应邀投稿,并且得到wiki的编辑特权。社区成员可以在wiki上注册一个免费账号,对编码标准和单独的规则做出评论。提供高质量评论的审核者常常得到编辑特权,可以直接为编码标准的开发和发展做出贡献。目前,CERT安全编码wiki有1576名注册的贡献者。
基于社区的开发过程有许多好处。最重要的是,它广泛吸引专家,并让他们对规则的内容形成一致的意见。在wiki上开发安全编码标准的主要缺点是内容不断演化。如果你需要最新信息,愿意接受尚未全面核查的变化,那么这种不稳定性是可以接受的。然而,许多软件开发组织想要一组静态的规则和建议,以便作为软件开发过程的需求。为此,在社区开发两年半之后,我们出版了本书第1版。随着2008年6月该书手稿的制作,书籍的1.0版本和安全编码标准的wiki版本开始分道扬镳。
在2007年4月的伦敦会议上首次提交CERT C安全编码指南给WG14审核,2007年8月在夏威夷可纳的会议上再次审核。
根据报道,2008年4月15日召开的J11/U.S. TAG会议讨论了INCITS PL22.11是否应该将CERT C安全编码标准提交给WG14,作为2类或者3类技术报告候选的问题。J11现在成为PL22.11 C语言编程任务组,这个技术委员会是ISO/IEC JTC1 SC22/WG14的美国技术顾问小组。我们就“谁有时间承担这一项目”这个问题进行了一次民意测验,赞成者(有时间)有4人,反对者(没有时间)有12人。之后,我们接收到的反馈是,虽然CERT C安全编码标准是一组强大的指导方针,开发时得到了WG14的许多技术专家的意见,并且已经由WG14审核多次,但是WG14通常不负责将指南“赐予”程序员,而负责定义编译器等工具的规范需求。
了解了这一点之后,我们提议WG14建立一个研究小组,考虑为C语言制作可分析安全编码指南的问题。这个研究小组于2009年10月27日第一次召开会议,CERT向ISO/IEC贡献了C安全编码规则的一个可自动实施子集,用于标准化进程。
研究小组的参与者包括分析程序供应商(如Coverity、Fortify、GammaTech、Gimpel、Klocwork和LDRA)、安全性专家、语言专家和消费者。2012年3月,WG14批准开发和发表ISO/IEC TS 17961—C语言编码规则的新工作项目,研究小组工作结束。意大利国家分委员会在WG14的代表Roberto Bagnara后来加入了WG14编辑委员会。2013年11月,ISO/IEC TS 17961: 2013(E)《信息技术—编程语言、环境和系统软件接口—C安全编码规则》[ISO /IEC TS 17961:2013]正式发表,可以在ISO商店(http://www.iso.org/iso/catalogue_detail.htm?csnumber=61134)订购。
ISO/IEC TS 17961 C语言安全编码规则ISO/IEC TS 17961的目的是建立一组分析程序(包括静态分析工具和C语言编译器)的需求基准,供希望诊断超出语言标准需求的不安全代码的供应商应用。所有规则都可以通过静态分析实施。选择这些规则的标准是,实施这些规则的分析程序必须能够有效地发现安全编码错误,不会产生过量的假阳性。
目前,不同供应商已经以特殊的方式将静态分析应用到安全保障上,造成重要安全保障问题的覆盖面不统一。ISO/IEC TS 17961列举了安全编码规则,需要分析引擎诊断这些规则的违背情况,作为规范相容性的指标。这些规则能够以实现相关的方式进行扩展,为任何相容静态分析实现的客户提供最小覆盖保证。
ISO/IEC TS 17961指定了C语言中安全编码的规则,包含每条规则的代码示例。不相容的代码示例阐述了具有潜在可利用安全性弱点的语言结构;这些例子预计会引起相容分析程序对受影响的语言结构的诊断。相容的例子预计不会引起诊断。ISO/IEC TS 17961不指定实施这些规则的机制和任何特殊的编码风格。
表P-1展示了ISO/IEC TS 17961与其他标准和方针的关联性。在已有的出版物中,ISO/IEC TS 17961是唯一以分析程序而非开发人员为直接受众的。
表P-1 ISO/IEC TS 17961与其他标准的比较编码标准C语言标准安全保障标准安全性标准国际化标准完整语言CWE无/全部是否否—MISRA C2C89否是否否MISRA C3C99否是否否CERT C99C99是否否
C安全编码标准:开发安全、可靠、稳固系统的98条规则(原书第2版) 电子书 下载 mobi epub pdf txt