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

AddressSanitizer: heap-buffer-overflow on IccTagXml #55

Open
RootUp opened this issue Oct 31, 2023 · 4 comments
Open

AddressSanitizer: heap-buffer-overflow on IccTagXml #55

RootUp opened this issue Oct 31, 2023 · 4 comments

Comments

@RootUp
Copy link

RootUp commented Oct 31, 2023

Tested on OS - Ubuntu 22.04 LTS 5.15.0-72-generic #79-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

A heap based buffer overflow was identified on IccToXml while fuzzing the vulnerability is triggered with a crafted .icc profile file. Attaching the same for reference.

GDB:

(gdb) r sample.icc /dev/null 
Starting program: /DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml sample.icc /dev/null
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f6bc9c in icCurvesToXml (xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., szName=0x7ffff7f99874 "MCurves", pCurves=pCurves@entry=0x61f7a0, numCurve=<optimized out>, numCurve@entry=3, nType=nType@entry=icConvertVariable, blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991
2991	      IIccExtensionTag *pTag = pCurves[i]->GetExtension();
(gdb) 
(gdb) bt
#0  0x00007ffff7f6bc9c in icCurvesToXml (
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., szName=0x7ffff7f99874 "MCurves", pCurves=pCurves@entry=0x61f7a0, numCurve=<optimized out>, numCurve@entry=3, 
    nType=nType@entry=icConvertVariable, blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991
#1  0x00007ffff7f6cfc7 in icMBBToXml (
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., pMBB=pMBB@entry=0x61f4b0, nType=nType@entry=icConvertVariable, blanks=..., bSaveGridPoints=true)
    at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3151
#2  0x00007ffff7f6f86c in CIccTagXmlLutAtoB::ToXml (this=0x61f4b0, 
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3798
#3  0x00007ffff7f58331 in CIccProfileXml::ToXmlWithBlanks (this=<optimized out>, this@entry=0x7fffffffe1e8, xml=..., blanks=...)
    at /DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:264
#4  0x00007ffff7f557ec in CIccProfileXml::ToXml (this=0x7fffffffe1e8, 
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"...) at /DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:79
#5  0x0000000000403696 in main (argc=<optimized out>, argv=0x7fffffffe3b8) at /DemoIccMAX/IccXML/CmdLine/IccToXml/IccToXml.cpp:38
(gdb) i r
rax            0x61f7a0            6420384
rbx            0x1                 1
rcx            0x1                 1
rdx            0x624               1572
rsi            0x60c010            6340624
rdi            0x0                 0
rbp            0x1                 0x1
rsp            0x7fffffffd3f0      0x7fffffffd3f0
r8             0x624580            6440320
r9             0x0                 0
r10            0x7fffffffc9b0      140737488341424
r11            0xb6ff62935fcf2779  -5260377454638323847
r12            0x7fffffffd488      140737488344200
r13            0x61f7e0            6420448
r14            0x6                 6
r15            0x7fffffffd478      140737488344184
rip            0x7ffff7f6bc9c      0x7ffff7f6bc9c <icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)+588>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) 
rax            0x61f7a0            6420384
rbx            0x1                 1
rcx            0x1                 1
rdx            0x624               1572
rsi            0x60c010            6340624
rdi            0x0                 0
rbp            0x1                 0x1
rsp            0x7fffffffd3f0      0x7fffffffd3f0
r8             0x624580            6440320
r9             0x0                 0
r10            0x7fffffffc9b0      140737488341424
r11            0xb6ff62935fcf2779  -5260377454638323847
r12            0x7fffffffd488      140737488344200
r13            0x61f7e0            6420448
r14            0x6                 6
r15            0x7fffffffd478      140737488344184
rip            0x7ffff7f6bc9c      0x7ffff7f6bc9c <icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)+588>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb)

ASAN:

==115400==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000118 at pc 0x7ffff7f03d71 bp 0x7fffffffb7d0 sp 0x7fffffffb7c8
READ of size 8 at 0x602000000118 thread T0
    #0 0x7ffff7f03d70 in icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991:32
    #1 0x7ffff7f07440 in icMBBToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, CIccMBB*, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3151:12
    #2 0x7ffff7f10e17 in CIccTagXmlLutAtoB::ToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3798:13
    #3 0x7ffff7ebff07 in CIccProfileXml::ToXmlWithBlanks(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:264:27
    #4 0x7ffff7eb930e in CIccProfileXml::ToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:79:10
    #5 0x4d3da5 in main DemoIccMAX/IccXML/CmdLine/IccToXml/IccToXml.cpp:38:16
    #6 0x7ffff7319d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x7ffff7319e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #8 0x4224d4 in _start (DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml+0x4224d4)

0x602000000118 is located 0 bytes to the right of 8-byte region [0x602000000110,0x602000000118)
allocated by thread T0 here:
    #0 0x4d128d in operator new[](unsigned long) (DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml+0x4d128d)
    #1 0x7ffff7d260b8 in CIccMBB::NewCurvesM() DemoIccMAX/IccProfLib/IccTagLut.cpp:3595:15
    #2 0x7ffff7d260b8 in CIccTagLutAtoB::Read(unsigned int, CIccIO*) DemoIccMAX/IccProfLib/IccTagLut.cpp:3877:27
    #3 0x7ffff7c240e3 in CIccProfile::LoadTag(IccTagEntry*, CIccIO*, bool) DemoIccMAX/IccProfLib/IccProfile.cpp:1188:14
    #4 0x7ffff7c275d0 in CIccProfile::Read(CIccIO*, bool) DemoIccMAX/IccProfLib/IccProfile.cpp:748:10

SUMMARY: AddressSanitizer: heap-buffer-overflow DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991:32 in icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
Shadow bytes around the buggy address:
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff8000: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
  0x0c047fff8010: fa fa fd fa fa fa fd fa fa fa 00 04 fa fa 00 fa
=>0x0c047fff8020: fa fa 00[fa]fa fa fd fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8070: 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
  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
==115400==ABORTING

sample.icc.zip

@xsscx
Copy link
Collaborator

xsscx commented May 5, 2024

This is an interesting .icc profile and it breaks many other implementations :-)

I added some code to bailout early and fail to read the file [seperate issue to be resolved] in PR #64.

It is a defensive patch that will be evaded with more fuzzing.

@xsscx
Copy link
Collaborator

xsscx commented Jul 13, 2024

Hello @RootUp

I will request a CVE for this issue.

CVE Summary

The AddressSanitizer report indicates a heap-buffer-overflow issue in the icCurvesToXml function, specifically an attempt to access memory just outside the bounds of an allocated buffer based on 889db62.

Analysis

Call Stack: icCurvesToXml calls are seen from several functions (icMBBToXml, CIccTagXmlLutAtoB::ToXml, CIccProfileXml::ToXmlWithBlanks, CIccProfileXml::ToXml, and main).
The allocation of the memory is tracked back to CIccMBB::NewCurvesM at IccTagLut.cpp:3595:15.

The function icCurvesToXml is attempting to access or iterate over an array or buffer but reads past its end.
The allocation in CIccMBB::NewCurvesM indicates memory allocated for CIccCurve objects may be insufficient or improperly managed, leading to an out-of-bounds read.

Proposed Fixes

Ensure that the CIccMBB::NewCurvesM function allocates memory for the array of LPIccCurve pointers.
Add proper memory allocation for each CIccCurve object after calling NewCurvesM to prevent access to uninitialized pointers.

Add checks in icCurvesToXml to verify that each CIccCurve pointer is properly initialized before accessing it.
Add error handling to gracefully handle cases where pCurves[i] is not initialized.

Error messages in the icCurvesFromXml function to provide clearer diagnostics when XML parsing fails.

Metrics

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

@xsscx
Copy link
Collaborator

xsscx commented Sep 14, 2024

@RootUp

Updated on 14 Sep 2024

RE: CVE Request 1699842 for CVE ID Request

I have requested a status from CVE.

@maxderhak
Copy link
Contributor

Is this issue still open or has it been indirectly resolved?

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

3 participants