X41 D-Sec GmbH Security Advisory: X41-2017-001

Multiple Vulnerabilities in X.org

Overview

Vendor: X.org/Freedesktop.org

Vendor URL: https://www.x.org/wiki/

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Advisory-URL: https://www.x41-dsec.de/lab/advisories/x41-2017-001-xorg/

Status: Public

Timing attack against MIT Cookie

Vulnerability Type: Other

Affected Products: Xorg Server

Attack Type: Local

Impact: Escalation of Privileges

Severity Rating: low

Confirmed Affected Version: 1.19.0 and lower

Confirmed Patched Version:

Vector: local

CVE: CVE-2017-2624

CVSS Score: 5.9

CVSS Vector: CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N

Summary and Impact

The xorg-server uses memcmp() to check the received MIT cookie against a series of valid cookies. If the cookie is correct, it is allowed to attach to the Xorg session:

XID
MitCheckCookie(unsigned short data_length,
               const char *data, ClientPtr client, const char **reason)
{
    struct auth *auth;

    for (auth = mit_auth; auth; auth = auth->next) {
        if (data_length == auth->len &&
            memcmp(data, auth->data, (int) data_length) == 0)
            return auth->id;
    }
    *reason = "Invalid MIT-MAGIC-COOKIE-1 key";
    return (XID) -1;
}

Since most memcmp() implementations return after an invalid byte is seen, this causes a time difference between a valid and invalid byte, which in theory could allow an efficient brute force attack.

Analysis

X41 was not able to measure a significant difference using the optimised memcmp() version of a standard Linux system, but for a naive implementation consisting of a loop comparing the bytes. Since timing attacks against memcmp() have been successful in the past and fixed elsewhere X41 would consider this an issue. If this would be exploited, it would allow a local attacker to run code in the Xorg session of another user.

In order to prevent this, MIT-COOKIES should be removed or a memcmp() similar to timingsafe_memcmp() used. Other projects (e.g. openssl) use timing safe memcmp() implementations to compare cookies retrieved via the network.

Workaround

None

Potential Use after Free in Xorg Server

Vulnerability Type: Other

Affected Products: Xorg Server

Attack Type: Local

Impact: -

Severity Rating: none

Confirmed Affected Version: 1.19.0 and lower

Confirmed Patched Version: -

Vector: local

CVE: -

CVSS Score: -

CVSS Vector: -

Summary and Impact

In XDM is a (currently non security) issue, regarding a potential use after free.

The ToID() function in os/auth.c is not used anywhere, just defined in the struct and filled by the protocols, but there are no users.

AuthToIDFunc ToID;          /* convert cookie to ID */

X41 noticed that, XdmToID() frees the cookie argument in case it can resolve the ID or on failure, but not if it can't allocate memory for plain:

  XdmToID(unsigned short cookie_length, char *cookie)
    {
        XdmAuthorizationPtr auth;
        XdmClientAuthPtr client;
        unsigned char *plain;
    
        plain = malloc(cookie_length);
        if (!plain)
            return (XID) -1;
        for (auth = xdmAuth; auth; auth = auth->next) {
            XdmcpUnwrap((unsigned char *) cookie, (unsigned char *) &auth->key,
                        plain, cookie_length);
            if ((client =
                 XdmAuthorizationValidate(plain, cookie_length, &auth->rho, NULL,
                                          NULL)) != NULL) {
                free(client);
                free(cookie);
                free(plain);
                return auth->id;
            }
        }
        free(cookie);
        free(plain);
        return (XID) -1;
    }

The same return value is given, whether no memory could be allocated or it just failed to lookup the ID, so the caller cannot distinguish whether this memory is freed or not, which might lead to double-free or memory leaks. The other ToID functions do not free this parameter.

Weak entropy usage for session keys in libxdm

Vulnerability Type: Other

Affected Products: libXdmcp

Attack Type: Local

Impact: Escalation of Privileges

Severity Rating: medium

Confirmed Affected Version: 1.1.2 and lower

Confirmed Patched Version: -

Vector: local

CVE: CVE-2017-2625

CVSS Score: 7.1

CVSS Vector: CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

Summary and Impact

To further explore the auth mechanism libXdmcp-1.1.2 was checked as well.

XDM uses weak entropy to generate the session keys on non BSD systems:

  void
    XdmcpGenerateKey (XdmAuthKeyPtr key)
    {
    #ifndef HAVE_ARC4RANDOM_BUF
     long    lowbits, highbits;
    
        srandom ((int)getpid() ^ time((Time_t *)0));
        lowbits = random ();
        highbits = random ();
        getbits (lowbits, key->data);
        getbits (highbits, key->data + 4);
    #else
     arc4random_buf(key->data, 8);
    #endif
 }

On multi user systems it might possible to check the PID of the process and how long it is running to get an estimate of these values, which could allow an attacker to attach to the session of a different user. Several checked Linux distributions (debian, archlinux and Ubuntu) did not link against libbsd at the time this was found.

Workaround

Compile against libbsd.

Weak Entropy Usage in Session Keys in libICE

Vulnerability Type: Other

Affected Products: libICE

Attack Type: Local

Impact: Escalation of Privileges

Severity Rating: medium

Confirmed Affected Version: 1.0.9 and lower

Confirmed Patched Version: -

Vector: local

CVE: CVE-2017-2626

CVSS Score: 7.1

CVSS Vector: CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

Summary and Impact

libICE depends on arc4random() as well to generate the session cookies, thereby falling back to the same weak mechanism as libXdmcp:

IceGenerateMagicCookie (
    int len
)
{
    char    *auth;
#ifndef HAVE_ARC4RANDOM_BUF
    long    ldata[2];
    int     seed;
    int     value;
    int     i;
#endif

    if ((auth = malloc (len + 1)) == NULL)
    return (NULL);

#ifdef HAVE_ARC4RANDOM_BUF
    arc4random_buf(auth, len);
#else
#ifdef ITIMER_REAL
    {
    struct timeval  now;
    X_GETTIMEOFDAY (&now);
    ldata[0] = now.tv_sec;
    ldata[1] = now.tv_usec;
    }
#else
    {
    long    time ();
    ldata[0] = time ((long *) 0);
    ldata[1] = getpid ();
    }
#endif
    seed = (ldata[0]) + (ldata[1] << 16);
    srand (seed);
    for (i = 0; i < len; i++)
    {
    value = rand ();
    auth[i] = value & 0xff;
    }
#endif
    auth[len] = '\0';
    return (auth);
}

For this issue a PoC is available which takes 2-3 seconds to retrieve the key: icetest.c

Workaround

Compile against libbsd.

Weak Entropy Usage in xorg server

Vulnerability Type: Other

Affected Products: Xorg Server

Attack Type: Local

Impact: Unknown

Severity Rating: unclear

Confirmed Affected Version: 1.19.0 and lower

Confirmed Patched Version: -

Vector: local

CVE: -

CVSS Score: -

CVSS Vector: -

Summary and Impact

When looking at other places that use entropy, X41 also noticed os/auth.c and hw/xwin/winauth.c providing GenerateRandomData()

  void
    GenerateRandomData(int len, char *buf)
    {
        int fd;
    
        fd = open("/dev/urandom", O_RDONLY);
        read(fd, buf, len);
        close(fd);
    }

When the call to open or read fails, the contents of buf might be undefined. This should be handled more gracefully, it might fail in chrooted environments (unlikely) or when file descriptors are exhausted. Newer Linux Kernels provide getrandom() to protect against this and OpenBSD provides getentropy().

The security impact of these functions has not been further inspected.

About X41 D-Sec GmbH

X41 D-Sec GmbH is an expert provider for application security services. Having extensive industry experience and expertise in the area of information security, a strong core security team of world class security experts enables X41 to perform premium security services.

Fields of expertise in the area of application security are security centric code reviews, binary reverse engineering and vulnerability discovery. Custom research and a IT security consulting and support services are core competencies of X41.

Timeline

2017-01-17 to 01-23 Report to xorg-security@lists.x.org

2017-02-10 CVE Request at secalert@redhat.com

2017-02-13 CVE IDs assigned

2017-02-16 Information of distros@vs.openwall.org

2017-02-20 Patch for CVE-2017-2624 provided by Matthieu Herrb

2017-02-28 Advisory release

Author: Eric Sesterhenn
Date: 2017-02-28 00:00:00 +0100