When GD functions are called they first retrieve the resource data for further processing. When these functions are interrupted by an error, after the resource data is retrieved, a malicious userspace errorhandler can destroy the image resource and replace it with a specially prepared fake resource. This allows read and write access to arbitrary memory addresses that can be exploited to execute arbitrary code.
Affected are PHP 4 <= 4.4.6 and PHP 5 <= 5.2.1
When PHP functions need to keep track of data structures they register resources with the Zend Engine. The resource system has reference counters but those only keep track of the PHP variables that point to the actual resource. There is however no usage counter that counts how many functions currently use the resource internally.
Because of this a special bug class exists in the PHP code. Whenever it is possible for usercode to interrupt a PHP function after it has acquired the resource data through the resource identifier, the usercode can destroy the resource and for example allocate a PHP string of the same size that will take the same place in memory as the freed resource. This PHP string can be used to create a special crafted resource that allows exploiting the internals of the PHP functions. When the malicious interruption ends the function will continue and use the replaced resource data.
To achieve the necessary function interruption it is usually enough to put an object into one of the function parameters. This will trigger a PHP error during a conversion to a long value. However other kind of warnings or notices that are thrown by the functions can also be used.
Proof of concept, exploit or instructions to reproduce
The attached exploit uses the substr_compare() information leak vulnerability to determine what offsets to use. Therefore the exploit will only work on PHP 5. It is however possible to use other functions of GD to leak bigger parts of memory in a faster way than the implemented peek() function. Therefore in an exploit that should also work in PHP 4, those should be used.
The exploit will spawn a shell on port 4444 as usual.
This class of vulnerability does not only affect the GD extension but many more extension.
The only correct fix for this would be to rework the PHP resource system to support usage counters and to use them. Or to use the resource reference counter for that purpose.
Because this is a lot of work we doubt that it will be fixed soon.