Analysis of the RoundCube html2text Vulnerability
RoundCube Webmail Project (http://roundcube.net) is a popular, AJAX enabled web based email client. RoundCube utilizes a user friendly interface and allows users to access IMAP email via their web browser. RoundCube is written in PHP with a MySQL database and utilizes XHTML and CSS. RoundCube's intuitive interface and advanced UI functionality have made it a popular open source webmail client. Unfortunately RoundCube versions 0.2-3 beta and 0.2-1 alpha were found to contain a critical flaw that allowed remote attackers to execute arbitrary code with the privileges of the web server (CVE-2008-5619). This article examines the root causes of that flaw and it's implications.
RoundCube utilized the html2text function by Jon Abernathy (jon@chuggnutt.com) that contains a critical flaw which enables input to be parsed and executed by the PHP engine. This means that malicious input containing specially crafted input can cause the web server to execute PHP code. This flaw is introduced with the 'e' flag used in the preg_replace() function in PHP. Using the 'e' in a regular expression allows for PHP to do processing on input. For instance if we wanted to change a lower case string to an upper case one we could use:
<?php print preg_replace('/(.*)/e', 'strtoupper("\\1")', 'test'); ?>
This usage of the preg_replace allows a programmer to use PHP's strtoupper() function to process the input string. This enables dangerous consequences though if the user is able to pass in strings that include PHP commands.
The tricky part to this exploitation is masking the PHP commands as variables in order to execute them. In normal operation the preg_replace will allow you to pass in variables and perform substitution on them. For instance:
<?php $foo = 'bar'; print preg_replace('/(.*)/e', 'strtoupper("\\1")', '$foo'); ?>
Will print out "BAR" as expected. However, using:
<?php $foo = 'bar'; print preg_replace('/(.*)/e', 'strtoupper("\\1")', 'phpinfo()'); ?>
will simply print out "PHPINFO()". In order to get the PHP engine to interpret the command we have to assign it to a variable. Normally this is possible by simply prepending a '$' delimiter and utilizing the PHP curly bracket notation. Thus:
<?php print ${phpinfo()}; ?>
Will dutifully print out the phpinfo() command output. If we try to pass this to our original preg_replace() function, however, some escaping does occur so you'll notice that:
<?php print preg_replace('/(.*)/e', 'strtoupper("\\1")', '${phpinfo()}'); ?>
Produces the following error:
[Tue Jan 13 09:24:48 2009] [error] [client 192.168.0.50] PHP Fatal error: preg_replace() [function.preg-replace]: Failed evaluating code: \nstrtoupper("${phpinfo()}") in /var/www/html/exploit.php on line 22
In order to bypass this error an extra set of curly braces can be included, properly escaping the command for evaluation. The updated code:
<?php print preg_replace('/(.*)/e', 'strtoupper("\\1")', '{${phpinfo()}}'); ?>
Will produce the proper output. In the case of RoundCube this flaw is introduced in line 6 of bin/html2text.sh:
$converter = new html2text(html_entity_decode($HTTP_RAW_POST_DATA, ENT_COMPAT, 'UTF-8'));
Which passes raw post data directly to the html2text function found in program/lib/html2text.php. By passing proper variables as described in Jacobo Avariento Gimeno's Milw0rm post, you can easily pass PHP functions directly to this script. As of this writing exploits have been observed in the wild.
Conclusion
While RoundCube is likely the first high profile target of this exploit, it likely won't be the last. Any program using Jon Abernathy's html2text functionality could be vulnerable. Additionally, other programs which use PHP's preg_replace() function with the 'e' modifier could likely contains similar vulnerabilities. It is important that careful code audit be utilized to spot and fix these flaws before they are discovered by malicious attackers. Of course, exploiting flaws like this allow attackers to run code with the privilege of the web server. This is an extremely common threat vector and it is for this reason that it is imperative to either limit the web server's access to the file system (such as through a chroot jail) and/or carefully monitor the behavior of the web server. It is common for attacker to upload and execute files via exploits such as the one described in this article, so limiting where the web server can write files is extremely useful in preventing successful exploitation.