Ubuntu下借助chroot搭建系统级隔离的FTP服务


(其实这是一个系统安全课程的实验,大多数流行的ftp服务端实现均已内置了基于chroot的目录隔离以及低权限启动daemon进程的安全措施,本实验选择ftp服务纯属偶然或者老师觉得比较方便,其实更常见的应用是搭建chroot隔离的HTTP、nodejs等web应用)

chroot提供了一种系统级的文件系统隔离方案,能够将一个进程及其所有子进程所能访问的文件系统范围限制到某个目录树内。由chroot运行的程序无法访问到文件系统中位于它的根目录以外的任意文件,这由命令的名字“change root”可以看出。

这种严格而有效的限制是基于kernel所提供的同名系统调用实现的,用户在终端中所执行的命令chroot只是对这个系统调用的简单包装,它可以帮助用户启动一个chrooted的进程。借助该命令,用户可以方便地将某个程序“隔离”到某个目录下,假如有攻击者获取了该进程的控制权,它仍不能(其实不一定!)逃逸出这个目录,攻击者无法访问其它敏感数据、从而减小了攻击的威胁面。因此,被限制后的程序的活动范围又被称作“监狱”。

0x1 环境搭建

(1) 安装vsftpd

前面已经说过,chroot之后的进程只能看到某个目录下的文件、并将该目录视作它的根目录。这就意味着,该进程所需要的所有动态链接库、动态链接器、配置文件等依赖文件,都需要存放在该目录(指chroot系统调用所指定的目录)下。

本实验以vsftpd程序为例。该程序是一个易用的FTP服务端程序,在Ubuntu上可使用命令sudo apt-get install vsftpd进行安装。

安装后,使用sudo service vsftpd start启动FTP服务器。这时候,你应该可以在浏览器中使用ftp://localhost访问本机的FTP服务器了,这说明vsftpd安装无误。

(2) 配置vsftpd

编辑文件/etc/vsftpd.conf,允许匿名登录、解除vsftpd对用户根目录的限制(以便体现出我们手动chroot的效果),重启vsftpd服务,检查配置是否生效。这时,用户可以通过访问“..”来逃逸家目录。

(3) 配置监狱环境

本实验最难的环节来了:由于我们要在“监狱”内配置vsftpd,这需要我们把vsftpd所需的所有依赖均安装妥当。

(3.1) 用户登录信息

vsftpd会使用linux系统集成的身份验证机制进行登录,所以需要将/etc/passwd文件拷贝到监狱内。(在监狱目录下执行命令cp /path/to/file ./ --parent,下同)

(3.2) vsftpd的二进制依赖

vsftpd的二进制文件位于/usr/sbin/vsftpd,需要将其拷贝到监狱内,并将其所使用的动态链接库全部拷贝到监狱内。

(3.3) 其它系统级依赖

vsftpd使用getpwnam函数获取系统级用户的信息,这个函数又依赖于nsswitch……我解决这一依赖问题的方法是:把/lib全部拷贝到监狱内。这一方案的副作用在于,浪费了一些磁盘空间,同时有泄露敏感二进制文件的可能(私有商业代码编译的私有库)。(这一方案也顺便解决了监狱内bash输入命令时退格键功能异常的奇怪现象,推测是少了某些二进制库,虽然bash能启动,但是没有报错)

题外话:至于我为啥发现vsftpd依赖getpwnam,是因为在配置好其他依赖后,运行vsftpd报错找不到用户(我指定的是nobody),然而这个用户一定存在!于是我就把错误消息贴到vsftpd代码库里搜索,找到了错误来源:

twoprocess.c


    const struct vsf_sysutil_user* p_user = str_getpwnam(p_user_str);

    if (p_user == 0)

    {

        die2("cannot locate user entry:", str_getbuf(p_user_str));

    }

secutil.c


    p_user = str_getpwnam(p_user_str);

    if (p_user == 0)

    {

        die2("cannot locate user entry:", str_getbuf(p_user_str));

    }

错误来自str_getpwnam函数返回0,继续追溯,这个函数调用了getpwnam,这是一个系统库API,继续追溯,发现是缺少一些lib,全部拷贝过去,问题解决。

0x2 效果展示

现在,用户虽然能够逃出他的家目录,但是不能逃出监狱目录,这表示chroot已经生效。

0x3 扩展阅读

How To Set Up vsftpd for Anonymous Downloads on Ubuntu 16.04

浅析在FreeBSD中建立chroot的FTP服务 - 王朝网络移动版

nginx won’t start: getpwnam(“nginx”) failed in /etc/nginx/nginx.conf:5

详解ftp环境配置解决方案(vsftpd)

vsftpd配置文件参数详解

VSFTPD——CHROOT