Chroot相关
一:定义
chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 `/`,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 `/` 位置。
二:背景
以前,Unix/Linux上的daemon都是以root权限启动的。当时,这似乎是一件理所当然的事情,因为像Apache这样的服务器软件需要绑定到"众所周知"的端口上(小于1024)来监听HTTP请求,而root是惟一有这种权限的用户。
但是,随着攻击者活动的日益频繁,尤其是缓冲区溢出漏洞数量的激增,使服务器安全受到了更大的威胁。一旦某个网络服务存在漏洞,攻击者就能够访问并控制整个系统。因此,为了减缓这种攻击所带来的负面影响,现在服务器软件通常设计为以root权限启动,然后服务器进程自行放弃root,再以某个低权限的系统账号来运行进程。这种方式的好处在于一旦该服务被攻击者利用漏洞入侵,由于进程权限很低,攻击者得到的访问权限又是基于这个较低权限的,对系统造成的危害比以前减轻了许多。
有些攻击者会试图找到系统其它的漏洞来提升权限,直至达到root。由于本地安全性远低于远程安全保护,因此攻击者很有可能在系统中找到可以提升权限的东西。即使没有找到本地漏洞,攻击者也可能会造成其它损害,如删除文件、涂改主页等。
为了进一步提高系统安全性,Linux内核引入了chroot机制。chroot是内核中的一个系统调用,软件可以通过调用库函数chroot,来更改某个进程所能见到的根目录。比如,Apache软件安装在/usr/local/httpd/目录下,以root用户(或具有相同权限的其它账号)启动Apache,这个root权限的父进程会派生数个以nobody权限运行的子进程,具体情况取决于个人设置。父进程监听请求自80端口的tcp数据流,然后根据内部算法将这个请求分配给某个子进程来处理。这时Apache子进程所处的目录继承自父进程,即/usr/local/httpd/。但是,一旦目录权限设定失误,被攻击的Apache子进程可以访问/usr/local、/usr、/tmp,甚至整个文件系统,因为Apache进程所处的根目录仍是整个文件系统的根。如果能够利用chroot将Apache限制在/usr/local/httpd/,那么,Apache所能存取的文件都是/usr/local/httpd/下的文件或其子目录下的文件。创建chroot"监牢"的作用就是将进程权限限制在文件系统目录树中的某一子树中。
三:作用
在经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,如果一个进程/命令运行在一个不能访问外部根目录文件的已修改环境中,这种修改环境通常被称为"监禁目录"(jail)或是"chroot 监禁",只有特权进程和根用户才能使用 chroot 命令,它带来的好处大致有以下几个:
1.增加了系统的安全性,限制了用户的权力
在经过 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性,这个一般是在登录 (login) 前使用 chroot,以此达到用户不能访问一些特定的文件。
2.建立一个与原系统隔离的系统目录结构,方便用户的开发测试
使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构,在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发。
3.切换系统的根目录位置,引导 Linux 系统启动以及急救系统等。
chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init,另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统。
4.限制chrooter所能执行的程序,如SetUid,或是会造成Load 的 Compiler等等。
5.防止chrooter存取某些特定文档,如/etc/passwd。
6.防止入侵者/bin/rm -rf /。
7.将特权分配给无特权的进程,例如 Web 服务或 DNS 服务。
8.不使程序或系统崩溃下,运行旧程序或 ABI 兼容的程序。
9.系统恢复。
10.重新安装引导装载程序,例如 Grub 或 Lilo。
11.密码找回,重置一个已丢失的密码等。
四:原理
使用者无论是从console或是telnet进入,都必须执行/usr/bin/login来决定是否能进入系统,而login所做的动作大致是:
(1)打印出login的提示符号,等待使用者输入密码。
(2)检查密码是否正确,错误的话回到(1)。
(3)正确的话以setuid()来改变身份为login_user。
(4)以exec()执行user的shell。
因此我们必须先修改/usr/bin/login的source code,让login在(2)到(3)的中间执行chroot($CHROOT_PATH)的动作,已达到CHROOT的目的,并以修改过的login替代原先的/usr/bin/login。
(5)稍微好一点的方法必须在做chroot()之前检查login user的group,如果有某个特定的group(如chrootgrp)才执行chroot(),不然所有的人都会被chroot了。
五:实例
5.1 语法
#chroot new_root [command...]
#chroot option
5.2 环境配置
由于在经过 chroot 之后,系统读取到的 bin/ 等与系统相关目录将不再是旧系统根目录下的,而是切换后新根下的目录结构和文件,因此我们有必要准备一些目录结构以及必要的文件。
1.设置好监狱路径及子目录
#J=$HOME/jail
#mkdir -p $J
#mkdir -p $J{etc,sbin,usr/lib,/usr/bin,usr/sbin,home,bin,lib64,lib}
#cd $J
2.拷贝可执行文件
#cp -v /bin/{bash,ls} $J/bin
3.拷贝库文件
#list=”$(ldd /bin/{ls,bash} | egrep -o ‘/lib.*.\.[0-9]’) ”
#for i in $list:do cp -v “$i” “${J}${i}”; done
5.3使用
#chroot $J /bin/bash
改变了根目录的 bash 和 ls 程序现在被监禁在$HOME/$J这个特殊目录中,而且不能再访问外部的目录树,这个目录可以看做是它们的"/"(root)目录。如果配置正确的话,这会极大增强安全性。
5.4 退出
#exit
六:编写一个chroot
chroot 的编写涉及了2个函数,chroot() 以及 chdir(),它们都包含在 unistd.h 头文件中。chroot() 将切换参数 path 所指位置为根目录 (/),chdir() 用来将当前的工作目录改变成以参数path 所指的目录。
以此我们可以编写一个非常粗略的 `chroot`。