iDEFENSE Security Advisory 03.31.05: PHP getimagesize() Multiple Denial of Service Vulnerabilities

From: iDEFENSE Labs (labs-no-reply_at_idefense.com)
Date: 04/01/05

  • Next message: Jeremy Rasmussen: "PayPal "security" measures"
    Date: Thu, 31 Mar 2005 18:23:04 -0500
    To: <bugtraq@securityfocus.com>, <vulnwatch@vulnwatch.org>
    
    

    PHP getimagesize() Multiple Denial of Service Vulnerabilities

    iDEFENSE Security Advisory 03.31.05
    www.idefense.com/application/poi/display?id=222&type=vulnerabilities
    March 31, 2005

    I. BACKGROUND

    PHP is a widely-used general-purpose scripting language that is
    especially suited for Web development and can be embedded into HTML.
    More information is available at:

       http://www.php.net

    II. DESCRIPTION

    Remote exploitation of multiple denial of service vulnerabilities in
    the PHP Group's PHP scripting language allows attackers to consume CPU
    resources. The vulnerable routines, php_handle_iff() and
    php_handle_jpeg(), are reachable from the PHP function getimagesize(),
    which is defined as follows:

        array getimagesize ( string filename [, array &imageinfo] )

    The getimagesize() routine is used to determine the size and dimensions
    of multiple image formats, including GIF, JPG, PNG, TIFF, etc.

    ISSUE 1 - php_handle_iff() Denial of Service

    Remote exploitation of a denial of service (DoS) condition in the PHP
    Group's PHP scripting language allows attackers to consume CPU
    resources.

    The problem specifically exists within the function php_handle_iff()
    defined in ext/standard/image.c. The vulnerability is demonstrated in
    the following excerpt:

        static struct gfxinfo *php_handle_iff(php_stream * stream TSRMLS_DC)
        {
        ...
                /* loop chunks to find BMHD chunk */
                do {
        [1] if (php_stream_read(stream, a, 8) != 8) {
                                efree(result);
                                return NULL;
                        }
                        chunkId = php_ifd_get32s(a+0, 1);
        [2] size = php_ifd_get32s(a+4, 1);
                        if ((size & 1) == 1) {
                                size++;
                        }
                    if (chunkId == 0x424d4844) { /* BMHD chunk */
                            ...
                    ...
                } else {
        [3] if (php_stream_seek(stream, size, SEEK_CUR)) {
                                    efree(result);
                                    return NULL;
                            }
                        }
                } while (1);
        }

    In the excerpt above, at line [1], 8 bytes are read from the user-
    supplied file stream. At line [2], the variables 'chunkId' and 'size'
    are set to user-supplied values from the file stream. If the variable
    'size' is set to -8, then on line [3] the current position within the
    file stream is moved back 8 bytes, resulting in an infinite loop.

    ISSUE 2 - php_handle_jpeg() Denial of Service

    Local exploitation of an input validation vulnerability in The PHP
    Group's PHP embedded scripting language allows attackers to consume CPU
    resources. The vulnerability specifically exists due to insufficient
    validation of JPEG image file headers in the php_handle_jpeg()
    function. The JPEG file header contains a file length field which may
    be manipulated to cause an infinate loop in the copying of file data to
    memory as shown below from ext/standard/image.c:

        static struct gfxinfo *
        php_handle_jpeg (php_stream * stream, pval *info TSRMLS_DC)
        {
            struct gfxinfo *result = NULL;
            unsigned int marker = M_PSEUDO;
            unsigned short length, ff_read=1;
        
            for (;;) {
        [1] marker = php_next_marker(stream, marker, 1, ff_read
    TSRMLS_CC);
                ff_read = 0;
                switch (marker) {
                    ...
                    default:
        [2] php_skip_variable(stream TSRMLS_CC);
                                        break;
                }
            }
        
            return result; /* perhaps image broken -> no info but size */
        }
        
        static void php_skip_variable(php_stream * stream TSRMLS_DC)
        {
        [3] off_t length = ((unsigned int)php_read2(stream TSRMLS_CC));
        
            length = length-2;
            if (length)
            {
        [4] php_stream_seek(stream, (long)length, SEEK_CUR);
            }
        }

    The php_next_marker() call [1] reads the next byte in the stream to
    determine handling of the associated data. If given an invalid marker
    value, the case statement executes the default block which calls the
    php_skip_variable() function [2]. The php_read2() call [3] will return
    0 bytes if the file stream has reached its end, so the pointer math
    causes a length value of -2 in the php_stream_seek() call[4]. This
    results in an infinate loop as the stream now points to the last two
    bytes of the file when the pointer is returned to the for loop in
    php_handle_jpeg().

    III. ANALYSIS

    Exploitation of either vulnerability could allow unauthenticated remote
    attackers to consume 100% CPU resources on vulnerable systems.
    Exploitation requires that an attacker supply a malicious image to the
    getimagesize() PHP routine. The getimagesize() routine is frequently
    used when handling user-supplied image uploads, which increases the
    feasibility of remote exploitation.

    IV. DETECTION

    iDEFENSE has confirmed the existence of these vulnerabilities in PHP
    versions 4.2.2, 4.3.9, 4.3.10 and 5.0.3.

    V. WORKAROUND

    iDEFENSE is currently unaware of any workaround for this issue.

    VI. VENDOR RESPONSE

    These vulnerabilities are addressed in PHP 5.0.4 which is available for
    download at:

       www.php.net/distributions/php-5.0.4.tar.gz
       www.php.net/distributions/php-5.0.4.tar.bz2

    VII. CVE INFORMATION

    The Common Vulnerabilities and Exposures (CVE) project has assigned the
    following names to these issues:

    CAN-2005-0524 - php_handle_iff()
    CAN-2005-0525 - php_handle_jpeg()

    These are candidates for inclusion in the CVE list
    (http://cve.mitre.org), which standardizes names for security problems.

    VIII. DISCLOSURE TIMELINE

    02/23/2005 Initial vendor notification
    02/23/2005 Initial vendor response
    03/31/2005 Coordinated public disclosure

    IX. CREDIT

    The discoverer of these issues wishes to remain anonymous.

    Get paid for vulnerability research
    http://www.idefense.com/poi/teams/vcp.jsp

    Free tools, research and upcoming events
    http://labs.idefense.com

    X. LEGAL NOTICES

    Copyright (c) 2005 iDEFENSE, Inc.

    Permission is granted for the redistribution of this alert
    electronically. It may not be edited in any way without the express
    written consent of iDEFENSE. If you wish to reprint the whole or any
    part of this alert in any other medium other than electronically, please
    email customerservice@idefense.com for permission.

    Disclaimer: The information in the advisory is believed to be accurate
    at the time of publishing based on currently available information. Use
    of the information constitutes acceptance for use in an AS IS condition.

    There are no warranties with regard to this information. Neither the
    author nor the publisher accepts any liability for any direct, indirect,
    or consequential loss or damage arising from use of, or reliance on,
    this information.


  • Next message: Jeremy Rasmussen: "PayPal "security" measures"

    Relevant Pages