Bug 1192382 - (CVE-2020-23109) VUL-0: CVE-2020-23109: libheif: buffer overflow vulnerability in heif_colorconversion.cc may lead to DoS and Information Disclosure
(CVE-2020-23109)
VUL-0: CVE-2020-23109: libheif: buffer overflow vulnerability in heif_colorco...
Status: RESOLVED FIXED
Classification: Novell Products
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents
unspecified
Other Other
: P3 - Medium : Normal
: ---
Assigned To: Petr Gajdos
Security Team bot
https://smash.suse.de/issue/314158/
CVSSv3.1:SUSE:CVE-2020-23109:4.4:(AV:...
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2021-11-05 09:48 UTC by Thomas Leroy
Modified: 2022-10-27 07:48 UTC (History)
5 users (show)

See Also:
Found By: Security Response Team
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Leroy 2021-11-05 09:48:14 UTC
rh#2020244

Buffer overflow vulnerability in function convert_colorspace in heif_colorconversion.cc in libheif v1.6.2, allows attackers to cause a denial of service and disclose sensitive information, via a crafted HEIF file.

Bug report [0]

[0] https://github.com/strukturag/libheif/issues/207

References:
https://bugzilla.redhat.com/show_bug.cgi?id=2020244
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-23109
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-23109
Comment 1 Thomas Leroy 2021-11-05 09:53:30 UTC
This vulnerability could affect SUSE:SLE-15-SP4:GA and openSUSE:Factory. 
But the bug report [0] is still opened, and the master branch seems still vulnerable (to my humble opinion). However, I still haven't managed to reproduce the bug on master branch, and in a vulnerable version. I am still investigating.
Comment 2 Petr Gajdos 2022-06-07 11:02:06 UTC
I have tried to reproduce with version 1.6.2 (built against x265 and libde265 from NON_Public:multimedia:tumbleweed), and I succeeded:

$ valgrind  -q ./heif-convert /192382/heap-overflow.poc out.png
File contains 1 images
==2255== Invalid read of size 2
==2255==    at 0x48A2E3C: Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<heif::HeifPixelImage const> const&, heif::ColorState, heif::ColorConversionOptions) (heif_colorconversion.cc:2263)
==2255==    by 0x489D86D: UnknownInlinedFun (heif_colorconversion.cc:2446)
==2255==    by 0x489D86D: heif::convert_colorspace(std::shared_ptr<heif::HeifPixelImage> const&, heif_colorspace, heif_chroma) (heif_image.cc:396)
==2255==    by 0x48A80E4: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:896)
==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
==2255==    by 0x10F626: main (in /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
==2255==  Address 0x535037e is 6,158 bytes inside a block of size 6,159 alloc'd
==2255==    at 0x484A20F: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255==    by 0x4898FEA: heif::HeifPixelImage::add_plane(heif_channel, int, int, int) (heif_image.cc:151)
==2255==    by 0x48868DB: heif_image_add_plane (heif.cc:745)
==2255==    by 0x48A8936: UnknownInlinedFun (heif_decoder_libde265.cc:126)
==2255==    by 0x48A8936: libde265_v1_decode_image(void*, heif_image**) (heif_decoder_libde265.cc:306)
==2255==    by 0x488E86E: heif::HeifContext::decode_image(unsigned int, std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const (heif_context.cc:944)
==2255==    by 0x48A8097: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
==2255==    by 0x488D5CE: heif::HeifContext::decode_image(unsigned int, std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const (heif_context.cc:1017)
==2255==    by 0x48A8097: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
==2255==    by 0x10F626: main (in /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
==2255== 
==2255== Invalid read of size 2
==2255==    at 0x48A2E4C: Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<heif::HeifPixelImage const> const&, heif::ColorState, heif::ColorConversionOptions) (heif_colorconversion.cc:2264)
==2255==    by 0x489D86D: UnknownInlinedFun (heif_colorconversion.cc:2446)
==2255==    by 0x489D86D: heif::convert_colorspace(std::shared_ptr<heif::HeifPixelImage> const&, heif_colorspace, heif_chroma) (heif_image.cc:396)
==2255==    by 0x48A80E4: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:896)
==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
==2255==    by 0x10F626: main (in /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
==2255==  Address 0x535037e is 6,158 bytes inside a block of size 6,159 alloc'd
==2255==    at 0x484A20F: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2255==    by 0x4898FEA: heif::HeifPixelImage::add_plane(heif_channel, int, int, int) (heif_image.cc:151)
==2255==    by 0x48868DB: heif_image_add_plane (heif.cc:745)
==2255==    by 0x48A8936: UnknownInlinedFun (heif_decoder_libde265.cc:126)
==2255==    by 0x48A8936: libde265_v1_decode_image(void*, heif_image**) (heif_decoder_libde265.cc:306)
==2255==    by 0x488E86E: heif::HeifContext::decode_image(unsigned int, std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const (heif_context.cc:944)
==2255==    by 0x48A8097: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
==2255==    by 0x488D5CE: heif::HeifContext::decode_image(unsigned int, std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const (heif_context.cc:1017)
==2255==    by 0x48A8097: heif::HeifContext::Image::decode_image(std::shared_ptr<heif::HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
==2255==    by 0x10F626: main (in /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)

[..]  lot of  'Use of uninitialised value' in PngEncoder::Encode()

==2255== 
Written to out.png
$

However, I cannot reproduce same way anymore when I update to latest 1.12.0:

$ valgrind  -q ./heif-convert /192382/heap-overflow.poc test.png
File contains 1 images
Could not decode image: 0: Unsupported feature: Unsupported color conversion
$

The key is in the following commit:
https://github.com/strukturag/libheif/commit/bca0162018df9a32d21c05aad1fa203881fa7813
which applied on top of 1.6.2 gives the same result as 1.12.0. This means the heap overflow is fixed or at least hidden by the commit in question.
Comment 8 Thomas Leroy 2022-10-24 16:57:09 UTC
Cf analysis reported upstream [0].
[0] https://github.com/strukturag/libheif/issues/207#issuecomment-1289322472
Comment 9 Thomas Leroy 2022-10-25 14:49:44 UTC
(In reply to Petr Gajdos from comment #2)
> I have tried to reproduce with version 1.6.2 (built against x265 and
> libde265 from NON_Public:multimedia:tumbleweed), and I succeeded:
> 
> $ valgrind  -q ./heif-convert /192382/heap-overflow.poc out.png
> File contains 1 images
> ==2255== Invalid read of size 2
> ==2255==    at 0x48A2E3C:
> Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<heif::
> HeifPixelImage const> const&, heif::ColorState,
> heif::ColorConversionOptions) (heif_colorconversion.cc:2263)
> ==2255==    by 0x489D86D: UnknownInlinedFun (heif_colorconversion.cc:2446)
> ==2255==    by 0x489D86D:
> heif::convert_colorspace(std::shared_ptr<heif::HeifPixelImage> const&,
> heif_colorspace, heif_chroma) (heif_image.cc:396)
> ==2255==    by 0x48A80E4:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:896)
> ==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
> ==2255==    by 0x10F626: main (in
> /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
> ==2255==  Address 0x535037e is 6,158 bytes inside a block of size 6,159
> alloc'd
> ==2255==    at 0x484A20F: operator new[](unsigned long) (in
> /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==2255==    by 0x4898FEA: heif::HeifPixelImage::add_plane(heif_channel, int,
> int, int) (heif_image.cc:151)
> ==2255==    by 0x48868DB: heif_image_add_plane (heif.cc:745)
> ==2255==    by 0x48A8936: UnknownInlinedFun (heif_decoder_libde265.cc:126)
> ==2255==    by 0x48A8936: libde265_v1_decode_image(void*, heif_image**)
> (heif_decoder_libde265.cc:306)
> ==2255==    by 0x488E86E: heif::HeifContext::decode_image(unsigned int,
> std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const
> (heif_context.cc:944)
> ==2255==    by 0x48A8097:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
> ==2255==    by 0x488D5CE: heif::HeifContext::decode_image(unsigned int,
> std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const
> (heif_context.cc:1017)
> ==2255==    by 0x48A8097:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
> ==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
> ==2255==    by 0x10F626: main (in
> /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
> ==2255== 
> ==2255== Invalid read of size 2
> ==2255==    at 0x48A2E4C:
> Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<heif::
> HeifPixelImage const> const&, heif::ColorState,
> heif::ColorConversionOptions) (heif_colorconversion.cc:2264)
> ==2255==    by 0x489D86D: UnknownInlinedFun (heif_colorconversion.cc:2446)
> ==2255==    by 0x489D86D:
> heif::convert_colorspace(std::shared_ptr<heif::HeifPixelImage> const&,
> heif_colorspace, heif_chroma) (heif_image.cc:396)
> ==2255==    by 0x48A80E4:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:896)
> ==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
> ==2255==    by 0x10F626: main (in
> /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
> ==2255==  Address 0x535037e is 6,158 bytes inside a block of size 6,159
> alloc'd
> ==2255==    at 0x484A20F: operator new[](unsigned long) (in
> /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==2255==    by 0x4898FEA: heif::HeifPixelImage::add_plane(heif_channel, int,
> int, int) (heif_image.cc:151)
> ==2255==    by 0x48868DB: heif_image_add_plane (heif.cc:745)
> ==2255==    by 0x48A8936: UnknownInlinedFun (heif_decoder_libde265.cc:126)
> ==2255==    by 0x48A8936: libde265_v1_decode_image(void*, heif_image**)
> (heif_decoder_libde265.cc:306)
> ==2255==    by 0x488E86E: heif::HeifContext::decode_image(unsigned int,
> std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const
> (heif_context.cc:944)
> ==2255==    by 0x48A8097:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
> ==2255==    by 0x488D5CE: heif::HeifContext::decode_image(unsigned int,
> std::shared_ptr<heif::HeifPixelImage>&, heif_decoding_options const*) const
> (heif_context.cc:1017)
> ==2255==    by 0x48A8097:
> heif::HeifContext::Image::decode_image(std::shared_ptr<heif::
> HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options
> const*) const [clone .constprop.0] [clone .isra.0] (heif_context.cc:880)
> ==2255==    by 0x48862FD: heif_decode_image (heif.cc:663)
> ==2255==    by 0x10F626: main (in
> /home/abuild/rpmbuild/BUILD/libheif-1.6.2/examples/heif-convert)
> 
> [..]  lot of  'Use of uninitialised value' in PngEncoder::Encode()
> 
> ==2255== 
> Written to out.png
> $
> 
> However, I cannot reproduce same way anymore when I update to latest 1.12.0:
> 
> $ valgrind  -q ./heif-convert /192382/heap-overflow.poc test.png
> File contains 1 images
> Could not decode image: 0: Unsupported feature: Unsupported color conversion
> $
> 
> The key is in the following commit:
> https://github.com/strukturag/libheif/commit/
> bca0162018df9a32d21c05aad1fa203881fa7813
> which applied on top of 1.6.2 gives the same result as 1.12.0. This means
> the heap overflow is fixed or at least hidden by the commit in question.

This commit indeed forces RGB internal representation that calls Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace instead of buggy Op_YCbCr420_to_RRGGBBaa::convert_colorspace. The latter doesn't verify that alpha plane bit_depth is 8, but the former does, that's why we ended up with a false assert, instead of an oob read. So we can say that bca0162018df9a32d21c05aad1fa203881fa7813 fixes the issue. Thanks for pointing this Petr.

I raised upstream that there could be an additional fix that would prevent a certain class of bug. Depending on there reply, we could backport bca0162018df9a32d21c05aad1fa203881fa7813 to fix the bug this poc triggers, or an additional fix that would be more complete
Comment 10 Petr Gajdos 2022-10-26 11:01:04 UTC
(In reply to Thomas Leroy from comment #9)
> This commit indeed forces RGB internal representation that calls
> Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace instead of buggy
> Op_YCbCr420_to_RRGGBBaa::convert_colorspace. The latter doesn't verify that
> alpha plane bit_depth is 8, but the former does, that's why we ended up with
> a false assert, instead of an oob read. So we can say that
> bca0162018df9a32d21c05aad1fa203881fa7813 fixes the issue. Thanks for
> pointing this Petr.

Thank you Thomas, a lot.

> I raised upstream that there could be an additional fix that would prevent a
> certain class of bug. Depending on there reply, we could backport
> bca0162018df9a32d21c05aad1fa203881fa7813 to fix the bug this poc triggers,

To my knowledge, bca0162018df9a32d21c05aad1fa203881fa7813 is already part of 1.12.0 we have in only supported 15sp4,TW/libheif. However, it was refined later that day by c7f99cbb176118f7c5e378fd88b22d913bef7377 and 66095625f52c2f077859c3f4e1e5cd87758afba4.

Perhaps I should go trough your comment in upstream in more details bug to understand your concerns better?

> or an additional fix that would be more complete

Sure, I will add it.
Comment 11 Thomas Leroy 2022-10-26 11:26:02 UTC
(In reply to Petr Gajdos from comment #10)
> (In reply to Thomas Leroy from comment #9)
> > This commit indeed forces RGB internal representation that calls
> > Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace instead of buggy
> > Op_YCbCr420_to_RRGGBBaa::convert_colorspace. The latter doesn't verify that
> > alpha plane bit_depth is 8, but the former does, that's why we ended up with
> > a false assert, instead of an oob read. So we can say that
> > bca0162018df9a32d21c05aad1fa203881fa7813 fixes the issue. Thanks for
> > pointing this Petr.
> 
> Thank you Thomas, a lot.
> 
> > I raised upstream that there could be an additional fix that would prevent a
> > certain class of bug. Depending on there reply, we could backport
> > bca0162018df9a32d21c05aad1fa203881fa7813 to fix the bug this poc triggers,
> 
> To my knowledge, bca0162018df9a32d21c05aad1fa203881fa7813 is already part of
> 1.12.0 we have in only supported 15sp4,TW/libheif. However, it was refined
> later that day by c7f99cbb176118f7c5e378fd88b22d913bef7377 and
> 66095625f52c2f077859c3f4e1e5cd87758afba4.

Indeed, these 3 commits have been pushed in v1.7.0.
It's even better for 1.12.0. The program returns an error instead of crashing with a false assert. So we can consider sle15sp4 already fixed.

> Perhaps I should go trough your comment in upstream in more details bug to
> understand your concerns better?

You can, my github comment is more complete. I will monitor the issue, and hope they will reply...

> > or an additional fix that would be more complete
> 
> Sure, I will add it.

I think we can close this bug. If upstream agrees to add my suggestion, you could just normally update the package, there won't be any more CVE allocated :)
Comment 12 Thomas Leroy 2022-10-26 11:27:23 UTC
(In reply to Thomas Leroy from comment #11)
> (In reply to Petr Gajdos from comment #10)
> > (In reply to Thomas Leroy from comment #9)
> > > This commit indeed forces RGB internal representation that calls
> > > Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace instead of buggy
> > > Op_YCbCr420_to_RRGGBBaa::convert_colorspace. The latter doesn't verify that
> > > alpha plane bit_depth is 8, but the former does, that's why we ended up with
> > > a false assert, instead of an oob read. So we can say that
> > > bca0162018df9a32d21c05aad1fa203881fa7813 fixes the issue. Thanks for
> > > pointing this Petr.
> > 
> > Thank you Thomas, a lot.
> > 
> > > I raised upstream that there could be an additional fix that would prevent a
> > > certain class of bug. Depending on there reply, we could backport
> > > bca0162018df9a32d21c05aad1fa203881fa7813 to fix the bug this poc triggers,
> > 
> > To my knowledge, bca0162018df9a32d21c05aad1fa203881fa7813 is already part of
> > 1.12.0 we have in only supported 15sp4,TW/libheif. However, it was refined
> > later that day by c7f99cbb176118f7c5e378fd88b22d913bef7377 and
> > 66095625f52c2f077859c3f4e1e5cd87758afba4.
> 
> Indeed, these 3 commits have been pushed in v1.7.0.
> It's even better for 1.12.0. The program returns an error instead of
> crashing with a false assert. So we can consider sle15sp4 already fixed.
> 
> > Perhaps I should go trough your comment in upstream in more details bug to
> > understand your concerns better?
> 
> You can, my github comment is more complete. I will monitor the issue, and
> hope they will reply...
> 
> > > or an additional fix that would be more complete
> > 
> > Sure, I will add it.
> 
> I think we can close this bug. If upstream agrees to add my suggestion, you
> could just normally update the package, there won't be any more CVE
> allocated :)

I forgot, could you please update the changes file to add the CVE and bsc at bca0162018df9a32d21c05aad1fa203881fa7813 line? This first commit is enough to fix the issue
Comment 13 Petr Gajdos 2022-10-27 07:17:18 UTC
(In reply to Thomas Leroy from comment #12)
> I forgot, could you please update the changes file to add the CVE and bsc at
> bca0162018df9a32d21c05aad1fa203881fa7813 line? This first commit is enough
> to fix the issue

You mean something like this?
https://build.opensuse.org/request/show/1031460
Comment 14 Thomas Leroy 2022-10-27 07:25:33 UTC
(In reply to Petr Gajdos from comment #13)
> (In reply to Thomas Leroy from comment #12)
> > I forgot, could you please update the changes file to add the CVE and bsc at
> > bca0162018df9a32d21c05aad1fa203881fa7813 line? This first commit is enough
> > to fix the issue
> 
> You mean something like this?
> https://build.opensuse.org/request/show/1031460

Exactly, thanks!
Comment 15 Petr Gajdos 2022-10-27 07:47:32 UTC
Closing, thanks
Comment 16 Petr Gajdos 2022-10-27 07:47:47 UTC
.