Lucene search

K
talosTalos IntelligenceTALOS-2019-0879
HistoryNov 20, 2019 - 12:00 a.m.

xcftools flattenIncrementally rows allocation code execution vulnerability

2019-11-2000:00:00
Talos Intelligence
www.talosintelligence.com
10

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.002 Low

EPSS

Percentile

61.6%

Summary

An exploitable integer overflow vulnerability exists in the flattenIncrementally function in the xcf2png and xcf2pnm binaries of xcftools 1.0.7. An integer overflow can occur while calculating the row’s allocation size, that could be exploited to corrupt memory and eventually execute arbitrary code. In order to trigger this vulnerability, a victim would need to open a specially crafted XCF file.

Tested Versions

xcftools 1.0.7

Product URLs

http://henning.makholm.net/xcftools/

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-680: Integer Overflow to Buffer Overflow

Details

Xcftools is a set of tools for handling Gimp’s XCF files. It provides an xcfinfo tool for extracting information from an XCF file, and xcf2png and xcf2pnm for converting an XCF to PNG or PNM format.

When converting an XCF, the utilities first parse the file using the function getBasicXcfInfo. For each XCF layer, the function computeDimensions is called:

struct tileDimensions {
  struct rect c ;
  unsigned width, height ;
  unsigned tilesx, tilesy ;
  unsigned ntiles ;
};

struct rect {
  int t, b, l, r ;
};

void
computeDimensions(struct tileDimensions *d)
{
  d->c.r = d->c.l + d->width ;                            // [1]
  d->c.b = d->c.t + d->height ;
  d->tilesx = (d->width+TILE_WIDTH-1)/TILE_WIDTH ;
  d->tilesy = (d->height+TILE_HEIGHT-1)/TILE_HEIGHT ;
  d->ntiles = d->tilesx * d->tilesy ;
}

The function takes a structure containing some information about the layer: width, height, horizontal and vertical offset. These values are all gathered from the input file. The code calculates the bounds of the layer by filling the rect structure.

As we can see at [1], the “horizontal offset” (d->c.l) is used together with the layer width, to calculate the “right” field of the rectangle.

When the flattenIncrementally function is called, the size of each row is calculated based on the values r and l alone:

void
flattenIncrementally(struct FlattenSpec *spec,lineCallback callback)
{
  rgba *rows[TILE_HEIGHT] ;
  unsigned i, y, nrows, ncols ;
  struct rect where ;
  struct Tile *tile ;
  static struct Tile toptile ;

  toptile.count = TILE_HEIGHT * TILE_WIDTH ;
  fillTile(&toptile,0);

  for( where.t = spec->dim.c.t; where.t < spec->dim.c.b; where.t=where.b ) {
    where.b = TILE_TOP(where.t)+TILE_HEIGHT ;
    if( where.b > spec->dim.c.b ) where.b = spec->dim.c.b ;
    nrows = where.b - where.t ;
    for( y = 0; y < nrows ; y++ )
      rows[y] = xcfmalloc(4*(spec->dim.c.r-spec->dim.c.l));               // [2]

    for( where.l = spec->dim.c.l; where.l < spec->dim.c.r; where.l=where.r ) {
      ...
      for( y = 0 ; y < nrows ; y++ )
        memcpy(rows[y] + (where.l - spec->dim.c.l),                       // [3]
               tile->pixels + y * ncols, ncols*4);
      ...
    }
    for( y = 0 ; y < nrows ; y++ )
      callback(spec->dim.width,rows[y]);                                  // [4]
  }
}

At [2], a row is allocated using the width multiplied by 4. This operation doesn’t take integer overflows into account, so any width larger than 0x3fffffff would result in an overflow.

Any logic writing to rows after this point, will risk corrupting the heap, leading to arbitrary code execution. There are at least two paths for corruption, at [3] and [4] (which would be triggered by any callback writing to a row, for example by optimistic_palette_callback which calls palettify_row).

Timeline

2019-07-31 - Initial contact
2019-08-07 - Plain text file sent
2019-10-02 - 60+ day follow up
2019-10-21 - 90 day notice
2019-11-21 - Public release

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.002 Low

EPSS

Percentile

61.6%