简介
我们经常会听说计算机遭到基于Internet的远程攻击。通常位于攻击最前线的是一些服务器软件,例如:WEB、邮件和DNS,这些服务通常是通过监控进程(daemon,也可以叫作精灵进程)来提供的。这些服务即使是位于防火墙之后,也需要面对各种探测和攻击,以至让攻击者获得系统访问权限。大多数的恶意攻击者都会在系统安装rootkit,以便能够进行通常的系统操作。
一般情况下,这些rootkit和病毒需要使用目标系统的可执行文件、动态连接库以及配置文件。比如:一个安装在linux主机上的rootkit可能需要访问/bin/sh或者能够读写/etc目录下的系统配置文件。而且一旦系统被攻击者侵入,攻击者获得了root权限,就可以运行修改任何自己需要的文件。最近的lion、ramen蠕虫对BIND的攻击就可以证明以上观点。
但是如果你对精灵进程(daemon)进行限制,只允许其访问必要的文件,而不能访问整个文件系统,又将如何呢?这样就可以使我们的安全不再依赖于daemon软件开发人员的安全水平。
幸运的是,UNIX系统能够提供这样一种机制实现上面这种想法。在最近的BIND攻击中,Thaumaturgix, Inc的IT管理员William Cox提出了“在chrooted的环境中运行服务器进程,减小你的暴露程度(The best way to limit your exposure is to run the server in a 'chrooted' environment))。这种chrooted环境通常叫作一个chroot牢笼(jail),实际上这种概念已经存在了很长时间了,但是一直没有被软件开发人员和系统管理人员充分利用。
chroot牢笼(jail)概念综述
实现一个chroot jail包括两种方式:
限制进程只能访问整个文件系统的一个子集。
以较低的权限运行服务进程。
这两种方式是由一些标准的系统调用来提供的。首先,是chroot(),这个系统调用能够限制进程对文件系统的访问。即使某个进程是以root的权限运行的,它对文件/目录的访问也都是相对于chroot()系统调用限制的整个文件系统的子目录。
例如,如果一个进程以/var/sample/jail为参数执行了chroot()系统调用,现在它要访问一个文件:/etc/passwd,但是操作系统最后会把这个访问请求替换为对 /var/sample/jail/etc/passwd的访问。chroot系统调用只能以root权限调用。
降低进程权限的系统调用主要包括:setuid()、setgid()和setgroups()。setuid()指定进程的实际和有效用户权限;而setgid()指定进程的实际和有效组权限。setuid()系统非常重要,一旦通过它进入较低的权限运行,进程将无法自己重新获得root权限。setgroups()定义进程的追加组成员关系。除此之外,还有一些其它的相关系统调用,用户可以从自己系统的手册页中获得相关文档。
其它种类的操作系统可能还有另外的进程束缚方法。例如在FreeBSD中就有一个jail()函数。为了使你更好地体会到jailing的好处,我将通过一个典型的rootkit加以说明,在不同的权限下以及有没有被限制在jail环境中rootkit对系统的危害是不同的。在此,要时刻记住一件事情,当一个服务被侵入,攻击者就能够拥有服务进程所具有的权限。请看下面这个表格:
+-----------------+---------------------------------------|
|
|
|
|
|
running as root
|
running non-root |
|
|
|
|
+-----------------+-------------------+-------------------|
|
|
|
|
|
entire fs
|
(a)
|
(c)
|
|
|
|
|
|-----------------+-------------------+-------------------|
|
|
|
|
|
jailed fs
|
(b)
|
(d)
|
|
|
|
|
+---------------------------------------------------------/
运行于(a)类(进程以root权限运行并且可以访问整个文件系统)状态下的进程是rootkit的首选目标,侵入这样的服务,攻击者可以修改二进制可执行文件,例如:/bin/ps、/bin/netstat等,打开特权网络端口,读取任意的系统文件包括:/etc/shadow文件。最糟糕的是,他们能够对系统进行完全的破坏,比如:rm -rf /。运行于这种状态,最为常见的一个例子就是sendmail(http://www.sendmail.org。
如果服务进程处于(b)类(root权限、牢笼环境)状态下,一般的rootkit就可能无法正常操作,因为它们一般需要一个shell(/bin/sh)和一些基本的命令,例如:/bin/rm和/bin/cp。然而,在这种状态下,rootkit照样可以打破牢笼(jail)。因为服务进程以root权限运行,攻击者可以通过攻击代码直接执行一些允许root执行的操作(例如:直接引用牢笼之外文件系统的索引节点)。因此,这种状态虽然比(a)类状态安全(门槛高的多),但是也无法对服务提供足够的保护。
服务进程处于(c)类(非root权限,可以访问整个文件系统)状态下,对整个系统的威胁比(a)状态小,因为毕竟攻击者无法直接获得root权限。但是,如果服务进程处于这种状态下,攻击者一旦侵入这个服务,就可以执行一些命令,获得一个shell进行交互,然后很可能通过本地攻击获得root权限。即使攻击者不能获得root权限,也可以访问到系统的绝大多数配置文件和其它信息,例如:用户的电子邮件帐户信息(大量的垃圾邮件将蜂拥而至)。
最后,处于(d)类(非root权限,jail环境)状态下的服务进程受到的限制最为苛刻,这样攻击者根本没有机会执行shell,也不可能获得大量的系统信息。而且,对系统进行的所有破坏都被限制在jail环境中。在这种状态下,最大的威胁就是攻击者在这个jail环境中防止一个可以被jail环境之外的进程访问的可执行文件,从而使攻击代码扩散出jail环境。因此,你应该经常监视你的牢笼,看一下里面的囚犯是否逃出来了:P。
下面我们将举一个现实的例子进行说明。
Postfix精灵进程分析
Postfix(http://www.postfix.org)是一个邮件传输代理(Mail Transfer Agent)。它允许用户收/发SMTP邮件,把给本地用户的邮件投递到用户主机。Postfix是sendmail的一个变通,作者Wietse Venema对安全问题倾注了很大的关注。这个软件是一个非常典型的所谓守纪律精灵(disciplined daemon),可以安装在一个chroot牢笼(jail)环境中。我相信理解了Postfix是如何工作的,你就可以实现一个简单的安全精灵(daemon)。
Postfix从一个叫作master的程序开始执行,master以root权限启动,然后继续以root权限运行。不过,master本身非常小,其作用这是spawn进程,这些进程大部分会被放在一个chroot牢笼(jail)环境中执行实际的工作。通过这种方式,以root权限运行的代码数量非常有限。
下面我们看一看master是怎样和smtpd进行交互的。master一旦检测到一个向25号端口(SMTP的监听端口)的连接,它就会执行smtpd。下面我们就看一下postfix使用的一些jailing方法,这些代码在src/util/chroot_uid.c文件中。在讲述过程中,我们把/var/spool/postfix作为chroot牢笼(jail)环境的根目录:
+-----------------------------+-----------------+--------------------|
|
user/group
|
filesystem
|
+-----------------------------+-----------------+--------------------|
|
master is run on startup
|
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
master opens port 25
|
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
master detects connection |
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
master forks smtpd
|
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
master continues execution |
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
smtpd inherits permissions |
root/root
|
/
|
|-----------------------------+-----------------+--------------------|
|
smptd calls setgid()
|
root/postfix
|
/
|
|-----------------------------+-----------------+--------------------|
|
smptd calls initgroups()* |
root/postfix
|
/
|
|-----------------------------+-----------------+--------------------|
|
smtpd calls chroot()
|
root/postfix
| /var/spool/postfix |
|-----------------------------+-----------------+--------------------|
|
smptd calls setuid()
| postfix/postfix | /var/spool/postfix |
|-----------------------------+-----------------+--------------------|
|
smtpd processes connection | postfix/postfix | /var/spool/postfix |
|-----------------------------+---