0x00 前言
2016-10-03号,在exploit-db上出了Apache Tomcat 8/7/6 (Debian-Based Distros) - Privilege Escalation,也就是CVE-2016-1240 ,基于Debain的Apache Tomcat权限提升,攻击者在获取到tomcatN的shell之后,可以利用Debain系统在使用package安装的tomcat的启动脚本/etc/init.d/tomcatN
中的缺陷,SUID的特性和对geteuid
函数的覆盖,得到可使用的rootshell,达到提升权限的目的。本文将会对exploit脚本进行分析,并搭建环境加以复现
0x01 脚本缺陷
以tomcat7为例,在init脚本/etc/init.d/tomcat7
中
这段脚本主要是root用户在touch了catalina.out文件后,再将文件的所有者改为tomcat7的用户。脚本看似没有什么问题,但是cve的作者提出这么一个场景:当攻击者以tomcat的身份访问服务器的时候(比如说拿下了tomcat服务器的webshell),他就可以将catalina.out替换成指向任意文件的动态链接(软链接),在服务器重启之后(当然,是需要创造这种机会的),init脚本再次以root权限运行,将动态链接所指向的文件的所有者改成了tomcat用户,这样攻击者就可以读写服务器上的任意文件了。正如长亭科技的文章所分析的,作者并不甘于单纯的文件操作,而是利用SUID和/etc/ld.so.preload的方法获取到root权限的shell
0x02 环境搭建
老生常谈的系统更新就不赘述了,我这里使用Ununtu14.04虚拟机和tomcat7进行测试。问题出现于package中的初始化脚本中,而脚本则是来源于安装时的deb包,虽然可以通过apt-get直接安装tomcat7,但是debian官方及时进行了修复,我们得去下载历史的deb包来安装服务复现环境。在snapshot上可以找到历史的deb包,这里我选择安装tomcat 7.0.14-1,过程如下
都是一些常规的依赖安装,安装好后cat -n /etc/init.d/tomcat7 | less
就可看到存在缺陷的脚本片段了,但是在尝试启动tomcat的时候会报错* no JDK found - please set JAVA_HOME
,起来也要安装jdk环境sudo apt-get install --no-install-recommends openjdk-7-jdk
,再根据这里在/etc/default/tomcat7
中加入JAVA_HOME
的环境变量JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
,最后再重启一下tomcat就成功搭建起来了
服务起来后可以尝试一下长亭文章中的利用缺陷操作系统文件,这里就不多说了
0x03 脚本分析
为了方便说明,请允许我先把脚本贴过来
首先是49到66行的cleanexit和ctrl_c函数负责在退出后环境的清理,直至原始的状态。从77到81行看出脚本接受catalina.out的路径和模式的选择,模式分为deferred和active模式,默认为active。83到97行则是检查是否为tomcat用户运行地脚本和对应路径的catalina.out文件是否存在。
如果设置了deferred参数则会进入105到117行的逻辑,该模式就是被动等待。首先删除catalina.out文件,再建立/etc/default/locale的软链接到catalina.out,等tomcat或系统重启后tomcat用户就可以变成/etc/default/locale的所有者,即可写入任意的命令,最后结合/etc/cron.daily/tomcatN中的计划任务的配置,在每天早上6:25利用root权限来执行写入的任意命令。
如果等不了的话可以进入active模式,121到155行是前期利用环境的准备。先说一下作者整体的利用思路:借助init脚本中的缺陷把/etc/ld.so.preload的所有者改为tomcat,而/etc/ld.so.preload和LD_PRELOAD的作用一样,我们将自定义的函数编译成so文件后再写入/etc/ld.so.preload中,即可完成对标准C函数的覆盖,进而实现我们想要的效果。
147到149行是先copy一个后面shell到/tmp目录下,不过权限还比较低。151到155行则是检查/etc/ld.so.preload存在,为了安全起见存在的话退出脚本。122到145行在编译/tmp/privesclib.so文件,覆盖掉标准的geteuid函数,在函数内部会检测程序的euid,当euid为0时也就是root权限运行时会将之前的后面shell改为root用户和root组,更改后门shell的权限并设置SUID,最后删除/etc/ld.so.preload文件。
这里需要补充一下SUID的知识:linux内核主要是根据euid和egid来确定进程对资源的访问权限的,当linux的二进制文件执行时,会使用geteuid函数来获得euid。一个进程如果没有SUID或SGID位,则euid=uid egid=gid;如果一个程序设置了SUID,则euid和egid变成被运行的程序的所有者的uid和gid。也就是说其他人运行了设置有SUID的程序,则该程序会以程序所有者的身份被运行,我们的passwd程序就是这样的一个例子。(更多相关参考可以看这里)如果成功执行了我们覆盖的geteuid函数,后门shell的权限则会变成rws,当任何人运行该shell时,shell都会以root的身份被执行,我们的权限也就提升了。
下面就需要创造调用覆盖函数的机会。158到174行利用缺陷,在等待tomcat或主机重启后将/etc/ld.so.preload的所有者改为tomcat用户,然后向其中写入我们之前编译的/tmp/privesclib.so文件。最后调用sudo程序,因为sudo的权限为rws所有者为root,所以在调用过程中euid是为0的,我们的覆盖函数就发挥的作用,更改后门shell的权限。187到203行则是检测后门shell的权限是否更改成功并且调用,这样整个权限提升的过程就完成了。
0x04 漏洞复现
直接下载作者提供的脚本还不能用,需要编辑一下,而且编译环境需要gcc,具体如下:
为了模拟攻击者拿到了tomcat的shell和创造机会使tomcat重启,我将tomcat的shell设置了一下,并且使用sleep将重启服务后置几秒然后运行攻击脚本,具体如下:
CVE-2016-5425
10月10号freebuf上有一篇文章通报本文所述的漏洞,然后就有人评论说“还是我fedora小白鼠闷声发大财.”。然而CVE的作者也在10月10号提交了Apache Tomcat 8/7/6 (RedHat-Based Distros) - Privilege Escalation,也就是CVE-2016-5425,影响所有基于RedHat的发行版本,当然fedora也包含在内,想一想也是蛮搞笑的单纯。这个漏洞依旧是安装包中文件权限设置不当,使得tomcat组对/usr/lib/tmpfiles.d/tomcat.conf有写权限,因此可对该文件写入相应的指令,一旦主机重启就会以root权限执行写入的命令,即可反弹shell也可留下后面,更多的内容见这里。
这两次CVE的成功都是建立在主机重启之后,在主机down掉时我们该去排查相应的原因,而不是盲目的重启。当我们的生活因为某种原因down掉时,是不是应该去反省一下自己寻找原因,而不是随意排解后的无脑前行。你愿意被生活exploit吗?