Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

out-of-bounds read in geotag #2036

Closed
kevinbackhouse opened this issue Dec 20, 2021 · 1 comment · Fixed by #2039 or #2037
Closed

out-of-bounds read in geotag #2036

kevinbackhouse opened this issue Dec 20, 2021 · 1 comment · Fixed by #2039 or #2037
Labels
Milestone

Comments

@kevinbackhouse
Copy link
Collaborator

I received this report from Huawei Central software Security Team. It's a bug in samples/geotag.cpp, which is a demo application, so we consider it to be a regular bug, not a security issue.

Hi team,
I identify a global-buffer-overflow at readImageTime in geotag.cpp of Exi=
v2 when fuzzing.

Exiv2 version:
commit fde8ed0
And I also test it on the latest official release version: Exiv2 v0.27.5<ht=
tps://github.com/Exiv2/exiv2/releases/tag/v0.27.5>

Operating system:
Ubuntu 18.04 bionic

Reproduce steps:

  1.   Compile the program with ASAN using AFL++.
    
export AFL_USE_ASAN=1
mkdir build && cd build
CC=afl-cc CXX=afl-c++ cmake ..
make
  1.   Run command below with the POC which is in the attachments.
    
./bin/geotag poc

Report:
The main of the ASAN's log:

==========================
==========================
===============
==15101==ERROR: AddressSanitizer: global-buffer-overflow on address=
 0x000000557ddc at pc 0x00000049934c bp 0x7ffea4a5fa30 sp 0x7ffea4a5f1e0
READ of size 1 at 0x000000557ddc thread T0
    #0 0x49934b in __interceptor_strlen.part.30 (/home/hgh/programs/exiv2_r=
e/build/bin/geotag+0x49934b)
    #1 0x52299f in std::char_traits<char>::length(char const*) /usr/lib/gcc=
/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/char_traits.h:32=
0:9
    #2 0x52299f in std::__cxx11::basic_string<char, std::char_traits<char>,=
 std::allocator<char> >::basic_string(char const*, std::allocator<char> con=
st&) /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits=
/basic_string.h:511
    #3 0x52299f in readImageTime(std::__cxx11::basic_string<char, std::char=
_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<ch=
ar, std::char_traits<char>, std::allocator<char> >*) /home/hgh/programs/exi=
v2_re/samples/geotag.cpp:648
    #4 0x5294d9 in main /home/hgh/programs/exiv2_re/samples/geotag.cpp:863:=
35
    #5 0x7f2059d02bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/c=
su/../csu/libc-start.c:310
    #6 0x41c8a9 in _start (/home/hgh/programs/exiv2_re/build/bin/geotag+0x4=
1c8a9)

0x000000557ddc is located 36 bytes to the left of global variable '<string =
literal>' defined in '/home/hgh/programs/exiv2_re/samples/geotag.cpp:678:36=
' (0x557e00) of size 5
  '<string literal>' is ascii string '.doc'
0x000000557ddc is located 0 bytes to the right of global variable '<string =
literal>' defined in '/home/hgh/programs/exiv2_re/samples/geotag.cpp:634:7'=
 (0x557dc0) of size 28
  '<string literal>' is ascii string 'Exif.Photo.DateTimeOriginal'
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/hgh/programs/exiv2=
_re/build/bin/geotag+0x49934b) in __interceptor_strlen.part.30
Shadow bytes around the buggy address:
  0x0000800a2f60: 00 07 f9 f9 f9 f9 f9 f9 07 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2f70: 02 f9 f9 f9 f9 f9 f9 f9 02 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2f80: 02 f9 f9 f9 f9 f9 f9 f9 02 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2f90: 00 00 03 f9 f9 f9 f9 f9 00 05 f9 f9 f9 f9 f9 f9
  0x0000800a2fa0: 00 00 02 f9 f9 f9 f9 f9 02 f9 f9 f9 f9 f9 f9 f9
=>0x0000800a2fb0: 06 f9 f9 f9 f9 f9 f9 f9 00 00 00[04]f9 f9 f9 f9
  0x0000800a2fc0: 05 f9 f9 f9 f9 f9 f9 f9 05 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2fd0: 00 00 00 f9 f9 f9 f9 f9 05 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2fe0: 03 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
  0x0000800a2ff0: 04 f9 f9 f9 f9 f9 f9 f9 05 f9 f9 f9 f9 f9 f9 f9
  0x0000800a3000: 00 03 f9 f9 f9 f9 f9 f9 00 04 f9 f9 f9 f9 f9 f9
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==15101==ABORTING

Acknowledge for reporting this issue:
[email protected]mailto:[email protected] in Huawei Central software Security Team

@kevinbackhouse
Copy link
Collaborator Author

The bug is here:

} while ( !result && ++dateString );

I think that code is supposed to iterate through the elements of dateStrings:

exiv2/samples/geotag.cpp

Lines 633 to 638 in 6833eca

const char* dateStrings[] =
{ "Exif.Photo.DateTimeOriginal"
, "Exif.Photo.DateTimeDigitized"
, "Exif.Image.DateTime"
, NULL
};

Instead, it's iterating through the characters of the first string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment