Some facts about the PHPList vulnerability and the phpbb.com hack
February 6th, 2009 | by Stefan Esser |A few days ago phpbb.com was hacked through a super-globals-overwrite vulnerability in PHPList that was used by an attacker for a local file inclusion exploit. Details about the whole attack, written down by someone who claims to be the attacker, can be read here. From the explanation it seems that the PHP installation on phpbb.com was more or less a default one that was not hardened against attacks at all, but I will get into this later.
First I want to shed some light on the super-globals-overwrite vulnerability in PHPList that was wrongly attributed a local file inclusion vulnerability in so many places (including the PHPList announcement). Responsible for the attack is the following code in admin/index.php:
if (!ini_get("register_globals") || ini_get("register_globals") == "off") { # fix register globals, for now, should be phased out gradually # sure, this gets around the entire reason that register globals # should be off, but going through three years of code takes a long time.... foreach ($_REQUEST as $key => $val) { $$key = $val; } } ... if (isset($_SERVER["ConfigFile"]) && is_file($_SERVER["ConfigFile"])) { print '<!-- using '.$_SERVER["ConfigFile"].'-->'."\n"; include $_SERVER["ConfigFile"]; }
This code will detect if register_globals is turned off (which is the default since PHP 4.2) and in that case emulate register_globals by globalising everything within the _REQUEST array. Code similar to this is used by many projects to emulate register_globals=on. Usually this is done as a quick hack to make software work when register_globals=off. The comment proves that this is also the case for PHPList.
The problem here is that the foreach loop above does not contain any kind of sanity check which allows attackers to overwrite all the super-global-variables (like GLOBALS, _SERVER, _ENV, …) by supplying new values for them through either the URL, the POST data or through the COOKIE. For the code above this also means an attacker can also overwrite the value of $_SERVER['ConfigFile'] from the outside. This gives the attacker full control over an include statement, which allows him to include arbitrary files.
Unfortunately the original exploit author, the PHPList team and many other people still believe that using is_file() or file_exists() around the file to include is enough to ensure that it is a local file. Therefore the original exploit and also the PHPList security announcement wrongly assume this is a local file inclusion problem. In reality however is_file() and file_exists() also work on PHP’s URL wrappers if the wrapper implements the stat() call. PHP’s HTTP(S)/DATA/PHP://INPUT URL wrappers do not support this. But since PHP 5.0 the FTP URL wrapper does support this and therefore _SERVER['ConfigFile'] allows a normal remote file inclusion through the FTP protocol.
More importantly neither the original exploit writer, nor the PHPList team or anyone else reporting about it have realised that the problem is bigger than _SERVER['ConfigFile'] and therefore it is not suprinsing that the fix by PHPList is just a hack that fixes a single exploit but not the problem.
if (isset($_REQUEST['_SERVER'])) { exit; }
This code does obviously protect the _SERVER variables only. All the other super-global-variables are still unprotected. Because of this it is still possible to perform LFI/RFI and SQL-Injection attacks against the latest PHPList release by just overwriting other super-globals.
Protection
This attack was only possible because the PHP installation of phpbb.com was not configured securely. Multiple applications on the same server should be isolated from each other. Activating open_basedir*, which is a simple PHP configuration option, would have been good enough to stop PHPList from including avatar files uploaded to the PHPBB installation. Additionally disabling allow_url_fopen/allow_url_include in combination with the is_file() check would have stopped a possible remote file inclusion attack. However SQL-Injection attacks would through the super-globals-overwrite would still be possible.
On the other hand there is a simple way to protect a server against super-globals-overwrite vulnerabilities: Just install the Suhosin PHP security extension. It will detect, log and stop this kind of super-globals-overwrite. If you ask me any admin installing a vanilla PHP without Suhosin patch and extension is careless anyway.
Attention
*open_basedir - don’t get me wrong - open_basedir is not secure when it comes to protect a server against a malicious users/PHP scripts, but it makes exploiting local file inclusion attacks a lot harder.





13 Responses to “Some facts about the PHPList vulnerability and the phpbb.com hack”
By George A. Theall on Feb 6, 2009 | Reply
Interestingly, the author was aware of the wrapper issue from a similar issue reported in December:
http://www.attrition.org/pipermail/vim/2008-December/002106.html
By Jace on Feb 6, 2009 | Reply
Frankly I’ve never felt very comfortable with phpList as a whole considering the user interface feels slapped onto some crude tool that is confusing and unintuitive. This exploit has confirmed my fears that the developers really could care less about their software and do “just enough” to make it functional. While I don’t pretend to be an expert coder, if you’re not going to do something well and barely skate by, you might as well just quit. If the developers react this way to a MAJOR exploit, I can only imagine how they handle little bugs (or don’t as it would seem).
By zmx on Feb 6, 2009 | Reply
Thanks for the very informative post Stefan.
Keep up the good work
By dt on Feb 8, 2009 | Reply
Nice article. However, you didn’t mention mod_security that adds an extra layer of protection against some attacks (like XSS and remote file inclusion for some scripts). Also, disabling all exec functions is a good security step.
Why open_basedir is not secure? I think is good to use it in conbination with all the other protections.
By Bertrand on Feb 9, 2009 | Reply
Thanks Stefan.
By Tom Sommer on Feb 9, 2009 | Reply
What other software would you recommend?
By Michiel on Feb 10, 2009 | Reply
Thanks for the heads up. I’ll get on the case as soon as I can. Ironically enough, the register globals hack is probably not even necessary any longer, and hasn’t been for quite some time. If you look further down the code, I reverse it, so that issues could be ironed out. I should have taken it out and have done this in the main source base now. After a bit of testing, I’ll release a version without it. The dev branch has been working without it for ages, but being a sole coder makes it very hard to restabilise it for public release.
By Betsy Buchanan on Feb 24, 2009 | Reply
Ifs, ands and buts it’s all good! To think that this could have and should have been avoided, what a mess. Interesting reading though.
Regards,
Betsy Buchanan