Talos Vulnerability Report

TALOS-2018-0531

NASA CFITSIO `ffghbn` and `ffghtb` Stack Overflow Code Execution Vulnerabilities

April 12, 2018
CVE Number

CVE-2018-3848 - CVE-2018-3849

Summary

Exploitable buffer overflow vulnerabilities exist in image parsing functionality of the CFITSIO library version 3.42. Specially crafted images parsed via the library, can cause a stack-based buffer overflow overwriting arbitrary data. An attacker can deliver an FIT image to trigger this vulnerability and potentially gain code execution.

Tested Versions

NASA CFITSIO 3.42

Product URLs

https://heasarc.gsfc.nasa.gov/fitsio/fitsio.html

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-121: Stack-based Buffer Overflow

Details

CFITSIO is a library written in C, for reading and writing data files in FITS data format. This format is the standard astronomical data format endorsed by both NASA and the IAU. FITS is primarily designed to store scientific data sets consisting of multi-dimensional arrays and 2-dimensional tables containing rows and columns of data. This software is used extensively and is the primary library used when writing an application to handle the FITS format. Among other things CFITSIO is widely used in ground-based observatories as well as orbiting astronomical observatories in their ground data processing pipeline systems. For more users see, https://heasarc.gsfc.nasa.gov/docs/software/fitsio/major_users.html.

The vulnerabilities arise in the ffghbn and ffghtb function.

CVE-2018-3848 - ffghbn

The ffghbn responsible for getting data from a binary table inside a FITS image. This function’s main purpose is to parse the header keywords and validate them to ensure they conform to the FITS standard. The function also returns the necessary data to parse the rest of the table. Below is a look at the function responsible for parsing.

int ffghbn

    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];  [0]
    char message[81];


    /* read the first keyword of the extension */
    ffgkyn(fptr, 1, name, value, comm, status);                         [1]

    if (!strcmp(name, "XTENSION"))
    {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
             
            if ( (value[0] != '\'')   ||  /* first char must be a quote */    [2]
                 ( strcmp(xtension, "BINTABLE") &&
                   strcmp(xtension, "A3DTABLE") &&
                   strcmp(xtension, "3DTABLE")
                 ) )
            {
                sprintf(message,
                "This is not a BINTABLE extension: %s", value);                [3]
                ffpmsg(message);
                return(*status = NOT_BTABLE);
            }
    }

Location 0 defines the buffer variables used throughout the function. At 3, we see the function read in the keyword directly from the header. This value is then compared with the expected value, 2, and if it does not match we fall into the if statement. There is then a vulnerable call to the function sprintf, 3. Looking at the sprintf manual page it states,

 The sprintf() functions are easily misused in a manner which enables malicious users to arbitrarily change
 a running program's functionality through a buffer overflow attack.  Because sprintf() assume an infinite-
 ly long string, callers must be careful not to overflow the actual space; this is often hard to assure.  For safety, programmers should use the snprintf() interface instead.

Due to the lack of bounds checking as stated above this call will cause a buffer overflow. The name parameter is taken directly from the user and although restricted in size to 75 bytes at 0, the added error message makes it longer than the 81 bytes of available space in the buffer. This causes an exploitable stack based buffer overflow.

CVE-2018-3849 - ffghtb

This vulnerability is similar to the vulnerability discussed in CVE-2018-3848. This instance occurs in the ffghtb function responsible for the parsing of an ascii table inside a FITS image.

int ffghtb(

char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];        [4]
char xtension[FLEN_VALUE], message[81];

/* read the first keyword of the extension */
ffgkyn(fptr, 1, name, value, comm, status);                              [5]

if (!strcmp(name, "XTENSION"))
{
        if (ffc2s(value, xtension, status) > 0)  
        {

        if ( (value[0] != '\'')   ||  /* first char must be a quote */    [6]
             ( strcmp(xtension, "TABLE") ) )
        {
            sprintf(message,
            "This is not a TABLE extension: %s", value);                  [7]
            ffpmsg(message);
            return(*status = NOT_ATABLE);
        }
}

The same vulnerable pattern as above is present. The buffers are defined at 4 and at location 5 the value is read in from the image. Location 6 compares the value for validity and if the check fails it falls into the vulnerable sprintf call, 7.

Timeline

2018-02-23 - Vendor Disclosure
2018-03-21 - Vendor patched
2018-04-12 - Public Release

Credit

Discovered by Tyler Bohan of Cisco Talos.