《高质量程序设计艺术》样章连载——3.4 问题API
原书名:Code Quality: The Open Source Perspective<o:p></o:p>
<!---->1. <!---->深入剖析著名开源软件的质量问题<o:p></o:p>
<!---->2. <!---->全面阐述C、C++和Java代码中的常见编程错误<o:p></o:p>
<!---->3. <!---->指导你编写优秀代码的圣经<o:p></o:p>
<o:p> </o:p>
更多详细信息:http://www.china-pub.com/37661<o:p></o:p>
----------------------------------------------------------------------------------------------------------------------<o:p></o:p>
<o:p></o:p> 3.4 问题API
在检查代码、清除安全漏洞的时候,有一个值得关注的目标就是一些经常会被误用而导致程序有漏洞的API函数。其中的一部分函数(例如在3.3节研究的access系统调用,以及C库函数strcpy)的接口本质上就是不安全的。这些年来,很多这种问题API已经被更加安全的替代品取代了。然而,为了保持向后兼容,这些不安全的函数仍然存在。另外,替代的函数通常是特定于操作系统的,因此比原来的不安全函数的可移植性差。另外一些函数,尽管它们本质上不是不安全的,但是通常会被不适当地用在安全关键的环境中(没有经过有针对性的设计),或者使用的方式太过随意,容易被恶意用户利用。最后,有些函数,例如tmpfile、getpass、getopt和syslog,通常就实现得容易被攻击。尽管其最新的实现是安全的,但是并不一定总是能够保证在你检查的系统上运行着的就是正确的版本。在后续各小节中,我们将研究一些具有代表性的API问题。<o:p></o:p>
3.4.1 容易出现缓冲区溢出的函数
<!----><!----><!---->很多函数使用调用者提供的缓冲区来返回变长的结果,但是它们的接口没有提供指定缓冲区长度的手段。因此,在很多情况下,很难甚至不可能避免缓冲区溢出漏洞。这些函数包括C库的字符串函数strcpy、strcat以及strncat;I/O函数gets、sprintf、vsprintf、scanf、sscanf、fscanf、vscanf以及vfscanf;还有一些操作系统特定的函数,如Unix函数getwd,以及Windows函数OemToChar和CharToOem。
<!----><!----><!---->处理这些函数的方法有两种。一种方法是使用更加安全的替代函数,即接受一个额外的参数来指定目标缓冲区的大小(见表3-6)。
表3-6 不安全的C函数及其更安全的替代品<o:p></o:p>
不安全的函数<o:p></o:p>
|
更安全的替代品<o:p></o:p>
|
strcpy<o:p></o:p>
strcat<o:p></o:p>
strncat<o:p></o:p>
gets<o:p></o:p>
sprintf<o:p></o:p>
vsprintf<o:p></o:p>
getwd<o:p></o:p>
|
strlcpy或strncpy<o:p></o:p>
strlcat或strncat<o:p></o:p>
strlcat<o:p></o:p>
fgets<o:p></o:p>
snprintf或指定“%.长度”格式<o:p></o:p>
vsnprintf<o:p></o:p>
getcwd或open(".")后跟fchdir<o:p></o:p>
|
<!----><!---->下的例子演示了正确地传递缓冲区大小给strncpy函数的习惯用法:
<o:p> </o:p>
<!----><!----><!---->在上述例子中,打印的数值总是落在0~255(0xff)范围之内,因此可以使用2个十六进制数字表示。因此,3个字符大的缓冲区(2个字节储存数字,还有一个用来储存结尾的null字符)就足以装下结果了。让人吃惊的是,这段代码的作者觉得正好分配3个字符来储存结果不太对劲,于是就让所用的缓冲区比实际需要的大2个字节,“以防万一”。
<!----><!---->
<!---->
在某些情况下,数据来自于用户输入,这时候对数据的长度做任何假设都是不合适的。图3-5中的代码(写本书时它仍然是不正确的)演示的NETBSD的banner程序是有缓冲区溢出问题的,因为它将用户指定的(任意大小的)消息复制到一个定长的缓冲区中。这个程序具有潜在的漏洞,因为在某些环境中,banner程序被用来在共享的打印机上执行的打印作业之间生成输出分隔页,在这种情况下,banner的执行权限可能不是普通用户。与此对应的FreeBSD实现(见图3-6)也使用strcpy和strcat,但是却没有这个问题,因为所需要的缓冲区空间是计
<!---->
<!---->
http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/banner/banner.c?rev=1.15。
<!---->
3.4.2 格式字符串漏洞
<!----><!----><!----><!----><!----><!---->很多输出例程都有一个特殊的参数,该参数是一个格式字符串,用来指定输出的格式。典型的例子有C库函数printf和fprintf,Unix系统特有的函数syslog、warn、warnx、err、errx和setproctitle,以及Windows系统上的函数FormatMessage。对这些例程的一种误用是将需要输出的字符串直接指定为格式字符串参数,例如:
试图从栈上获取其他的数据。精心构造的格式字符串可以让程序去读或者写任意的内存位置,进而被用来获得对系统的控制权。
<!----><!---->上面的第一个例子基本上是没有什么问题的,因为输出的字符串是固定的。但是另外两个例子就不同了,格式字符串可能是来自于用户提供的数据:前一个例子中是主机名与用户提供的FTP用户的邮件地址,后一个例子中是用户偏爱的编辑器。这两者都曾经是安全漏洞报告的主题。 修正这些问题是很容易的:使用一个格式字符串作为第一个参数,这样原来的参数就会被格式化为一个字符串并输出。上面的两个问题也就是这么解决的:
在某些情况下,例如支持国际化的程序,它们不得不使用用户提供的数据来作为格式字符串(例如本地化的消息)。针对这些情况,有些系统在其C库中提供了fmtcheck函数,该函数可以依照一个正确的格式模板对一个可疑的(来自于不可信的用户)格式字符串进行验证。只有在两个格式字符串的格式指定符的类型以及顺序(而不是文本)都一一对应的情况下,fmtcheck函数才会报告说被检查的格式字符串是符合模板的。
3.4.3 路径与命令行解释器的元字符漏洞
<!----><!----><!----><!----><!----><!---->很多函数都负责加载可执行程序。它们中的一部分可能会根据发起执行命令的用户指定的一系列目录路径来定位可执行代码。这样的例子包括标准C库函数system,Unix函数popen、dlopen、execlp和execvp,以及Windows函数spawnlp、spawnvp、LoadLibrary、LoadLibraryEx、AfxLoadLibrary、ShellExecute、ShellexecuteEx、CreateProcess、CreateProcessAsUser和WinExec。如果你在以提升了的权限运行的代码中发现了这些函数,那么需要注意的是攻击者可能会改变默认的查找路径,导致这些程序加载并执行他们选定的代码。就我们列出的函数而言,一般来说调用它们的代码都会以提升了的权限运行。针对这种漏洞的解决方案首先要做的就是将寻找路径设置为安全的默认值:
前面讨论的函数中的system和popen还有额外的潜在安全问题。它们两个都将想要执行的命令作为参数,调用系统的命令行解释器(在Unix上一般是sh,而在Windows上是command或者cmd)来运行这个命令。这个额外的一层间接调用导致了更多的漏洞。
<!---->■如果要执行的命令包含用户提供的文本,攻击者就可以以很多种方式利用命令行解释器的灵活性。明确地说,他们可以使用:
<!---->●<!---->输入和输出重定向字符来读写其他文件。<o:p></o:p>
<!---->●<!---->命令分隔字符(Unix系统上的“;”字符以及各种版本的Windows上使用的“&”)来执行更多的命令。<o:p></o:p>
<!---->●<!----> <!---->Unix命令行解释器的命令结果转义字符“、”来执行其他命令。<o:p></o:p>
<!---->●<!----> <!---->命令行解释器的各种引号使用机制,来让命令行解释器解释命令行参数而不传递给要执行的程序。<o:p></o:p>
<!----><!----><!---->专门去防卫这些攻击是很麻烦的,最安全的方法就是对用户输入的所有字符进行过滤,除了字符、数字、空格以及斜线之外,其他的字符都过滤掉。
<!---->■ <!----><!----><!----><!---->在Unix系统上,恶意用户可以设置IFS环境变量,这个环境变量指定了内部字段分隔字符(internal field separator)——命令行解释器用IFS字符将命令的文本行分割为各个字段——来改变命令被解释的方式。
<!---->■<!---->在Windows系统中,攻击者可以修改环境变量COMSPEC的值,加载他们指定的命令行解释器。
从运行环境中去掉对应的变量就可以避免后两种攻击,没有设置这些变量的时候,底层的代码通常会使用安全的默认值。更好的方法则是,在代码中看到system和popen时,考虑一下是否可以使用fork、execv、wait以及pipe(Unix系统上)或者spawnv(Windows系统上)。
3.4.4 临时文件
<!----><!----><!---->很多应用在运行过程中都会生成临时文件。函数库的开发人员出于提供方便的目的,编写了很多API来产生临时文件(mktemp、mkstemp、tempnam、tmpnam和tmpfile),但非常遗憾的是,当前的状况是一团糟。对于应该使用哪个接口,C库的各种实现提供了互相矛盾的建议。关于临时文件相关函数的各种问题可以总结如下。
<!---->■返回临时文件名的mktemp、tempnam和tmpnam有竞态条件问题;在这些函数返回之后到调用这些函数的程序真正创建临时文件之间的间隙,攻击程序可以使用产生的临时文件名创建一个符号链接。因此,特权程序可能会被欺骗,在攻击者通常没有写入权限的地方生成文件,或者将已存在的文件置空。
<!---->■<!---->较早的tempnam、tmpnam、tmpfile和mktemp实现就两方面来说是有缺陷的。首先,就每个文件名模板字符串来说,它们只支持有限的文件名(一般最多26个)。另外,典型的实现都使用access系统调用来判断是否可以用某个文件名生成文件,这导致了另一个竞态条件,让特权程序的执行状况变得更加复杂。
<!---->■ <!---->较早的tmpfile实现可能会生成其他用户或者组可读及可写的文件。
<!---->■ <!---->大多数实现产生的文件名都是很容易猜测的;这可以帮助攻击者预先创建同名的文件,骗得应用程序犯下错误。
<!---->■
分享到:
相关推荐
### V4L2 API函数说明书概述 #### 一、引言 Video for Linux Two (V4L2) 是一种在 Linux 内核中用于视频采集和处理的 API(应用程序编程接口)。它支持广泛的硬件设备,如 USB 摄像头、电视卡、视频捕获卡等,并且...
它提供了丰富的函数和数据结构,用于管理相机状态、传输图像数据、控制曝光参数等。通过 EDSDK,开发者可以创建自定义的摄影应用,实现自动化工作流程或者在特定环境下控制相机。 2. **API详解** API(Application...
【微信大转盘抽奖小程序源码】是一种基于微信小程序开发的应用程序,用于实现互动式的抽奖活动。这种源码是开发者已经编写完成并经过测试的代码,确保无误且功能完善,使用者可以将其作为基础,快速搭建自己的抽奖...
这些滤镜功能强大,能够帮助开发者在应用程序中实现丰富的图像处理效果。 首先,让我们逐一了解这些滤镜的作用: 1. **柔化滤镜**:这种滤镜通过降低图像的局部对比度来使图像看起来更柔和,常用于肖像照片的修饰...
微信小程序是一种轻量级的应用开发平台,主要针对移动端,由腾讯公司推出,旨在提供便捷的、无需下载安装即可使用的应用服务。"微信小程序源码摄影展示小程序"是专门为摄影师或摄影爱好者设计的一个小程序模板,它...
在"小程序链接WiFi"这个功能中,`app.js`是应用程序的主JS文件,它包含了全局的配置和事件处理。开发者可能在这里定义一个全局的函数,如`onLaunch`或`onShow`,来处理小程序启动或显示时的逻辑,例如初始化WiFi连接...
微信小程序是一种轻量级的应用程序,它无需下载安装即可在微信平台上使用,为用户提供了便捷的体验。在这款名为“恶搞小程序,放屁特效”的应用中,开发者利用了微信小程序的技术特性,创造了一个趣味性十足的功能,...
海康SDK通常包含一系列的API函数和库文件,允许开发者访问和控制摄像头的各项功能,如调整分辨率、曝光时间等,以及获取实时视频流。在WPF应用中,我们需要引用这些库,并调用相应的API函数。 在集成SDK时,首先要...
佳能EDSDK2.3 API文档是为开发者提供的一份详细指南,用于集成佳能相机功能到第三方应用程序中。这份PDF文档涵盖了佳能相机的电子开发套件(EDSDK)的所有接口和函数,使得程序员可以控制相机的设置、拍摄照片、录制...
5. **事件通知**:支持通过事件机制来通知应用程序关于相机状态的变化。 6. **高级功能**:例如图像流压缩、硬件触发等,满足更复杂的应用需求。 #### 五、兼容性与合规性 - **FCC认证**:对于美国市场的客户,...
在Android平台上,相机功能是应用程序开发中的重要组成部分,特别是在创建社交、图像编辑或者任何与图像处理相关的应用时。本文将详细解析一个名为"TakePicture"的Android Camera拍照例子程序,帮助开发者理解如何在...
2. 安全可靠:腾讯云提供强大的安全防护机制,确保数据安全和应用稳定。 3. 弹性扩展:根据业务需求自动调整资源,应对高并发场景,降低运维成本。 4. 整合腾讯生态:与微信支付、腾讯地图、社交分享等功能无缝...
1. 数据安全较低:由于微信小程序运行在微信的环境中,用户的隐私数据可能存在安全隐患,开发者需要额外注意数据保护和加密。 2. 自有度受制于腾讯:微信小程序的规则和政策由腾讯制定,开发者在功能实现和运营策略...
JS自调用匿名函数是一种在JavaScript编程中广泛使用的技术,它的目的是创建一个临时的命名空间,以避免...通过这种方式,可以将应用程序的不同部分隔离开来,降低了代码之间的依赖,提高了代码的可维护性和可重用性。
在Android开发中,Camera API是开发者用来集成相机功能到应用程序的关键部分。 描述中提到的“NULL”没有提供额外信息,但博文链接可能包含详细的实现细节或示例代码。由于我们无法直接访问该链接,我们将基于通用...
此外,了解佳能设备特有的通信协议和命令集也是必不可少的,因为这将直接影响到应用程序的兼容性和性能。 总之,佳能开发包为开发者提供了丰富的资源,使他们能够构建与佳能硬件紧密结合的创新应用,同时降低了跨...
在VC环境中,你可以选择创建一个新的MFC应用程序或Win32控制台应用程序。为了使用uEye的ActiveX控件,我们需要在工程设置中包含相应的库和头文件。在“项目” -> “属性” -> “配置属性” -> “C/C++” -> “常规”...