7

CVE-2020-7468:FreeBSD ftpd chroot本地提权漏洞分析

 3 years ago
source link: https://www.freebuf.com/vuls/258825.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Z3eYFrV.jpg!mobile

漏洞概述

在今年7月,我们从一位匿名研究员那里收到了FreeBSD中的一个本地权限提升漏洞的相关信息,即一个存在于FreeBSD的文件传输协议守护进程( ftpd )中的漏洞。ftpd提供了一个名为 ftpchroot 的功能,旨在限制经过身份验证的用户对文件系统的访问。这个特性是使用“chroot”系统调用实现的,这是一种通常称为“chroot jail”的安全技术,chroot jail可以将进程限制在文件系统的受限部分来运行。但是,在该漏洞的帮助下,攻击者实际上可以利用这种被“囚禁”的状态来进行各种非法操作,将其权限从受限制的FTP帐户提升为“root”权限,并允许攻击者能够在目标系统上执行任意代码。此漏洞在FreeBSD FTP守护程序中存在了很长时间,最早可以追溯到FreeBSD 6.3版本。目前,这个漏洞被标记为了 CVE-2020-7468/ZDI-20-1431 ,相关 漏洞补丁 已于今年9月份正式发布。

漏洞分析

这个漏洞存在的根本原因是freebsd/libexec/ftpd/ftpd.c的chroot()函数在进行业务处理时存在设计缺陷。下面给出的是存在漏洞的函数简化版本:

void pass(char *passwd)

{

// ...

        if (guest || dochroot) {

// ...

                /*

                 * Finally, do chroot()

                 */

                if (chroot(chrootdir) < 0) {

                        reply(550, "Can't change root.");

                        goto bad;

                }

                __FreeBSD_libc_enter_restricted_mode();

        } else  /* real user w/o chroot */

                homedir = pw->pw_dir;

// ...

        if (chdir(homedir) < 0) {

                if (guest || dochroot) {

                        reply(550, "Can't change to base directory.");

                        goto bad;

                } else {

// ...

                }

// ...

bad:

        /* Forget all about it... */

#ifdef  LOGIN_CAP

        login_close(lc);

#endif

        if (residue)

                free(residue);

        end_login();

}

如果 FTP 用户试图登录并被配置为限制在/etc/ftpchroot中的chroot jail,那么ftpd将调用chroot和chdir系统调用)。如果chdir系统调用失败,则代码将跳转到标签bad处。在这种情况下,ftpd仍然会等待新的登录,但连接已锁定在chroot jail内。此时,将导致连接上的下次登录尝试会引发错误行为。

漏洞利用

为了强制chdir系统调用在登录过程中失效,攻击者可使用命令 chmod 0 在主目录上更改权限。另外,攻击者将会上传和主页目录相关的文件“etc/spwd.db”。该文件是修改过的常规 FreeBSD 系统(包含root用户的已知密码)的密码数据库。chdir调用失败后,ftpd会被锁定在chroot jail中,以便所有后续的文件系统访问都会跟用户主目录相关,而不是真实的文件系统root路径。这样一来,当对后续登录进行认证时,ftpd读取攻击者的spwd.db而不是存储在文件系统真实root目录下的/etc/spwd.db。此时,攻击者就可以通过已知密码以root身份进行登录了。

下一步,攻击者需要上传/etc/pam.d/ftpd和/usr/lib/pam_opie.so.5。第一个文件可以让ftpd在登录过程中加载多个动态库,其中就包括这第二个文件。第二个文件旨在通过已获得的root权限来突破chroot jail并执行反向Shell。接下来,攻击者就能够以root权限来执行任意代码了。

漏洞利用步骤大致如下:

  • 通过受限的 FTP 账户登录。
  • 上传包含已知root密码的etc/spwd.db。
  • 执行“chmod 0”。
  • 再次以受限的 FTP 账户登录。在登录过程中,chdir执行失败,导致ftpd进程在chroot jail中被锁定。
  • 通过已知密码以 root 身份登录。
  • 上传/etc/pam.d/ftpd和/usr/lib/pam_opie.so.5,后者包含一个反向Shell。
  • 再次以受限 FTP 账户身份登录。和之前一样,chdir执行失败,导致ftpd进程在chroot jail中被锁定。
  • 通过已知密码以 root 身份登录。ftpd执行该反向Shell。

漏洞修复

为解决这个问题,FreeBSD对其功能实现代码进行了修改,如果chdir系统调用失败的话,则ftpd将会立刻断开连接:

void fatalerror(char *s)

{

        reply(451, "Error in server: %s", s);

        reply(221, "Closing connection due to server error.");

        dologout(0);

        /* NOTREACHED */

}

 

void pass(char *passwd)

{

// ...

        if (chdir(homedir) < 0) {

                if (guest || dochroot) {

                        fatalerror("Can't change to base directory.");

                } else {

//...

}

总结

这个漏洞是一个逻辑提权漏洞,因此它的稳定性非常强,这个漏洞跟九月份发布的FreeBSD 内核提权漏洞( CVE-2020-7460 )也是不一样的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK