BACK

CREDIT

POC or EXPLOIT

REFERENCES






Thu, 29 Mar 2007

Summary

Whenever functions accept references (which all do in the default configuration) it is possible for a malicious user space error handler that interrupts the function to modify the function parameters after the function has already started executing. This might for example trick the function into accessing arbitrary memory addresses. The iptcembed() function is an example where this vulnerability class can be used to leak arbitrary heap memory to the attacker.

Affected versions

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

Detailed information

When the iptcembed() function is called it retrieves the three parameters and converts them into the expected format.

        if (zend_get_parameters_ex(3, &iptcdata, &jpeg_file, &spool_flag) == FAILURE) {
            WRONG_PARAM_COUNT;
        }
        convert_to_string_ex(iptcdata);
        convert_to_string_ex(jpeg_file);
        convert_to_long_ex(spool_flag);
        spool = Z_LVAL_PP(spool_flag);

Unfortunately the convert_to_* functions can trigger an error under certain conditions. For example when passing an array as jpeg_file or an object as spool_flag parameter. When this happens the user space error handler is able to first cast the variable that contains the iptcdata into an int and then set it to an arbitrary long value. This results in a ZVAL that when mistaken as string is the same length as the original string with a memory position at the address specified by the long value.

It should be obvious that this little trick allows leaking arbitrary memory blocks.

Proof of concept, exploit or instructions to reproduce

When the attached exploit is executed it will leak 256 bytes from address 0x08048000 to the caller. On usual Linux systems this contains the ELF header of the currently running main executable.

memdump
---------

00000000: 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 02 ELF.............
00000010: 00 03 00 01 00 00 00 d0 72 08 08 34 00 00 00 bc ........r..4....
00000020: 1d b7 00 00 00 00 00 34 00 20 00 08 00 28 00 26 .......4. ...(.&
00000030: 00 23 00 06 00 00 00 34 00 00 00 34 80 04 08 34 .#.....4...4...4
00000040: 80 04 08 00 01 00 00 00 01 00 00 05 00 00 00 04 ................
00000050: 00 00 00 03 00 00 00 34 01 00 00 34 81 04 08 34 .......4...4...4
00000060: 81 04 08 13 00 00 00 13 00 00 00 04 00 00 00 01 ................
00000070: 00 00 00 01 00 00 00 00 00 00 00 00 80 04 08 00 ................
00000080: 80 04 08 60 af 3a 00 60 af 3a 00 05 00 00 00 00 ...`.:.`.:......
00000090: 10 00 00 01 00 00 00 00 b0 3a 00 00 30 3f 08 00 .........:..0?..
000000a0: 30 3f 08 ac 84 02 00 cc 19 04 00 06 00 00 00 00 0?..............
000000b0: 10 00 00 02 00 00 00 14 b0 3a 00 14 30 3f 08 14 .........:..0?..
000000c0: 30 3f 08 50 01 00 00 50 01 00 00 06 00 00 00 04 0?.P...P........
000000d0: 00 00 00 04 00 00 00 48 01 00 00 48 81 04 08 48 .......H...H...H
000000e0: 81 04 08 20 00 00 00 20 00 00 00 04 00 00 00 04 ... ... ........
000000f0: 00 00 00 50 e5 74 64 98 ae 3a 00 98 2e 3f 08 00 ...P.td..:...?..

Notes

This type of vulnerability is an architectural weakness of the Zend Engine. We do not expect that interruption bugs like this one will be fixed soon. While disabling allow_call_time_pass_reference helps to stop the provided exploit it does not help against similar interruption exploits against functions supposed to get references passed or against interruption attacks against different structures.