Bugzilla – Bug 1192382
VUL-0: CVE-2020-23109: libheif: buffer overflow vulnerability in heif_colorconversion.cc may lead to DoS and Information Disclosure
Last modified: 2023-02-24 14:45:25 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
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.
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.
Cf analysis reported upstream [0]. [0] https://github.com/strukturag/libheif/issues/207#issuecomment-1289322472
(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
(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.
(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 :)
(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
(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
(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!
Closing, thanks
.