Lucene search

K
talosTalos IntelligenceTALOS-2019-0821
HistoryJul 02, 2019 - 12:00 a.m.

Simple DirectMedia Layer SDL2_image IMG_LoadPCX_RW signed comparison code execution vulnerability

2019-07-0200:00:00
Talos Intelligence
www.talosintelligence.com
60

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.005 Low

EPSS

Percentile

75.4%

Summary

An exploitable integer overflow vulnerability exists when loading a PCX file in SDL2_image 2.0.4. A specially crafted file can cause an integer overflow, resulting in too little memory being allocated, which can lead to a buffer overflow and potential code execution. An attacker can provide a specially crafted image file to trigger this vulnerability.

Tested Versions

Simple DirectMedia Layer SDL2_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

This vulnerability is present in the SDL2_image library, which is used for loading images in different formats.

There is a vulnerability in the function responsible for loading PCX files. A specially crafted PCX file can lead to a heap buffer overflow and remote code execution.

Let’s investigate this vulnerability. After we attempt to load a malformed PCX file, the following state appears:

	./showimage PoC.pcx
==12669==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0xa896ce70 in thread T0
	#0 0xb7245a84 in free (/usr/lib/i386-linux-gnu/libasan.so.2+0x96a84)
	#1 0x81259b3 in SDL_free_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/stdlib/SDL_malloc.c:5372
	#2 0x8131dd2 in SDL_FreePalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_pixels.c:735
	#3 0x8131b32 in SDL_SetPixelFormatPalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_pixels.c:685
	#4 0x813d1f5 in SDL_SetSurfacePalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_surface.c:221
	#5 0x81448d1 in SDL_FreeSurface_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_surface.c:1233
	#6 0x80abfd7 in SDL_FreeSurface /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/dynapi/SDL_dynapi_procs.h:475
	#7 0x805875f in IMG_LoadPCX_RW ../IMG_pcx.c:252
	#8 0x804c301 in IMG_LoadTyped_RW ../IMG.c:195
	#9 0x804beff in IMG_Load ../IMG.c:136
	#10 0x804c3e7 in IMG_LoadTexture ../IMG.c:212
	#11 0x804b65c in main ../showimage.c:101
	#12 0xb6f99636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
	#13 0x804ad50  (/home/icewall/bugs/SDL_src/SDL2_image-2.0.4/build/showimage+0x804ad50)

0xa896ce70 is located 0 bytes inside of 536870912-byte region [0xa896ce70,0xc896ce70)

It looks like the heap has been corrupted, and application is crashing while free-ing. Let’s take a closer look at the code where the vulnerability takes place:

IMG_pcx.c
146	   bpl = pcxh.NPlanes * pcxh.BytesPerLine;
147	   if (bpl &gt; surface-&gt;pitch) {
148		 error = "bytes per line is too large (corrupt?)";
149	   }	
150    buf = (Uint8 *)SDL_calloc(SDL_max(bpl, surface-&gt;pitch), 1);
151    row = (Uint8 *)surface-&gt;pixels;	
152    for ( y=0; y&lt;surface-&gt;h; ++y ) {
153        /* decode a scan line to a temporary buffer first */
154        int i, count = 0;
155        Uint8 ch;
156        Uint8 *dst = (src_bits == 8) ? row : buf;
157        if ( pcxh.Encoding == 0 ) {
158            if(!SDL_RWread(src, dst, bpl, 1)) {
159                error = "file truncated";
160                goto done;
161            }
162        } else {
163            for(i = 0; i &lt; bpl; i++) {
164                if(!count) {
165                    if(!SDL_RWread(src, &ch, 1, 1)) {
166                        error = "file truncated";
167                        goto done;
168                    }
169                    if( (ch & 0xc0) == 0xc0) {
170                        count = ch & 0x3f;
171                        if(!SDL_RWread(src, &ch, 1, 1)) {
172                            error = "file truncated";
173                            goto done;
174                        }
175                    } else
176                        count = 1;
177                }
178                dst[i] = ch;
179                count--;
180            }
181        }

		(...)

214        row += surface-&gt;pitch;
215    }

The overflow appears at line 158. It happens because, as you can see at line 147, the calculated bpl value is checked against the surface-&gt;pitch field. Because both variables are of type signed integer, there is a scenario where e.g bpl = -1 and surface-&gt;pitch = 1, which causes that condition to be satisfied.

Later, assuming that src_bits is equal to 8, the dst pointer will have the value of row, where row == surface-&gt;pixels.

Now, calling SDL_RWread function at line 158 with a size argument equal bpl, bpl’s signed value will be treated as a size_t (unsigned), which consequently leads to reading UINT_MAX bytes from the file.

A dump of a malformed PCX file:

struct PCX file			0h	80h	Fg: Bg:	
ubyte Manufacturer		10	0h	1h	Fg: Bg:	
enum PCX_TYPE version	v3up (5)	1h	1h	Fg: Bg:	
ubyte encoding			0	2h	1h	Fg: Bg:	
ubyte BitsPerPixel		1	3h	1h	Fg: Bg:	
ushort Xmin				0	4h	2h	Fg: Bg:	
ushort Ymin				0	6h	2h	Fg: Bg:	
ushort Xmax				0	8h	2h	Fg: Bg:	
ushort Ymax				257	Ah	2h	Fg: Bg:	
ushort HDpi				511	Ch	2h	Fg: Bg:	
ushort VDpi				257	Eh	2h	Fg: Bg:	
ubyte Colormap[48]		10h	30h	Fg: Bg:	
ubyte Reserved			255	40h	1h	Fg: Bg:	
ubyte NPlanes			1	41h	1h	Fg: Bg:	
ushort BytesPerLine		32769	42h	2h	Fg: Bg:	
ushort PaletteInfo		18	44h	2h	Fg: Bg:	
ushort HscreenSize		0	46h	2h	Fg: Bg:	
ushort VscreenSize		0	48h	2h	Fg: Bg:	
ubyte Filler[54]		4Ah	36h	Fg: Bg:	

An attacker fulling controlling the size of overwrite (via size of the file) and its content, can turn this heap-based buffer overflow in a remote code execution.

Crash Information

	./showimage PoC.pcx
==12669==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0xa896ce70 in thread T0
	#0 0xb7245a84 in free (/usr/lib/i386-linux-gnu/libasan.so.2+0x96a84)
	#1 0x81259b3 in SDL_free_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/stdlib/SDL_malloc.c:5372
	#2 0x8131dd2 in SDL_FreePalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_pixels.c:735
	#3 0x8131b32 in SDL_SetPixelFormatPalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_pixels.c:685
	#4 0x813d1f5 in SDL_SetSurfacePalette_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_surface.c:221
	#5 0x81448d1 in SDL_FreeSurface_REAL /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/video/SDL_surface.c:1233
	#6 0x80abfd7 in SDL_FreeSurface /home/icewall/bugs/SDL_src/SDL2-2.0.9/src/dynapi/SDL_dynapi_procs.h:475
	#7 0x805875f in IMG_LoadPCX_RW ../IMG_pcx.c:252
	#8 0x804c301 in IMG_LoadTyped_RW ../IMG.c:195
	#9 0x804beff in IMG_Load ../IMG.c:136
	#10 0x804c3e7 in IMG_LoadTexture ../IMG.c:212
	#11 0x804b65c in main ../showimage.c:101
	#12 0xb6f99636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
	#13 0x804ad50  (/home/icewall/bugs/SDL_src/SDL2_image-2.0.4/build/showimage+0x804ad50)

0xa896ce70 is located 0 bytes inside of 536870912-byte region [0xa896ce70,0xc896ce70)
ASAN:SIGSEGV
==12669==AddressSanitizer: while reporting a bug found another one. Ignoring.

Timeline

2019-05-08 - Vendor Disclosure
2019-07-01 - Vendor Patched; 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.005 Low

EPSS

Percentile

75.4%