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-
-
- The very first line is a comment line specifying the name and version: #FIG 3.2
- The next few lines speak about few specifications of the fig file document.
(orientation, justification, units, papersize, multiple-page etc.)
- 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