Out-of-bound read in fig2dev 3.2.7a

Out-of-bound read in fig2dev 3.2.7a

Loginsoft-2018-1006

August 26, 2018

CWE

CWE-125: Out-of-bounds Read

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.)

URL: https://sourceforge.net/projects/mcj/

Vulnerable Versions

fig2dev 3.2.7a (Xfig package)

Vulnerability Details

An Out-of-bound read vulnerability was discovered in fig2dev 3.2.7a version.

SYNOPSIS

Another interesting piece of vulnerability discovered in fig2dev was a classic Out-of-bound read.

Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882022

fig2dev binary can be used to convert between various graphical formats. To accomplish the same, it uses different Objects & Object attributes.

Figure file format structure-

    1. The very first line is a comment line specifying the name and version: #FIG 3.2
    2. The next few lines speak about few specifications of the fig file document.

(orientation, justification, units, papersize, multiple-page etc.)

  1. Later blocks defines about various objects & its attributes, which is of our interest as that looked to be a proper point of manipulation.
Example

Object - `ELLIPSE` 
It's related attributes - 
    type    name            (brief description) 
    ----    ----            ------------------- 
    int    object_code        (always 1) 
    int    sub_type        (1: ellipse defined by radii 
                     2: ellipse defined by diameters 
                     3: circle defined by radius 
                     4: circle defined by diameter) 
    int    line_style        (enumeration type) 
    int    thickness        (1/80 inch) 
    int    pen_color        (enumeration type, pen color) 
    int    fill_color        (enumeration type, fill color) 
    int    depth            (enumeration type) 
    int    pen_style        (pen style, not used) 
    int    area_fill        (enumeration type, -1 = no fill) 
    float    style_val        (1/80 inch) 
    int    direction        (always 1) 
    float    angle            (radians, the angle of the x-axis) 
    int    center_x, center_y    (Fig units) 
    int    radius_x, radius_y    (Fig units) 
    int    start_x, start_y    (Fig units; the 1st point entered) 
    int    end_x, end_y        (Fig units; the last point entered) 

Ref: https://sourceforge.net/projects/mcj/

Jumping on to the color related attributes; there are two color fields `pen & fill` where pen is only for text (used to draw object) & fill to fill the region inside object. [1] The total capacity for the color table is 544 `color_table[544]`, out of which 32 are standard colors, the rest is for user color[512]. The Object attribute values must be passing through various functions & be used for different purposes too. Hence we went forward & manipulated the value of color to a negative value, which turned out to be a right hit!

The color value was passed forward to a function put_colorname() in gentikz.c, which takes in a color number as an argument and the same being used to access the structure member `std_color[c+1]` having the values color name, its RGB values etc. As we already know from [1], the capacity for standard color (std_color) is 32, hence anything passed more or less than the limit would go out of bounds. Later, the same issue was also detected by the fuzzer.

Suggested mitigation: There was a bound check present to make sure the color values didn’t cross the max limit (NUM_STD_COLS) anyhow checking for value less than the limit was missed. Adding a lower limit check looked like a proper fix.

As per the project owner, there were many checks employed to detect any invalid values being passed to the object attributes & replace them with the default value of the attribute or simply rejecting the file, but somehow this went unchecked.

Analysis

gef➤  ptype  std_color
type = const struct color_table {
    char name[9];
    float r;
    float g;
    float b;
} [33]

gef➤  p/d c
$1 = -558038585

gef➤  p/d std_color[c+1].name
Cannot access memory at address 0xfffffffce20d9720

gef➤  p/d std_color[-558038585+1].name
Cannot access memory at address 0xfffffffce20d9720
gef➤  p std_color[-10008]
$166 = {
  name = "TPIC Opti",
•	Reads data from fig2dev.c:877 ("TPIC Options:\n")

gef➤  p std_color[-10007]
$167 = {
  name = "    set d",
•	Reads data from fig2dev.c:878 (
" -f font set default font"

gef➤  p std_color[-10004]
$169 = {
  name = "\n--------",
•	Reads data from fig2dev.c:890 (\n------------)

Backtrace:
gef➤  bt
#0  strlen () at ../sysdeps/x86_64/strlen.S:106
#1  0x00007ffff680503f in __GI__IO_fputs (str=0xfffffffce20d9720 , fp=0x7ffff6b5c620 <_IO_2_1_stdout_>) at iofputs.c:33
#2  0x00000000004f48c0 in put_colorname (c=0xdebd01c7) at gentikz.c:1054
#3  0x00000000004f50c8 in set_pattern (pen_color=0x0, fill_style=0x29) at gentikz.c:1159
#4  0x00000000004f53b6 in put_drawcmd (style=0x0, thickness=0x0, pen_color=0x0, fill_color=0x7, fill_style=0x29, style_val=0, has_endcaps=0x0, cap_style=0x0) at gentikz.c:1214
#5  0x00000000004f914f in gentikz_line (l=0x60c00000be00) at gentikz.c:1642
#6  0x00000000004127d4 in gendev_objects (objects=0x7fffffffdcc0, dev=0x7b8000 ) at fig2dev.c:999
#7  0x000000000041125e in main (argc=0x4, argv=0x7fffffffde38) at fig2dev.c:482


Proof of Concept

fig2dev -L tikz $POC

TThe 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-25

Patch Release: 2018-08-26

Public Disclosure: 2018-08-26

Credit

Discovered by ACE Team – Loginsoft