Lucene search

K
talosTalos IntelligenceTALOS-2019-0843
HistoryJul 29, 2019 - 12:00 a.m.

SDL_image XPM image color code code execution vulnerability

2019-07-2900:00:00
Talos Intelligence
www.talosintelligence.com
101

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.003 Low

EPSS

Percentile

67.5%

Summary

An exploitable code execution vulnerability exists in the XPM image rendering functionality of SDL2_image 2.0.4. A specially crafted XPM image can cause an integer overflow, allocating too small of a buffer. This buffer can then be written out of bounds resulting in a heap overflow, ultimately ending in code execution. An attacker can display a specially crafted image to trigger this vulnerability.

Tested Versions

SDL_image 2.0.4

Product URLs

<https://www.libsdl.org/projects/SDL_image/&gt;

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-190: Integer Overflow or Wraparound

Details

LibSDL is a multi-platform library for easy access to low-level hardware and graphics, providing support for a large number of video games, software and emulators. The LibSDL2_Image library is an optional component that deals specifically with parsing and displaying a variety of image file formats, creating a single, uniform API for image processing, regardless of the type.

XPM is a line-based image format. The first line contains the width, height, number of colors, and number of characters per pixel to be parsed [0].

SDL_image/IMG_xpm.c:1015

/*
 * The header string of an XPMv3 image has the format
 *
 * &lt;width&gt; &lt;height&gt; &lt;ncolors&gt; &lt;cpp&gt; [ &lt;hotspot_x&gt; &lt;hotspot_y&gt; ]
 *
 * where the hotspot coords are intended for mouse cursors.
 * Right now we don't use the hotspots but it should be handled
 * one day.
 */
if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 // [0]
   || w &lt;= 0 || h &lt;= 0 || ncolors &lt;= 0 || cpp &lt;= 0) {
    error = "Invalid format description";
    goto done;
}

In preparation for parsing, a buffer is allocated for the pixels by multiplying the read number of colors by the characters per pixel [1].

SDL_image/IMG_xpm.c:1033

keystrings = (char *)SDL_malloc(ncolors * cpp); // [1]
if (!keystrings) {
    error = "Out of memory";
    goto done;
}
nextkey = keystrings;

The next line in the XPM format describes each color. The most basic format for each of these lines is to have a character with a given color. For instance, the following line shows that any following ā€˜zā€™ will be colored black and will produce a line of colors that has three black pixels, three white pixels and then three more black pixels.

z c #000000
. c #ffffff
zzz...zzz

When parsing these lines [2], the color code is copied into the keystrings/nextkey buffer allocated previously [3]. The amount of data copied is controlled via the cpp value read from the previous line assuming the first characters of the color code is valid [4].

SDL_image/IMG_xpm.c:1070

line = get_next_line(xpmlines, src, 0); // [2]
if (!line)
    goto done;

p = line + cpp + 1;

/* parse a colour definition */
for (;;) {
    char nametype;
    char *colname;
    Uint32 rgb, pixel;

    SKIPSPACE(p);
    if (!*p) {
        printf("Color parse error\n");
        error = "colour parse error";
        goto done;
    }
    nametype = *p;
    SKIPNONSPACE(p);
    SKIPSPACE(p);
    colname = p;
    SKIPNONSPACE(p);
    if (nametype == 's') {
        printf("skipping nametype == s\n");
        continue;      /* skip symbolic colour names */
    }

    if (!color_to_rgb(colname, (int)(p - colname), &rgb)) { // [4]
        printf("color to rgb failed\n");
        continue;
    }

    SDL_memcpy(nextkey, line, cpp); // [3]

By providing a sufficiently large ncolors and cpp value, the buffer allocation size can overflow into a size too small to hold the color code string. This causes the memcpy to cause a heap overflow, potentially resulting in code execution.

Crash Information

=================================================================
==21578==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff4 at pc 0x7fa51007e904 bp 0x7ffe5004dbd0 sp 0x7ffe5004d378
WRITE of size 4100 at 0x60200000eff4 thread T0
    #0 0x7fa51007e903 in __asan_memcpy (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x8c903)
    #1 0x4ba104 in load_xpm ../IMG_xpm.c:1123
    #2 0x40653c in IMG_LoadTyped_RW ../IMG.c:195
    #3 0x404d70 in main ../showimage.c:56
    #4 0x7fa50f51e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #5 0x405388 in _start (/root/vmshare/targets/sdl/SDL_image/build-afl-asan/showimage+0x405388)

0x60200000eff4 is located 0 bytes to the right of 4-byte region [0x60200000eff0,0x60200000eff4)
allocated by thread T0 here:
    #0 0x7fa51008a602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x4f6ebc in SDL_malloc_REAL /root/vmshare/targets/sdl/SDL/src/stdlib/SDL_malloc.c:5390

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 __asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=&gt;0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[04]fa
0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable:           00
Partially addressable: 01 02 03 04 05 06 07 
Heap left redzone:       fa
Heap right redzone:      fb
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack partial redzone:   f4
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
Array cookie:            ac
Intra object redzone:    bb
ASan internal:           fe
==21578==ABORTING

Timeline

2019-05-30 - Vendor Disclosure
2019-07-03 - Vendor Patched
2019-07-29 - Public Release

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.003 Low

EPSS

Percentile

67.5%