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
For this issue, CVE-2018-6187 is assigned.
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
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.