Opened 5 years ago

Closed 5 years ago

#7248 closed defect (fixed)

A heap-buffer-overflow in revmemcpy() of gdal-2.2.3

Reported by: leonzhao7 Owned by: warmerdam
Priority: high Milestone: 2.3.0
Component: default Version: 2.2.3
Severity: critical Keywords: overflow
Cc:

Description

Overview

The revmemcpy() function at frmts/grib/degrib18/degrib/memendian.c:113 in gdal 2.2.3 may result a heap-buffer-overflow via a crafted file.

Tested Version

gdal 2.2.3

Steps to Reproduce

./gdalinfo $POC

Additional info

Ubuntu 16.04, x64

Detail

The revmemcpy function assume that Dst is allocated to a size of Src, so it does not validate input parameters. But an attacker can destroy this assumption with a crafted file, he can controll the value of len and trigger the overflow vulnerability in the for loop.

void *revmemcpy (void *Dst, void *Src, const size_t len)
{
   size_t j;            /* Byte count */
   char *src = (char *) Src; /* Allows us to treat Src as an array of char. */
   char *dst = (char *) Dst; /* Allows us to treat Dst as an array of char. */

   src = src + len - 1;
   for (j = 0; j < len; ++j) {
      *(dst++) = *(src--);
   }
   return Dst;
}

Crash Information

The output of gdalinfo with address sanitizer enabled

/opt/asan/gdal/bin/gdalinfo gdal-memendian-revmemcpy-113-overflow 
Un-handled possible ensemble section center 0 subcenter 21
Un-handled possible ensemble section center 0 subcenter 21
Warning: Inside GRIB2Inventory, Message # 3
ERROR: Ran out of file reading SECT0
There were 63 trailing bytes in the file.
Un-handled possible ensemble section center 0 subcenter 21
Driver: GRIB/GRIdded Binary (.grb)
Files: gdal-memendian-revmemcpy-113-overflow
Size is 29562, 26948
Coordinate System is:
GEOGCS["Coordinate System imported from GRIB file",
    DATUM["unknown",
        SPHEROID["Spheroid imported from GRIB file",6378160,298.2539162964695]],
    PRIMEM["Greenwich",0],
    UNIT["degree",0.0174532925199433]]
Origin = (7353.321500000000015,7640.789000000000669)
Pixel Size = (23.295000000000002,-25.475999999999999)
Corner Coordinates:
Upper Left  (    7353.322,    7640.789) 
Lower Left  (    7353.322, -678886.459) 
Upper Right (  696000.111,    7640.789) 
Lower Right (  696000.111, -678886.459) 
Center      (  351676.717, -335622.835) 
Band 1 Block=29562x1 Type=Float64, ColorInterp=Undefined
  Description = 5397[-] var21 (reserved)
  Metadata:
    GRIB_COMMENT=undefined [-]
    GRIB_ELEMENT=var255
    GRIB_FORECAST_SECONDS=323820 sec
    GRIB_REF_TIME=  1613942460 sec UTC
    GRIB_SHORT_NAME=5397-var21
    GRIB_UNIT=[-]
    GRIB_VALID_TIME=  1614266280 sec UTC
Band 2 Block=29562x1 Type=Float64, ColorInterp=Undefined
  Description = 5397[-] var21 (reserved)
Un-handled possible ensemble section center 0 subcenter 21
numPts * (numBits in a Group) + # of unused bits -138713471 != # of available bits -88
=================================================================
==44642==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61100000577d at pc 0x00000060d287 bp 0x7ffd915401d0 sp 0x7ffd915401c0
READ of size 1 at 0x61100000577d thread T0
    #0 0x60d286 in revmemcpy degrib18/degrib/memendian.c:113
    #1 0x60d537 in memBitRead degrib18/degrib/memendian.c:227
    #2 0xe2716e in ReadGrib1Sect4 degrib18/degrib/degrib1.cpp:1601
    #3 0xe2871b in ReadGrib1Record(DataSource&, signed char, double**, unsigned int*, grib_MetaData*, IS_dataType*, int*, unsigned int, double, double) degrib18/degrib/degrib1.cpp:1831
    #4 0xe2c717 in ReadGrib2Record degrib18/degrib/degrib2.cpp:887
    #5 0x4a49f6 in GRIBRasterBand::ReadGribData(DataSource&, int, int, double**, grib_MetaData**) /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:398
    #6 0x4a3aa2 in GRIBRasterBand::LoadData() /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:255
    #7 0x4a43ed in GRIBRasterBand::GetNoDataValue(int*) /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:333
    #8 0x902f91 in GDALGetRasterNoDataValue /root/gdal-2.2.3/gcore/gdalrasterband.cpp:1644
    #9 0x4132f4 in GDALInfo /root/gdal-2.2.3/apps/gdalinfo_lib.cpp:959
    #10 0x40f260 in main /root/gdal-2.2.3/apps/gdalinfo_bin.cpp:211
    #11 0x7fdb72fd282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #12 0x40e7a8 in _start (/opt/asan/gdal/bin/gdalinfo+0x40e7a8)

0x61100000577d is located 1 bytes to the right of 252-byte region [0x611000005680,0x61100000577c)
allocated by thread T0 here:
    #0 0x7fdb7504d961 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98961)
    #1 0xe277b3 in ReadGrib1Record(DataSource&, signed char, double**, unsigned int*, grib_MetaData*, IS_dataType*, int*, unsigned int, double, double) degrib18/degrib/degrib1.cpp:1713
    #2 0xe2c717 in ReadGrib2Record degrib18/degrib/degrib2.cpp:887
    #3 0x4a49f6 in GRIBRasterBand::ReadGribData(DataSource&, int, int, double**, grib_MetaData**) /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:398
    #4 0x4a3aa2 in GRIBRasterBand::LoadData() /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:255
    #5 0x4a43ed in GRIBRasterBand::GetNoDataValue(int*) /root/gdal-2.2.3/frmts/grib/gribdataset.cpp:333
    #6 0x902f91 in GDALGetRasterNoDataValue /root/gdal-2.2.3/gcore/gdalrasterband.cpp:1644
    #7 0x4132f4 in GDALInfo /root/gdal-2.2.3/apps/gdalinfo_lib.cpp:959
    #8 0x40f260 in main /root/gdal-2.2.3/apps/gdalinfo_bin.cpp:211
    #9 0x7fdb72fd282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow degrib18/degrib/memendian.c:113 revmemcpy
Shadow bytes around the buggy address:
  0x0c227fff8a90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8aa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8ab0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8ad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff8ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[04]
  0x0c227fff8af0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c227fff8b00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c227fff8b10: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
  0x0c227fff8b20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c227fff8b30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
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
==44642==ABORTING

Attachments (1)

gdal-memendian-revmemcpy-113-overflow (1.7 KB ) - added by leonzhao7 5 years ago.
POC file that crashing gdal-2.2.3 in memendian.c:113 revmemcpyRay()

Download all attachments as: .zip

Change History (2)

by leonzhao7, 5 years ago

POC file that crashing gdal-2.2.3 in memendian.c:113 revmemcpyRay()

comment:1 by Even Rouault, 5 years ago

Milestone: 2.3.0
Resolution: fixed
Status: newclosed

The issue is no longer reproducible with GDAL trunk. Hundreds of security related fixes have been done in trunk since GDAL 2.2, so I'd suggest you to test against trunk

Note: See TracTickets for help on using tickets.