Ubuntu 10.04 LTS
wget https://github.com/mudongliang/source-packages/raw/master/CVE-2007-1286/php-4.4.4.tar.gz
tar -xvf php-4.4.4.tar.gz
cd php-4.4.4
./configure
make
./sapi/cli/php poc.php
MOPB-04-2007:PHP 4 unserialize() ZVAL Reference Counter Overflow
PHP ZVAL Reference Counter Integer Overflow Vulnerability
PHP 4.4.4 - 'Unserialize()' ZVAL Reference Counter Overflow (PoC)
Note: remember to remove or comment die("REMOVE THIS LINE");
In PHP 4 the ZVAL structure that internally describes a variable looks like this
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uchar type; /* active type */
zend_uchar is_ref;
zend_ushort refcount;
};
When this structure was designed the reference counter was made 16 bit wide so that the whole structure is exactly 8 bytes long (on 32bit systems). In PHP 5 this field is meanwhile 32 bit wide, because 16 bit can overflow too easily and PHP does not have an internal protection against overflows of the reference counter. Unfortunately for PHP 4 this means code like this will overflow the counter and will trigger a double destruction of the variable on script end.
$var = "POC";
for ($i = 0; $i < 0x10001; $i++) {
$arr[] = &$var;
}
An attacker can exploit this by overflowing the reference counter. Then he deletes one of the references which will result in the variable being destructed, because PHP knows only the lower 16 bit of the real refcount which is 1 in that case. When the variable is freed he carefully crafts some other variables that then get allocated into the same memory. He then frees all the other references which will trigger another destruction at refcount 1.