位置:海鸟网 > IT > linux/Unix >

如何使用chroot保障开源系统服务安全

本文中,作者将为大家讲述如何使用chroot保障开源系统服务安全。

1、主要功能

在早期的UNIX系统中,根目录是文件系统中的一个固定点。在当前UNIX变体中,包括Linux,你可以在每个进程的基础上定义根目录。chroot实用程序程序允许你用根目录(而非/)运行一个进程。

根目录位于目录层次结构的顶部,并且没有父目录。因此,一个进程无法访问根目录以上的文件,因为不存在。例如,如果运行一个程序(进程),指定其根目录为/home/sam/jail,该程序没有/home/sam中的任何文件的概念:jail是该程序的根目录,并标记为/(不是jail)。

通过创建一个人工的根目录,通常被称为(chroot)jail,可以防止一个程序访问、执行或修改(可能恶意)始自其根目录层次结构之外的文件。你必须正确设置一个chroot jail以提高安全性:如果你没有正确设置chroot jail,恶意用户会比没有chroot jail更容易获得访问系统的权限。

2、使用chroot

1)创建chrot jail

创建一个chroot jail很简单:使用root权限,执行/usr/sbin/chroot directory命令。其中directory成为根目录,该进程试图运行默认shell。使用root权限,下面的命令在(现有的)/home/sam/jail目录中设置一个chroot jail:

# /usr/sbin/chroot /home/sam/jail

/usr/sbin/chroot: failed to run command '/bin/bash': No such file or directory

这个例子设置一个chroot jail,但是当系统试图运行bash shell时,操作失败。一旦设置了jail,名为jail的目录将取代根目录的名称/。因此,chroot环境无法找到由/bin/bash路径名标识的文件。在这种情况下chroot jail正常工作,但没有用处。

让chroot jail按你想要的方式工作是较为复杂的。要让前面的例子在chroot jail中运行bash,在jail (/home/sam/jail/bin)中创建一个bin目录并将/bin/bash复制这个目录。由于bash二进制文件是到共享库的动态链接,你还需要将这些库文件(在lib中)复制到jail中。

2)一个具体的例子

下面的示例创建必要的目录、复制bash、使用ldd来显示bash依赖的共享库以及复制必要的库文件到lib中。 linux-gate.so.1文件是一个动态共享对象(DSO),由内核提供以加速系统调用,不必复制它。

$ pwd

/home/sam/jail

$ mkdir bin lib

$ cp /bin/bash bin

$ ldd bin/bash

linux-gate.so.1 => (0×00988000)

libtinfo.so.5 => /lib/libtinfo.so.5 (0×0076b000)

libdl.so.2 => /lib/libdl.so.2 (0×00afb000)

libc.so.6 => /lib/libc.so.6 (0×00110000)

/lib/ld-linux.so.2 (0×00923000)

$ cp /lib/{libtinfo.so.5,libdl.so.2,libc.so.6,ld-linux.so.2} lib

现在再次启动chroot jail。虽然一个普通用户可以完成所有设置,但必须使用root权限来运行chroot:

$ su

Password:

#/usr/sbin/chroot .

bash-4.1# pwd

/

bash-4.1# ls

bash: ls: command not found

bash-4.1#

这一次chroot查找并启动bash,显示其默认的提示符(bash-4.1#)。pwd命令工作,因为它是一个shell内置命令。然而,bash无法找到ls命令,因为它不在chroot jail中。如果想要jail中的用户能够使用ls,可以把/bin/ls及其库文件复制到jail中。exit命令允许你从jail退出。

如果为chroot提供第二个参数,它把该参数作为jail内运行的程序的名称。下面的命令与前一个等价:

# /usr/sbin/chroot /home/sam/jail /bin/bash

要建立一个有用的chroot jail,首先要确定chroot jail的用户需要哪些实用程序。然后将相应的二进制文件及其库文件复制到jail中。或者,可以建立二进制文件的静态副本并把它们放入jail中,无需安装单独的库。(静态链接二进制文件大大超过其对应的动态二进制文件。bash基本系统及其核心工具的规模超过50兆字节。)你可以在bash和coreutils SRPMS(源RPM)软件包中找到最常用工具的源代码。

chroot实用程序将失败,除非以root权限运行。以root权限运行chroot的结果是一个root shell(具有root权限的shell)运行在chroot jail内。由于具有root权限的用户可以突破chroot jail,当务之急是在chroot jail中要以降低的特权运行一个程序。

有几种方法可以降低用户的特权。例如,可以把su或sudo放在jail中,然后启动shell或jail内的守护程序,使用这些程序之一,来降低在jail中工作的用户的特权。以下命令以jail中降低的特权启动一个shell:

# /usr/sbin/chroot jailpath /bin/su user -c /bin/bash

其中jailpath是jail目录的路径名,以及user是shell以特权运行的用户名。这种情况下的问题是sudo和su调用PAM。要运行这些实用程序之一,需要把所有的PAM,包括它的库和配置文件,与sudo (或 su)和/etc/passwd文件一起放在jail中。或者,可以重新编译su或sudo。然而,其源代码调用PAM,所以需要修改其源代码以便它不调用PAM。这些技术既费时又引入了复杂性,从而导致不安全的jail。

下面的C程序以降低的特权运行chroot jail中的一个程序。因为该程序在调用chroot()之前获取你在命令行上指定的用户的UID和GID,不需要把/etc/passwd放入jail。该程序降低了指定用户的指定程序的特权。该程序为前面的问题提供了一个简单的解决方案,所以你可以试验chroot jail并更好地理解其工作原理。

$ cat uchroot.c

/* See svn.gna.org/viewcvs/etoile/trunk/Etoile/LiveCD/uchroot.c for terms of use. */

#include

#include

#include

int main(int argc, char * argv[])

{

if(argc < 4)

{

printf("Usage: %s {username} {directory} {program} [arguments]\n",

argv[0]);

return 1;

}

/* Parse arguments */

struct passwd * pass = getpwnam(argv[1]);

if(pass == NULL)

{

printf("Unknown user %s\n", argv[1]);

return 2;

}

/* Set the required UID */

chdir(argv[2]);

if(chroot(argv[2])

||

setgid(pass->pw_gid)

||

setuid(pass->pw_uid))

{

printf("%s must be run as root. Current uid=%d, euid=%d\n",

argv[0],

(int)getuid(),

(int)geteuid()

);

return 3;

}

return execv(argv[3], argv + 3);

}

以下命令的第一行使用cc(gcc软件包)编译uchroot.c,创建一个uchroot可执行文件。后续命令将uchroot移入/usr/local/bin目录,并给予相应的所有权。

$ cc -o uchroot uchroot.c

$ su

password:

# mv uchroot /usr/local/bin

# chown root:root /usr/local/bin/uchroot

# exit

$ ls -l /usr/local/bin/uchroot

-rwxrwxr-x. 1 root root 5704 12-31 15:00 /usr/local/bin/uchroot

使用本节前面的设置,执行下面的命令以chroot jail内用户sam的特权运行一个shell:

# /usr/local/bin/uchroot sam /home/sam/jail /bin/bash

如果你计划部署多个chroot jail,最好保存bin和lib目录的一个干净副本。

3、运行chroot Jail中的一个服务

运行jail内的shell,用处不大。在现实中,你更可能要运行jail内的一个特定服务。要运行jail内的服务,确保该服务所需的所有文件在jail内。使用uchroot在chroot jail中启动一个服务的命令格式为:

# /usr/local/bin/uchroot user jailpath daemonname

其中jailpath是jail目录的路径名,user是运行守护进程的用户名,daemonname是提供服务的守护进程的路径名(jail内)。

已经设置了某些服务器来利用chroot jail。例如,可以设置DNS以便named运行在jail中,以及vsftpd FTP服务器可以为客户端自动启动chroot jail。

4、安全性考虑

有些服务需要由具有root权限的用户或进程来运行,但一旦启动就释放其root权限(例如Apache、Procmail和vsftpd)。如果运行这样的服务,不必使用uchroot或者把su或sudo放入jail内。

以root权限运行的进程有可能从chroot jail退出。出于这个原因,在启动一个运行在jail内的程序之前,应该降低特权。此外,慎重对待jail内允许的setuid二进制文件—其中的安全漏洞可能会危及jail的安全。此外,确保该用户不能访问他上传到jail的可执行文件。