Bug 698908

Summary: There is a heap buffer overflow in do_pdf_save_document function.
Product: MuPDF Reporter: Young_X <yangx92>
Component: fuzzingAssignee: MuPDF bugs <mupdf-bugs>
Status: RESOLVED FIXED    
Severity: major CC: ismail, mjg, sebastian.rasmussen, yangx92
Priority: P4    
Version: master   
Hardware: PC   
OS: Linux   
Customer: Word Size: ---
Attachments: poc

Description Young_X 2018-01-23 20:35:57 UTC
Created attachment 14640 [details]
poc

There is a heap buffer overflow vulnerability in do_pdf_save_document function in source/pdf/pdf-write.c file.

Error message with Clang 
./mutool poster mutool_poster_crash 
warning: ignoring invalid character in hex string
warning: ... repeated 32 times ...
error: expected object number
warning: repairing PDF document
=================================================================
==15282==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60f00000ed24 at pc 0x000000838b6b bp 0x7fff2f1d4cc0 sp 0x7fff2f1d4cb8
WRITE of size 4 at 0x60f00000ed24 thread T0
    #0 0x838b6a  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x838b6a)
    #1 0x83b1a2  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x83b1a2)
    #2 0x542e29  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x542e29)
    #3 0x4eb9af  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x4eb9af)
    #4 0x7f68c50bc82f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #5 0x419bc8  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x419bc8)

0x60f00000ed24 is located 0 bytes to the right of 164-byte region [0x60f00000ec80,0x60f00000ed24)
allocated by thread T0 here:
    #0 0x4ba078  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x4ba078)
    #1 0x6a6a30  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x6a6a30)
    #2 0x6a6474  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x6a6474)
    #3 0x6a6109  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x6a6109)
    #4 0x846b5a  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x846b5a)
    #5 0x83ee28  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x83ee28)
    #6 0x8388fd  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x8388fd)
    #7 0x83b1a2  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x83b1a2)
    #8 0x542e29  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x542e29)
    #9 0x4eb9af  (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x4eb9af)
    #10 0x7f68c50bc82f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/xx/fuzz/mupdf_test/build/debug/mutool+0x838b6a) 
Shadow bytes around the buggy address:
  0x0c1e7fff9d50: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c1e7fff9d60: 00 00 00 00 00 00 00 00 04 fa fa fa fa fa fa fa
  0x0c1e7fff9d70: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c1e7fff9d80: 00 00 00 00 00 00 04 fa fa fa fa fa fa fa fa fa
  0x0c1e7fff9d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c1e7fff9da0: 00 00 00 00[04]fa fa fa fa fa fa fa fa fa 00 00
  0x0c1e7fff9db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c1e7fff9dc0: 00 00 00 00 fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1e7fff9dd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1e7fff9de0: fd fa fa fa fa fa fa fa fa fa 00 00 00 00 00 00
  0x0c1e7fff9df0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==15282==ABORTING

Call Stack
Breakpoint 1, do_pdf_save_document (ctx=0x60d00000cf70, doc=0x631000000800, opts=0x7fffffffdd00, 
    in_opts=0x7fffffffdee0) at source/pdf/pdf-write.c:2900
2900				for (num = 0; num < xref_len; num++)
(gdb) p xref_len
$1 = 117
(gdb) p opts->list_len
$2 = 41
(gdb) ignore 1 40
Will ignore next 40 crossings of breakpoint 1.
(gdb) c
Continuing.
=================================================================
==15423==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60f00000ed24 at pc 0x000000838b6b bp 0x7fffffffd460 sp 0x7fffffffd458
…
==15423==ABORTING
[Inferior 1 (process 15423) exited with code 01]
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000838ab8 in do_pdf_save_document at source/pdf/pdf-write.c:2900
	breakpoint already hit 1 time
	ignore next 40 hits

Error message with GCC
./mutool poster mupdf_poster_edited 
warning: ignoring invalid character in hex string
warning: ... repeated 32 times ...
error: expected object number
warning: repairing PDF document
Segmentation fault (core dumped)

Call stack
(gdb) run poster ~/fuzz/mupdf_test/build/debug/mutool_poster_crash 
Starting program: /home/xx/fuzz/mupdf_test/mupdf_1207_gcc/build/debug/mutool poster ~/fuzz/mupdf_test/build/debug/mutool_poster_crash
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
warning: ignoring invalid character in hex string
warning: ... repeated 32 times ...
error: expected object number
warning: repairing PDF document

Program received signal SIGSEGV, Segmentation fault.
0x0000000000509bcf in pdf_get_xref_entry (ctx=0x2a13010, doc=0x2a2b520, i=0) at source/pdf/pdf-xref.c:315
315				if (i >= sub->start && i < sub->start + sub->len)
(gdb) bt
#0  0x0000000000509bcf in pdf_get_xref_entry (ctx=0x2a13010, doc=0x2a2b520, i=0) at source/pdf/pdf-xref.c:315
#1  0x0000000000504870 in dowriteobject (ctx=0x2a13010, doc=0x2a2b520, opts=0x7fffffffe0a0, num=0, pass=0)
    at source/pdf/pdf-write.c:2188
#2  0x0000000000504b3e in writeobjects (ctx=0x2a13010, doc=0x2a2b520, opts=0x7fffffffe0a0, pass=0)
    at source/pdf/pdf-write.c:2233
#3  0x00000000005073d2 in do_pdf_save_document (ctx=0x2a13010, doc=0x2a2b520, opts=0x7fffffffe0a0, 
    in_opts=0x7fffffffe1f0) at source/pdf/pdf-write.c:2967
#4  0x0000000000507bf0 in pdf_save_document (ctx=0x2a13010, doc=0x2a2b520, filename=0x7546b6 "out.pdf", 
    in_opts=0x7fffffffe1f0) at source/pdf/pdf-write.c:3108
#5  0x0000000000425781 in pdfposter_main (axxc=2, axxv=0x7fffffffe390) at source/tools/pdfposter.c:205
#6  0x0000000000402c6e in main (axxc=3, axxv=0x7fffffffe388) at source/tools/mutool.c:127

Analysis
Through call stack of Clang-compiled and GCC-compiled, we can infer that there is a heap buffer overflow write at source/pdf/pdf-write.c:2901.
source/pdf/pdf-write.c:2900
2900				for (num = 0; num < xref_len; num++)
2901					opts->use_list[num] = 1;

The probable fix should add a check between opts->list_len and xref_len.

As for xref_len, it is read from input by function pdf_repair_xref.  

CREDIT: Young_X @ VARAS, IIE
Comment 1 Young_X 2018-01-24 02:14:07 UTC
For this issue, CVE-2018-6187 is assigned.
Comment 2 Sebastian Rasmussen 2018-01-29 15:24:32 UTC
I confirmed that this happens in 1.12.0, but it was papered over by the fix in 

====
commit fa9cd085533f68367c299e058ab3fbb7ad8a2dc6
Author: Tor Andersson <tor.andersson@artifex.com>
Date:   Fri Dec 1 16:07:23 2017 +0100

    Fix 698785: Catch malformed numbers in PDF lexical scanner.
    
    Return error tokens when parsing numbers with trailing garbage rather than
    ignoring the extra characters.
    
    Also handle error tokens more gracefully in array and dictionary parsing.
    Treat error tokens as the 'null' keyword and continue parsing.
====

The reason being that this changed the parsing in such a way so as not to trigger the issue as reported. The issue is as reported that use_list and related lists are not extended after the PDF document has been repaired. The fix for this issue is was I have as a tentative change awaiting review in commit 3e15b84c83a3e87cb19424c030b451f69b0b64a8
Comment 3 Sebastian Rasmussen 2018-02-01 09:17:25 UTC
Fixed in

commit 3e30fbb7bf5efd88df431e366492356e7eb969ec
Author: Sebastian Rasmussen <sebras@gmail.com>
Date:   Mon Jan 29 23:40:19 2018 +0100

    Bug 698908: Resize object use and renumbering lists after repair.
    
    Previously repair might end up increasing xref_len, but the lists
    were not correspodingly expanded, leading to ASAN complaints.