Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libgd gd2togif double free #208

Closed
riusksk opened this issue Apr 30, 2016 · 4 comments

Comments

@riusksk
Copy link

commented Apr 30, 2016

Info

libgd gd2togif tool have a double free vulnerability when parse gd2 file which have error header info , can cause to dos or possible to exec code.

Environment

  1. Ubuntu 14.04.2 LTS
  2. libgd 2.1.1 (Latest commit 2016-4-27 )

Detail

root@Ubuntu:~/libgd# Bin/gd2togif poc.gd2 out.gif
*** Error in `Bin/gd2togif': double free or corruption (top): 0x0000000000e532a0 ***
Aborted

modify poc.gd2 to trigger crash:

root@Ubuntu:~/libgd# xxd crash.gd2
0000000: 6764 3200 0001 0235 0172 0080 0002 fdcf  gd2....5.r......
0000010: a183 7f91 de00 0500 0400 00d6 0102 3501  ..............5.
0000020: 7200 8000 0200 e1ff 0300 0003 b57f fff5  r...............
0000030: 0003 b57f fff5 8b00 00                   .........
root@Ubuntu:~/libgd# Bin/gd2togif crash.gd2 out.gif    
Segmentation fault

use valgrind to locate the vul code about double free:

==30824== Invalid free() / delete / delete[] / realloc()
==30824==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30824==    by 0x4EA34E3: gdImageCreateFromGd2Ctx (gd_gd2.c:364)    // Second Free
==30824==    by 0x4EA35CF: gdImageCreateFromGd2 (gd_gd2.c:305)
==30824==    by 0x400C5F: main (gd2togif.c:28)
==30824==  Address 0x5f2f350 is 0 bytes inside a block of size 160 free'd
==30824==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30824==    by 0x4EA3498: _gd2CreateFromFile (gd_gd2.c:215)       // First Free
==30824==    by 0x4EA3498: gdImageCreateFromGd2Ctx (gd_gd2.c:359)
==30824==    by 0x4EA35CF: gdImageCreateFromGd2 (gd_gd2.c:305)
==30824==    by 0x400C5F: main (gd2togif.c:28)
Breakpoint 2, gdImageCreateFromGd2Ctx (in=in@entry=0x603250) at /root/libgd/src/gd_gd2.c:364
364                     gdFree (chunkIdx);
gdb-peda$ p chunkIdx
$1 = (t_chunk_info *) 0x6032a0
gdb-peda$ x chunkIdx
0x6032a0:       0x000000d6000003b5
gdb-peda$ list
358         /* Get the header */
359             im =
360                 _gd2CreateFromFile (in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy,
361                                     &chunkIdx);
362
363             if (im == NULL) {
364                     gdFree (chunkIdx);
365                     return 0;
366             }
367
368             bytesPerPixel = im->trueColor ? 4 : 1;

Exploitable Analysis

gdb-peda$ exploitable
Description: Heap error
Short description: HeapError (10/22)
Hash: 83089ffb997872264981b14f4ede0537.e4f2beb810527b8722b2ddbbdd3558ca
Exploitability Classification: EXPLOITABLE
Explanation: The target's backtrace indicates that libc has detected a heap error or that
  the target was executing a heap function when it stopped. This could be due to heap
  corruption, passing a bad pointer to a heap function such as free(), etc. Since heap
  errors might include buffer overflows, use-after-free situations, etc. they are
  generally considered exploitable.
Other tags: AbortSignal (20/22)

@vapier vapier added the bug label Apr 30, 2016

@vapier

This comment has been minimized.

Copy link
Member

commented Apr 30, 2016

i think your analysis is slightly off -- the first free is inside of _gd2CreateFromFile in the fail2 code path while the second free is in gdImageCreateFromGd2Ctx (what you listed as "first free").

the bugfix is easy, but have to spend a little time writing a test.

@riusksk

This comment has been minimized.

Copy link
Author

commented Apr 30, 2016

sorry, u are right, I has been modified it:

==30824== Invalid free() / delete / delete[] / realloc()
==30824== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30824== by 0x4EA34E3: gdImageCreateFromGd2Ctx (gd_gd2.c:364) // Second Free
==30824== by 0x4EA35CF: gdImageCreateFromGd2 (gd_gd2.c:305)
==30824== by 0x400C5F: main (gd2togif.c:28)
==30824== Address 0x5f2f350 is 0 bytes inside a block of size 160 free'd
==30824== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30824== by 0x4EA3498: _gd2CreateFromFile (gd_gd2.c:215) // First Free
==30824== by 0x4EA3498: gdImageCreateFromGd2Ctx (gd_gd2.c:359)
==30824== by 0x4EA35CF: gdImageCreateFromGd2 (gd_gd2.c:305)
==30824== by 0x400C5F: main (gd2togif.c:28)

root@Ubuntu:~/libgd# xxd crash.gd2
0000000: 6764 3200 0001 0235 0172 0080 0002 fdcf  gd2....5.r......
0000010: a183 7f91 de00 0500 0400 00d6 0102 3501  ..............5.
0000020: 7200 8000 0200 e1ff 0300 0003 b57f fff5  r...............
0000030: 0003 b57f fff5 8b00 00                   .........
root@Ubuntu:~/libgd# Bin/gd2togif crash.gd2 out.gif    
Segmentation fault
@riusksk

This comment has been minimized.

Copy link
Author

commented Apr 30, 2016

use CVE-2016-4413

@vapier

This comment has been minimized.

Copy link
Member

commented May 1, 2016

i doubt a CVE makes sense in this case. it's only a double free ... there is no other memory corruption or use of the pointer/memory. you'll need to prove things a bit more than "random tool's generalizations say it's exploitable".

the best you'd get is a remote DoS on a process that handles arbitrary user input.

vapier added a commit to vapier/libgd that referenced this issue May 1, 2016

tests: gd2: add general read test helpers libgd#208
Since we have random files we want to read & check, turn the two
read programs into general tools.  Then we have shell scripts to
run against the right inputs.

Most of the changes here are just shuffling variable names so we
can add to check_PROGRAMS independently of TESTS.

vapier added a commit to vapier/libgd that referenced this issue May 1, 2016

vapier added a commit that referenced this issue May 1, 2016

tests: gd2: add general read test helpers #208
Since we have random files we want to read & check, turn the two
read programs into general tools.  Then we have shell scripts to
run against the right inputs.

Most of the changes here are just shuffling variable names so we
can add to check_PROGRAMS independently of TESTS.

@vapier vapier closed this in 658f168 May 1, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.