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

CVE-2017-17725: exiv2 library: heap-buffer-overflow in Exiv2::getULong (types.cpp) #188

Closed
youwei1988 opened this issue Dec 12, 2017 · 17 comments
Assignees
Milestone

Comments

@youwei1988
Copy link

Description

on exiv2 0.26 (the latest version):

there is a heap-based buffer overflow in the Exiv2::getULong function (src/types.cpp), which can be triggered by crafted tiff file.

Note that this vulnerability is different from CVE-2017-14864 (issue 73), which is a an invalid memory address dereference.

./bin/exiv2 poc_3.tiff

=================================================================
==16413==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ef73 at pc 0x7f990f1613de bp 0x7ffee8097c30 sp 0x7ffee8097c20
READ of size 4 at 0x60200000ef73 thread T0
#0 0x7f990f1613dd in Exiv2::getULong(unsigned char const*, Exiv2::ByteOrder) /home/fuzz/exiv2/master/src/types.cpp:246
#1 0x7f990f053d2c in Exiv2::Jp2Image::readMetadata() /home/fuzz/exiv2/master/src/jp2image.cpp:271
#2 0x469742 in Action::Print::printSummary() /home/fuzz/exiv2/master/src/actions.cpp:288
#3 0x46e2e7 in Action::Print::run(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&) /home/fuzz/exiv2/master/src/actions.cpp:240
#4 0x40c18b in main /home/fuzz/exiv2/master/src/exiv2.cpp:166
#5 0x7f990e33d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#6 0x40cd48 in _start (/home/fuzz/exiv2/master/bin/exiv2+0x40cd48)

0x60200000ef75 is located 0 bytes to the right of 5-byte region [0x60200000ef70,0x60200000ef75)
allocated by thread T0 here:
#0 0x7f990faed6b2 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x996b2)
#1 0x7f990f053c49 in Exiv2::DataBuf::DataBuf(long) /home/fuzz/exiv2/master/include/exiv2/types.hpp:206
#2 0x7f990f053c49 in Exiv2::Jp2Image::readMetadata() /home/fuzz/exiv2/master/src/jp2image.cpp:269

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/fuzz/exiv2/master/src/types.cpp:246 Exiv2::getULong(unsigned char const*, Exiv2::ByteOrder)
Shadow bytes around the buggy address:
0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[05]fa
0x0c047fff9df0: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa fd fd
0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 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
==16413==ABORTING

PoC
PoC: https://github.com/youwei1988/poc/tree/master/exiv2/poc_3.tiff

Author
Credit to Wei You, please contact [email protected] for more details.

@D4N
Copy link
Member

D4N commented Dec 12, 2017

Thanks for your report. With which version of exiv2 did you try this? The v0.26 git tag, the head of the 0.26 branch or the head of master (or something else)?

@youwei1988
Copy link
Author

@D4N Thanks for reply.
I tried both v0.26 git tag and the branch of head of master, they are both affected. I will try more versions later.

@clanmills clanmills self-assigned this Dec 12, 2017
@clanmills
Copy link
Collaborator

clanmills commented Dec 12, 2017

I'm working on 'master' and unable to reproduced this on Linux/MacOS/Cygwin. Here's my result:

575 rmills@rmillsmm-w7:~/gnu/github/exiv2/exiv2 $ exiv2 poc_3.tiff
Exiv2 exception in print action for file poc_3.tiff:
corrupted image metadata
576 rmills@rmillsmm-w7:~/gnu/github/exiv2/exiv2 $

I'm not going to close this issue as it deserves more investigation. I'm currently working on long-term maintenance of our msvc/ and autotools/ and buildserver support. I will add the file poc_3.tiff to our test suite to ensure that this issue does not regress.

May I ask you to name give the "poc" files more meaningful/unique names that we can track. For example, add the date (in iso format). poc_2018-12-12

@youwei1988
Copy link
Author

@clanmills

Thank you very much for your testing.
I have git pull the latest version of the 'master' and still got the heap-buffer-overflow error.

Did you build exiv2 with Address Sanitizer?
Like: CC=gcc CXX=g++ CFLAGS="-fsanitize=address" CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" cmake . && make

Also, I have named the poc with poc_2018-12-12_issue188.
Here is the link: https://github.com/youwei1988/poc/blob/master/exiv2/poc_2018-12-12_issue188

Note: please do not use wget to get the file from the URL directly, it will not be the one I uploaded, which will cause the result "Exiv2 exception in print action for file...". Please click the link and press the download button to get the file I submitted in the github.

For your convenience, I also uploaded the poc to https://bugzilla.redhat.com/attachment.cgi?id=1366916, which can be get directly by using wget.

Thanks again.

@clanmills
Copy link
Collaborator

Thanks @youwei1988. I will investigate all your concerns. And thank you for using my file-date suggestion. As I said: this issue as it deserves more investigation I'll build the code as you've suggested.

@piponazo
Copy link
Collaborator

Hi, I could reproduce the issue in my Linux box:

  • Xubuntu 17.04
  • Gcc 7.2

I would be happy to work on this issue :)

@clanmills
Copy link
Collaborator

@piponazo Happy to accept your offer. I wonder why you've reproduced this and I have not. Puzzling. I'm using the latest MacOS-X + clang. Ubuntu 16.04LTS + GCC 5.something.

@piponazo
Copy link
Collaborator

Did you try to do what @youwei1988 suggested ? These are the exact steps I did to reproduce the issue:

rm -rf build
mkdir build && cd build
conan install ..
CFLAGS="-fsanitize=address" CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" cmake .. && make -j4
# run the command

@piponazo
Copy link
Collaborator

Note that if you use clang instead of gcc you might need to use other flags. I have been a long time without playing with sanitizers.

@piponazo piponazo self-assigned this Dec 14, 2017
@piponazo
Copy link
Collaborator

I have been debugging the code and I think I have detected where is the issue.

In the file jp2image.cpp line 254 we are reading the Jp2BoxHeader "subBoxes". After reading some subboxes we reach a case where its lenght is 4294967293. Then in lines 270 and 271 we hit the issue.

I am not very sure about how to fix the issue. @D4N maybe you can give me some hints about how to fix these issues since you have been fixing many of them lately ;)

@piponazo
Copy link
Collaborator

This is the output that I get (after adding the DEBUG compiler definition: #192 ):

(conan) ✔ /media/linuxDev/programming/exiv2/build [bug188 L|✚ 2…1⚑ 1] 
23:57 $ bin/exiv2 ../poc_2018-12-12_issue188 
Exiv2::Jp2Image::readMetadata: Reading JPEG-2000 file ../poc_2018-12-12_issue188
Exiv2::Jp2Image::readMetadata: Position: 20 box type: jp2h length: 20
Exiv2::Jp2Image::readMetadata: JP2Header box found
Exiv2::Jp2Image::readMetadata: subBox = �� length = 1785737760
Exiv2::Jp2Image::readMetadata: Position: 40 box type: jp2h length: 45
Exiv2::Jp2Image::readMetadata: JP2Header box found
Exiv2::Jp2Image::readMetadata: subBox = ihdr length = 22
Exiv2::Jp2Image::readMetadata: Ihdr data found
Exiv2::Jp2Image::readMetadata: subBox = colr length = 4294967293
Exiv2::Jp2Image::readMetadata: Color data found
=================================================================
==27597==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000002d5 at pc 0x7f66b46405fc bp 0x7fffbffbfb70 sp 0x7fffbffbfb60
READ of size 1 at 0x6020000002d5 thread T0
    #0 0x7f66b46405fb in Exiv2::getULong(unsigned char const*, Exiv2::ByteOrder) /media/linuxDev/programming/exiv2/src/types.cpp:246
    #1 0x7f66b45c00fd in Exiv2::Jp2Image::readMetadata() /media/linuxDev/programming/exiv2/src/jp2image.cpp:276
    #2 0x56233be5d018 in Action::Print::printSummary() /media/linuxDev/programming/exiv2/src/actions.cpp:288
    #3 0x56233be5be10 in Action::Print::run(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /media/linuxDev/programming/exiv2/src/actions.cpp:240
    #4 0x56233be3bc87 in main /media/linuxDev/programming/exiv2/src/exiv2.cpp:166
    #5 0x7f66b38ad1c0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x211c0)
    #6 0x56233be3b509 in _start (/media/linuxDev/programming/exiv2/build/bin/exiv2+0x2c509)
...

@D4N
Copy link
Member

D4N commented Dec 14, 2017

The problem is two-fold:

  1. an integer overflows: subBox.length is a uint32_t whose largest value is 4294967295, subBox.length is 4294967293. So once you add more than 2 to it, the whole thing overflows, which happens in line 269 of jp2image.cpp.
  2. subBox.length is used to create a new DataBuf, but due to the overflow it has only a size of 5. However the invocation in line 271 wants to extract 4 bytes from the DataBuf data at an offset of pad (which is 3) so that creates an out of bounds read, which ASAN catches.

I think there are two things that should be done here:

  1. make sure that the addition in line 269 does not overflow
  2. verify that subBox.length is not out of bounds of the image file, if that makes sense (I have no clue what jpeg subboxes are)

@clanmills
Copy link
Collaborator

I can't remember what a box is either - something in the architecture on the JPEG2000 file format.

This is very good work indeed, @D4N. Thanks you very much.

May I say something concerning 32bit vs 64bit? There's an overflow detect in tiff visitor_int.cpp about line 1523 that's based on uintptr_t. It's working OK in 64 bits, and not in 32 bits (on MSVC for sure, I haven't tested other platforms). Do you think it's possible to move the overflow detector into a utility function which we can call from different locations. By having the detector in a single function, we can "tune" it for 32/64 bit builds.

Gentlemen (@D4N and @piponazo) Thank You very much indeed for all your hard work. Believe me, it is appreciated.

@D4N
Copy link
Member

D4N commented Dec 15, 2017

Coincidentally, I have started just started working on such an overflow detector on Wednesday. I'll make an issue/PR about it soon, since there are some details to discuss about it (especially concerning how we are going to handle failures).

@D4N
Copy link
Member

D4N commented Jan 5, 2018

I think we can close this, or is there anything left to do?

@youwei1988
Copy link
Author

I have tested the latest version and found this vulnerability has been fixed. Thanks for all your work.

@D4N D4N closed this as completed Jan 6, 2018
@ghost
Copy link

ghost commented Feb 13, 2018

This has been assigned CVE-2017-17725

@D4N D4N changed the title exiv2 library: heap-buffer-overflow in Exiv2::getULong (types.cpp) CVE-2017-17725: exiv2 library: heap-buffer-overflow in Exiv2::getULong (types.cpp) Feb 13, 2018
a17r pushed a commit to a17r/exiv2 that referenced this issue Feb 16, 2018
a17r pushed a commit to a17r/exiv2 that referenced this issue Feb 16, 2018
a17r pushed a commit to a17r/exiv2 that referenced this issue Feb 27, 2018
@clanmills clanmills added this to the v0.27 milestone Nov 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants