当前位置: 首页 > 图文教程 > 网络安全 > 安全基础 > 安全编程: 避免竞争条件(1)

安全基础
IE浏览器防黑十大秘籍,黑客也没招
网络工程师讲解系统安全漏洞的形成和防治
清除导致XP系统反复重启的新网银木马
识破QQ欺骗网络地址的几种方法汇总
安全基础知识 细说暴库的原理与方法
排除无线突然中断故障实例
强搜天线 搜出WiFi世界的安全漏洞
网管应用技巧 内网安全十大策略说明
如何修改局域网内部打印机的IP地址
如何找出IIS中隐藏的网站
EFS加密技术的概念分析及一次解密经过
提高Windows XP系统安全性要关闭的10种服务
PHPBB 2.0.22 MOD版最新注入漏洞
修复Windows系统忘记密码的9个高招
用SockOnline软件轻松突破端口限制
安全基础知识 最强0到33600端口详解
执行文件方式加密FLASH文件的解密方法
网吧被入侵后的应对解决方法
网页“黑手”如何攻击你的Windows系统
不要让别人读了你的信 谈私密数据保护

安全基础 中的 安全编程: 避免竞争条件(1)


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-28   浏览: 38 ::
收藏到网摘: n/a

  了解什么是竞争条件,以及它们为什么会引发安全问题。本文向您展示了如何在类 UNIX® (Unix-like)系统中处理常见的竞争条件,包括如何正确地创建锁文件、锁文件的替代者,如何处理文件系统,以及如何处理共享目录(特别是如何在 /tmp 目录下正确创建临时目录)。需要您对信号处理稍有了解。

  通过一个偷窃而来的口令,Mallory 成功地登录到一台运行 Linux 的重要服务器。其帐号是一个非常受限的帐号,但是 Mallory 知道如何使用它来制造麻烦。Mallory 安装并运行了一个行为非常奇怪的小程序,该程序使用多个进程在 /tmp 目录下快速地创建和删除很多不同的符号链接文件。(符号链接文件也称为 symlink,是一种简单的文件,当被访问时,它会将请求重定向到另一个文件。)Mallory 的程序不停地创建和删除很多指向同一特殊文件(/etc/passwd,口令文件)的不同符号链接文件。

  这台重要的服务器的安全措施之一是,它每天都运行 Tripwire —— 具体地说,是较老的 2.3.0 版本。Tripwire 是一个检测重要文件是否被篡改的安全程序。与很多程序一样,Tripwire 启动时会尝试着创建一个临时文件。Tripwire 会查看并断定不存在名为“/tmp/twtempa19212”的文件,所以看起来这是一个合适的临时文件名称。但是在 Tripwire 完成检查后,Mallory 的程序就会使用该名称创建一个符号链接文件。这不是偶然的;Mallory 程序的设计目标就是创建最有可能为 Tripwire 所使用的文件名。然后 Tripwire 就会打开该文件,开始写入临时信息,但不用创建新的空文件,Tripwire 现在正在重写口令文件!从那时起,任何人 —— 甚至是管理员 —— 都不能登录到该系统,因为口令文件已经被破坏了。更糟的是,Mallory 的攻击完全可以覆盖所有文件,包括服务器上存储的重要数据。


竞争条件简介

  这是个假想的故事;“Mallory”是攻击者的一个惯用名。但是这类攻击,以及它所利用的缺陷,都极其常见。问题是很多程序都容易受到名为“竞争条件”的安全问题的影响。

  当由于事件次序异常而造成对同一资源的竞争,从而导致程序无法正常运行时,就会出现“竞争条件”。注意,竞争条件无需介入同一程序的两个部分之间的竞争;如果一个外部的攻击者可以通过意想不到的方式干扰程序,那么就会出现很多安全问题。例如,如果 Tripwire 2.3.0 确定某个文件不存在,它就会尝试着创建该文件,而不去考虑在进行这两个步骤期间,该文件是否已经被攻击者创建。几十年前,竞争条件还不是什么问题;那时,计算机系统通常在同一时刻只能运行一个单独的程序,什么都不能打断它或者与它竞争。但是,当今的计算机通常需要同时运行大量的进程和线程,经常还会有多个处理器确实在同时运行不同的程序。这样做更灵活,但是有一个危险:如果这些进程和线程共享了所有的资源,那么它们都可能互相影响。实际上,竞争条件缺陷是软件的更常见缺陷之一,此外,在类 Unix 系统上,/tmp 和 /var/tmp 目录经常会被错误地使用,从而导致竞争条件。

  不过,我们首先需要了解一些术语。所有 类-Unix 系统都支持用户进程;每个进程都有自己的内存空间(其他进程通常无法访问)。底层的内核会尽量使进程看起来像是在同时运行;在多处理器的系统中,它们确实可以同时运行。从理论上讲,一个进程可以拥有一个或多个线程;这些线程可以共享内存。线程也可以同时运行。由于线程可以共享内存,所以,相对于进程,线程之间更有可能产生竞争条件;正是由于这个原因,多线程程序的调试要困难得多。Linux 内核有一个非常好的基本设计:只有线程,并且一些线程可以与其他线程共享内存(这样实现了传统的线程),而另外一些线程则不能(这样就实现了独立进程)。

  为了理解竞争条件,让我们首先来看一个非常普通的 C 声明:

清单 1. 普通的 C 声明

b = b + 1;

  看起来非常简单,不是吗?但是,让我们假定有两个线程在运行这一行代码,在这里,“b”是一个由两个线程共享的变量,“b”的初始值为“5”。以下是一个似是而非的执行次序:

清单 2. 使用共享的“b”的可能执行次序

(thread1) load b into some register in thread 1.
    (thread2) load b into some register in thread 2.
(thread1) add 1 to thread 1's register, computing 6.
    (thread2) add 1 to thread 2's register, computing 6.
(thread1) store the register value (6) to b.
    (thread2) store the register value (6) to b.

  初始值为 5,然后两个线程分别加 1,但是最终的结果是 6... 而不是应该得到的 7。问题在于,两个线程互相干扰,从而导致产生错误的最终答案。

  通常,线程不是以原子的方式执行的;另一个线程可以在任何两个指令期间打断它,而且还可以使用一些共享的资源。如果一个安全程序的线程没有预防这些中断,那么另一个线程就可以干扰该安全程序的线程。在安全程序中