Buffer under write vulnerability in fig2dev 3.2.7a
Loginsoft-2018-16140August 25, 2018
CVE Number
CVE-2018-16140
CWE
CWE-124: Buffer Underwrite ('Buffer Underflow')
Product Details
Xfig is a free and open-source vector graphics editor which runs under the X Window System on most UNIX-compatible platforms. fig2dev is a library used by Xfig package to translate fig code to other graphical languages (tikz, shape, jpeg, png etc.)
Vulnerable Versions
fig2dev 3.2.7a (Xfig package)
Vulnerability Details
A Buffer under write vulnerability was discovered in fig2dev 3.2.7a version.
SYNOPSIS
Pre-research, on having a closer look at CVE's specific to fig2dev binary, we came across a buffer under write vulnerability which was discovered in fig2dev 3.2.6a-6, reported by jwilk.
Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882022
As per the report, a local variable `len` in get_line() function of fig2dev/read.c, when received with a values less than 2 (0 or 1), would end up writing outside the buffer, creating a buffer underwrite issue. Being precise, get_line() functions is responsible for doing few checks, some of them being Skip empty lines, trailing newline, trailing CR's etc. The problem exists while trailing any CR's (Carriage returns) from the fig document.
According to the code, on occurrence of an `\r`, a NULL termination is written thereby stripping off the CR. The issues get introduced when the value of len is manipulated with a value, which when computed with 2, would result in writing outside buffer, throwing a Segmentation fault (SIGSEGV).
As per Debian report log, the vulnerability looks to be fixed in the 3.2.7 release. Upon searching for the fix commit in the 3.2.7 release, we figured out there were no fix made to the get_line() function, instead in the read_objects() which was using the same block of code. This looked quite strange. Upon fuzzing, we were still able to reproduce the same issue. The value of len inside get_len() manage to be zero, leading to buffer underwrite.
Suggested mitigation: Applying the same bound check, which was employed earlier in 3.2.7 against read_objects() (checking len>0)
.
Analysis
Breakpoint 1 at 0x812ad: file read.c, line 1470.
The program is not being run.
Starting program: /home/ethan/Desktop/fig2dev-3.2.7a_debian/fig2dev/fig2dev -L tikz ~/Desktop/overflow_218
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, get_line (fp=0x616000000080) at read.c:1470
1470 if (buf[len-2] == '\r')
len = 1
rax 0x555555995ac0 93824996694720
rbx 0x7fffffffde70 140737488346736
rcx 0x0 0
rdx 0x0 0
rsi 0x616000000100 107064944754944
rdi 0x0 0
rbp 0x7fffffffddd0 0x7fffffffddd0
rsp 0x7fffffffddb0 0x7fffffffddb0
r8 0x0 0
r9 0x0 0
r10 0x7ffff7fdb780 140737353987968
r11 0x246 582
r12 0xffffffffbce 17592186043342
r13 0x7fffffffdf10 140737488346896
r14 0x7fffffffde70 140737488346736
r15 0x0 0
rip 0x5555555d52ad 0x5555555d52ad
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
1465 if (save_comment() < 0)
1466 return -1;
1467 } else if (*buf != '\n') { /* Skip empty lines */
1468 len = strlen(buf);
1469 buf[len-1] = '\0'; /* strip trailing newline */
1470 if (buf[len-2] == '\r')
1471 buf[len-2] = '\0'; /* strip trailing CRs */
1472 return 1;
1473 }
1474 }
Continuing.
[Inferior 1 (process 5867) exited with code 01]
ASAN Report
==4867==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000007cd03f at pc 0x0000004232a1 bp 0x7fffffffdb40 sp 0x7fffffffdb30
READ of size 1 at 0x0000007cd03f thread T0
#0 0x4232a0 in get_line /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/read.c:1470
#1 0x41a27f in read_objects /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/read.c:340
#2 0x418f20 in readfp_fig /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/read.c:172
#3 0x418e09 in read_fig /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/read.c:142
#4 0x411583 in main /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/fig2dev.c:424
#5 0x7ffff659282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#6 0x4030e8 in _start (/home/woot/Desktop/fig2dev-3.2.7a/fig2dev/fig2dev+0x4030e8)
0x0000007cd03f is located 59 bytes to the right of global variable 'gif_colnum' defined in 'read.c:80:13' (0x7cd000) of size 4
0x0000007cd03f is located 1 bytes to the left of global variable 'buf' defined in 'read.c:81:14' (0x7cd040) of size 8192
SUMMARY: AddressSanitizer: global-buffer-overflow /home/woot/Desktop/fig2dev-3.2.7a/fig2dev/read.c:1470 get_line
Shadow bytes around the buggy address:
0x0000800f19b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f19c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f19d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f19e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f19f0: 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
=>0x0000800f1a00: 04 f9 f9 f9 f9 f9 f9[f9]00 00 00 00 00 00 00 00
0x0000800f1a10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f1a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f1a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f1a40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800f1a50: 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
==4867==ABORTING
[Inferior 1 (process 4867) exited with code 01
Proof of Concept
fig2dev -L tikz $POC
The switch -L specifies the graphical language to which we want to convert our figure file to, followed by our input figure file. The issue is exploitable when supplied a crafted fig file via the above given command.
Timeline
Vendor Disclosure: 2018-08-22
Patch Release: 2018-08-23
Public Disclosure: 2018-08-25
Credit
Discovered by ACE Team - Loginsoft