BACK

CREDIT

POC or EXPLOIT

REFERENCES






Sun, 18 Mar 2007

Summary

When the mb_parse_str() function, which is the multibyte variant of the parse_str() function, is called with only one parameter and is interrupted by for example a memory_limit violation the register_globals directive will get internally activated during the process and not deactivated. Therefore the Apache child will have register_globals activated in a way undetectable for PHP code.

This vulnerability is similar to the one disclosed by the Hardened-PHP Project in 2005 in the non multibyte parse_str() function.

Affected versions

Affected are PHP 4 <= 4.4.6 and PHP 5 <= 5.2.1

Detailed information

When the mb_parse_str() function is called with only one parameter it will internally activate register_globals. This activation is performed by directly manipulating the flag in memory and not taking into account memory_limit interruptions.

    if (info->force_register_globals) {
        prev_rg_state = PG(register_globals);
        PG(register_globals) = 1;
    }

This is quite dangerous, because if a script termination occurs until the flag is reset it will not be automatically restored. This can happen for example due to a memory_limit violation as demonstrated by the attached exploit.

This kind of register_globals activation is more dangerous than having register_globals activated in the php.ini configuration because the script will believe it runs with register_globals being deactivated while in reality it stays activated until the Apache child dies. Possible safeguards against register_globals in the script will most probably not be executed.

Proof of concept, exploit or instructions to reproduce

The attached exploit will allocate memory until the memory_limit is nearly reached. It will then call mb_parse_str() which results in a memory_limit violation while register_globals is internally activated.

To test for this vulnerability you need to setup an Apache server with atleast two virtual hosts and globally deactivate register_globals. You can then send the following requests.

GET /rg.php?global_var=injected_global_var HTTP/1.1
Host: mopb-test
Connection: Keep-Alive
Keep-Alive: 100

HTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:10 GMT
Server: Apache
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

12
string(0) ""
NULL

0
GET /MOPB-26-2007.php HTTP/1.1
Host: other-vhost
Connection: Keep-Alive
Keep-Alive: 100

HTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:10 GMT
Server: Apache
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

b4
<br />
<b>Fatal error</b>:  Allowed memory size of 482344960 bytes exhausted (tried to allocate 164001 
bytes) in <b>/var/www/other-vhost/MOPB-26-2007.php</b>on line <b>29</b><br />

0
GET /rg.php?global_var=injected_global_var HTTP/1.1
Host: mopb-test
Connection: Close

HTTP/1.1 200 OK
Date: Sun, 18 Mar 2007 13:33:14 GMT
Server: Apache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

2e
string(0) ""
string(19) "injected_global_var"

0

In this case the rg.php script just outputs the current value of ini_get("register_globals"); and the content of the global variable global_var. It should be obvious that the global variable is set in the last attempt, although the ini_get() call says that register_globals is deactivated.

Notes

The danger of this vulnerability is that nowadays many scripts try to protect themself against register_globals being activated by warning the user that it is activated, by refusing to work while it is activated or by trying to undo it, when it is activated.

However when this vulnerability is exploited the script is unable to realise that register_globals is activated (without dirty tricks) and therefore believes it runs with register_globals deactivated.

In a shared environment (that uses mod_php) this allows a malicious user to attack other VHOSTS as if register_globals was activated. In a single user environment the usage of mb_parse_str() with only one parameter can be abused to remotely activate register_globals for further attacks.