Bypassing disabled system functions

In this article, we examine the specific code of an exploit to bypass disabled system functions, including the parameters of the imap_oprn function, the IMAP server types and SSH connection, and the -oProxyCommand option. You will also learn some ways to protect yourself against this bypass method.

Bypassing disabled system functions

Imagine that you’ve discovered an unrestricted file upload vulnerability and have uploaded a web shell to the server. Or maybe you have a payload that allows you to execute commands on the system through a local file inclusion (LFI) or remote file inclusion (RFI) vulnerability.

When you execute the command that’s supposed to call system functions on the server side, you’re greeted by a surprise warning which states that you’re not allowed to execute the function because it’s disabled.

Warning: system() has been disabled for security reasons in /var/www/html/shell.php on line 6

The disable_functions directive in the php.ini configuration file allows you to disable certain PHP functions. One of the suggested hardening practices is to disable functions such as system, exec, shell_exec, passthru, by using the disable_functions directive to prevent an attacker from executing system commands. However, a user named Twoster in the Russian Antichat forum announced a new bypass method to this security mechanism. In this blog post, we discuss the technical details of the bypass.

The exploit code of the bypass

Last week, Anton Lopanitsyn shared the exploit code on Github after the announcement on the Antichat forum. In the exploit code, it’s clear that the bypass relies on the imap_open() function, which is activated after the installation of the imap extension on PHP.

# CRLF (c)
# echo '1234567890'>/tmp/test0001

$server = "x -oProxyCommand=echo\tZWNobyAnMTIzNDU2Nzg5MCc+L3RtcC90ZXN0MDAwMQo=|base64\t-d|sh}";

imap_open('{'.$server.':143/imap}INBOX', '', '') or die("\n\nError: ".imap_last_error());

The imap_open() function doesn’t readily exist in the PHP core. It’s a wrapper for imapd, designed by the researchers at the University of Washington. As stated above, PHP will have the imap_open() function defined only after you’ve installed the IMAP PHP extension. Let’s analyze each component in the exploit code.

The parameters of the imap_open function

We’re going to take a closer look at the mailbox parameter the function takes, to understand how the imap_open function works in the exploit. Here is the syntax of the function:

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

The value for the mailbox parameter consists of the server name and the mailbox file path on the server. The name INBOX stands for the current user’s personal mailbox. This is how you set the mailbox parameter:

$mbox = imap_open ("{localhost:993/PROTOCOL/FLAG}INBOX", "user_id", "password");

Between the brackets, you can see the server name or IP address, the port number (after the colon) and the protocol name. After the protocol name, the user can choose to set a flag as the third parameter.

The warning in the official documentation of PHP about setting up the imap_open parameters is crucial.

This warning states that unless enable_insecure_rsh is disabled, the user data should not be directly transmitted to the mailbox parameter.

This warning states that unless enable_insecure_rsh is disabled, the user data should not be directly transmitted to the mailbox parameter. Let’s take a look at  how the IMAP extension works to understand what the enable_insecure_rsh configuration option does, and why the warning prompts users to disable it.

The IMAP server types and SSH connection

There are two Unix-based IMAP servers that are widely used. One is imapd, developed by the University of Washington, and the other is the IMAP server developed by Cyrus.

Cyrus stores the user emails in a built-in database. So, accessing Cyrus is only possible through the IMAP protocol. This is why when Cyrus is in use, there are no connections between user accounts on the Unix system on which the IMAP is installed and the IMAP accounts.

On the other hand, imapd stores the emails in files owned by the mail users on the Unix system, such as /var/spool/mail. User accounts and access privileges on imapd are directly related to the Unix server. If your mails are stored in a spool file to which you have authorization, you can login through SSH and verify your privileges on the files.

There’s no need for the entire procedure to establish an IMAP connection when there’s SSH. The imap_open function initially establishes an SSH connection and, if authorized, proceeds without an IMAP connection. This is called the IMAP preauthenticated mode. The warning given for passing the value in the mailbox parameter is based on this. The mailbox value will be passed on to the SSH command as a parameter while setting up an SSH connection.

Before the secure SSH protocol was widely used, there was a protocol called rsh. However, it’s quite insecure by default, doesn’t use encryption and shouldn’t be used for connections outside (and even inside) the local network. The imap.enable_insecure_rsh configuration option deactivates both rsh and ssh for preauthentication.

The -oProxyCommand option in the exploit

One of the many parameters the SSH command uses is the -o parameter, which allows you to set the options available for use during the connection. ProxyCommand is one of the options that can be set right before commencing the SSH connection. For example:

ssh -oProxyCommand="touch tmp.txt" localhost

When you execute this command, you’ll realize that the tmp.txt file will be created even if an SSH connection is not made to localhost.

The -oProxyCommand in the Exploit

Due to all the components in the exploit code, a system which has functions such as system and passthru disabled will still be vulnerable to executing commands in RFI or LFI vulnerabilities.

Additional measures against the bypass

There are two ways to protect yourself against the dangers of the imap PHP extension. The first is by checking for any special characters (such as forward slashes) whenever you pass user input to imap_open, which would prevent a remote code execution vulnerability. We stated above that you can use certain flags within the mailbox parameter. The /norsh flag is one of these and you should set it in order to disable the IMAP preauthenticated mode.

In addition, an effective defence against the disable_functions bypass is to disable the imap.enable_insecure_rsh option by giving a ‘0’ value in the php.ini file. However, in PHP version 5, this option isn’t available, so you should think twice whether you need the imap extension and whether you should add imap_open to your list of disabled functions.

Article written by Netsparker security researchers:

Ziyahan Albeniz
Sven Morgenroth
Umran Yildirimkaya

Sven Morgenroth

About the Author

Sven Morgenroth - Senior Security Engineer