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

In stb_image's PNM reader, loading a specially constructed valid 16-bit PGM file with 4 channels can cause a crash due to an out-of-bounds read #1225

Closed
NBickford-NV opened this issue Oct 7, 2021 · 3 comments
Labels
1 stb_image 2 bug 5 merged-dev Merged into development branch

Comments

@NBickford-NV
Copy link
Contributor

NBickford-NV commented Oct 7, 2021

Summary
stb_image's PNM loader in version v2.27 incorrectly interpreted 16-bit PGM files as 8-bit when converting to RGBA, leading to buffer overflow when later reinterpreting the result as a 16-bit buffer. An attacker could potentially have crashed a service using stb_image, or read up to 1024 bytes of non-consecutive heap data without control over the read location.

CVE number: CVE-2021-42716

Describe the bug
In stb_image's PNM reader, loading a valid 16-bit PGM file that is large enough
with the number of components set to 4 can cause a crash in
stbi__convert_16_to_8() due to an out-of-bounds read.

This issue includes a fix in pull request #1223, and a proof of concept file that
can be used to reproduce the crash. We're reporting this on GitHub Issues
following the guidance in issue #1213.

This appears to be due to how when stbi__pnm_load() loads a 16-bit PGM file
with N bytes of data, it incorrectly calls stbi__convert_format() instead of
stbi__convert_format16(), returning a buffer that is 2N bytes long instead of
4N bytes. Since ri.bits_per_channel is still 16 when control returns to
stbi__load_and_postprocess_8bit(), stbi__convert_16_to_8() attempts to read
img_len=4N bytes of data from this buffer, resulting in out-of-bounds reads.
When N is large enough, this results in an access violation.

To Reproduce
This .zip contains a 513 KB .pgm file, 16_to_8_oob_poc.pgm, which reproduces this issue:
16_to_8_oob_poc.zip

Calling stbi_load() with a path to this file and with a req_comp of 4 produces a
crash. I was able to verify this using tests/image_test.c (modified slightly in
order to build) on Windows version 20H2 with Microsoft Visual Studio 2019, and
I expect it should reproduce on other systems as well.

This file was generated using the following Python script, and should be a valid PGM file:

f = open('16_to_8_oob_poc.pgm', 'wb')
f.write(b'P5\n\n512 512\n65535\n')
f.write(bytearray([1]*512*512*2))
f.close()

It was derived from an example found using the Radamsa fuzzer.

Interestingly, tests/pbm/basi0g16.pgm is also a 16-bit PGM file, but reading it
doesn't cause a crash! I believe the reason is because this is a 32 x 32 image,
so it only includes N=2048 bytes of image data, and as a result the out-of-bounds
reads don't cross a page boundary that would result in an access violation.

Expected behavior
The example file should be loaded without crashing.

Screenshots

Here's a screenshot showing where the crash occurs and the call stack, when run
with the example file in image_test.c. (Note that the call in image_test.c may
be off by 2 lines; the specific callsite is stbi_load(argv[i], &w, &h, &n, 4).)

example_pgm_access_violation_and_call_stack

Thanks!

@NBickford-NV
Copy link
Contributor Author

Ah, I think this might be a duplicate of issue #1166.

musicinmybrain added a commit to musicinmybrain/zxing-cpp that referenced this issue Dec 8, 2021
Fixes a crash and an infinite loop in stb_image that could occur with
specially constructed PGM and HDR files

nothings/stb#1223

This is a candidate fix for:

  https://nvd.nist.gov/vuln/detail/CVE-2021-42715

  In stb_image's HDR reader, loading a specially constructed invalid HDR
  file can result in an infinite loop within the RLE decoder
  nothings/stb#1224

Additionally, this is a candidate fix for:

  https://nvd.nist.gov/vuln/detail/CVE-2021-42716

  stbi__pnm_load heap-buffer-overflow bug
  nothings/stb#1166

  In stb_image's PNM reader, loading a specially constructed valid
  16-bit PGM file with 4 channels can cause a crash due to an
  out-of-bounds read
  nothings/stb#1225
@rygorous
Copy link
Collaborator

Fix is merged into dev branch, will be in the next release.

@rygorous
Copy link
Collaborator

Fixed in 2.28.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 stb_image 2 bug 5 merged-dev Merged into development branch
Projects
None yet
Development

No branches or pull requests

2 participants