Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2023-52356-libtiff-analysis — Root-cause analysis and patch validation of CVE-2023-52356 in libtiff using AddressSanitizer and GDB. | Kitploit
Tools/GitHubGitHub/yardenbenita/cve-2023-52356-libtiff-analysis
Vulnerability AnalysisDebuggersBinary AnalysisPapers & ResearchLearning & Education
GitHubyardenbenita/cve-2023-52356-libtiff-analysis

CVE-2023-52356-libtiff-analysis

Root-cause analysis and patch validation of CVE-2023-52356 in libtiff using AddressSanitizer and GDB.

View Repository
1820 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2023-52356 – libtiff TIFFReadRGBATileExt Analysis

Overview

This lab analyzes CVE-2023-52356 in libtiff, focusing on the behavior of TIFFReadRGBATileExt when it receives image coordinates outside the valid image bounds.

The analysis includes reproduction of the original crash, debugging with AddressSanitizer and GDB, root-cause analysis, examination of the upstream patch, analysis of the original reproducer, and verification of the fixed version.

Test Environment

  • Target: libtiff
  • Vulnerable commit: 4d0329a4
  • Fix commit: 51558511
  • Trigger file: triger_input_47
  • Tools: Clang, AddressSanitizer, GDB, CMake

Crash Reproduction

The original reproducer was compiled against the vulnerable libtiff build with AddressSanitizer enabled.

The reproducer was executed with the provided trigger file:

root@kitploit:~
LD_LIBRARY_PATH="$PWD/libtiff/build-asan/libtiff" ./poc triger_input_47

The execution reproduced a segmentation fault caused by an invalid memory read. The AddressSanitizer stack trace identified the failure during a memmove operation called from TIFFReadRGBATileExt.

Root Cause Analysis

Using GDB, the crash condition was reproduced with the following runtime values:

root@kitploit:~
row = 34
img.height = 33
tile_ysize = 1

The vulnerable code then executed:

root@kitploit:~
read_ysize = img.height - row;

With the observed values, this calculation is:

root@kitploit:~
33 - 34 = -1

Because read_ysize is unsigned, the result wrapped to:

root@kitploit:~
read_ysize = 4294967295

which is UINT32_MAX.

The value of read_ysize was later used in the source pointer calculation for memmove.

Immediately before the failing memmove, GDB showed:

root@kitploit:~
read_ysize = 4294967295
read_xsize = 1
tile_ysize = 1
tile_xsize = 1
i_row = 0
raster = 0x7d0ff67e2d40

The destination pointer evaluated to:

root@kitploit:~
0x7d0ff67e2d40

which was the start of the raster buffer.

The source pointer evaluated to:

root@kitploit:~
0x7d13f67e2d38

The calculated source pointer was 17179869176 bytes, approximately 16 GiB, beyond the start of the raster buffer.

Executing the memmove in GDB resulted in:

root@kitploit:~
SIGSEGV, Segmentation fault

The backtrace showed the following crash path:

root@kitploit:~
__sanitizer_internal_memmove
__asan_memmove
TIFFReadRGBATileExt at tif_getimage.c:3345
LLVMFuzzerTestOneInput at poc.cc:61

This confirms that the unsigned underflow in read_ysize produced an out-of-bounds source offset. The resulting invalid source pointer was then used by memmove, causing an invalid memory read and a segmentation fault.

Patch Analysis and Fix Validation

The upstream fix added an explicit bounds check before the vulnerable read_ysize calculation:

root@kitploit:~
if (col >= img.width || row >= img.height)
{
    TIFFErrorExtR(tif, TIFFFileName(tif),
                  "Invalid row/col passed to TIFFReadRGBATile().");
    TIFFRGBAImageEnd(&img);
    return (0);
}

Using GDB on the fixed version, the following runtime values were observed:

root@kitploit:~
row = 34
img.height = 33
col = 0
img.width = 2047

For these values, the new validation condition evaluates to true because:

root@kitploit:~
row >= img.height
34 >= 33

The function therefore reported:

root@kitploit:~
Invalid row/col passed to TIFFReadRGBATile()

and returned 0.

As a result, execution did not reach the vulnerable calculation:

root@kitploit:~
read_ysize = img.height - row;

This prevents the unsigned underflow observed in the vulnerable version and stops the invalid value from being used in the later memmove source pointer calculation.

Reproducer Analysis and Preconditions

The original reproducer incorrectly calculates the number of tiles along the Y axis.

The relevant code passes the return value of TIFFGetField() directly as the Y coordinate to TIFFComputeTile():

root@kitploit:~
TIFFComputeTile(
    in_tif,
    0,
    TIFFGetField(in_tif, TIFFTAG_IMAGELENGTH, &tile_height),
    0,
    0)

Using GDB, tile_height was observed to contain:

root@kitploit:~
tile_height = 33

However, TIFFGetField() returned:

root@kitploit:~
1

The return value indicates success; it is not the image height. Therefore, the call effectively becomes:

root@kitploit:~
TIFFComputeTile(in_tif, 0, 1, 0, 0)

For this TIFF, GDB showed that this call returns:

root@kitploit:~
2047

This value is a tile index, not the number of tiles along the Y axis.

The original reproducer then used this value in its calculation of num_tiles_y, resulting in:

root@kitploit:~
num_tiles_y = 63

However, the image dimensions and tile dimensions are:

root@kitploit:~
image_width  = 2047
image_height = 33
tile_width   = 1
tile_height  = 1

Therefore, the correct number of tiles along the Y axis is:

root@kitploit:~
num_tiles_y = 33

The incorrect value of 63 causes the loop to iterate with Y values from 0 through 62, even though the image height is 33 and the valid Y coordinates are only 0 through 32.

This allows an invalid value such as:

root@kitploit:~
row = 34

to be passed to TIFFReadRGBATileExt.

The vulnerable libtiff version did not reject this out-of-range coordinate before performing the unsigned img.height - row calculation. This allowed the invalid API input generated by the reproducer to become a memory-safety failure.

The maintainer-provided corrected reproducer calculates the number of tiles directly from the image and tile dimensions.

For the same TIFF, the corrected calculation produces:

root@kitploit:~
num_tiles_x = 2047
num_tiles_y = 33

The corrected reproducer was tested against the same vulnerable libtiff build and the same trigger file.

The program exited with status 0, and no AddressSanitizer or SIGSEGV report was produced.

This supports the maintainer's observation that the original reproducer contains an incorrect tile-count calculation. However, the vulnerable libtiff version still lacked defensive row and column validation, allowing invalid API coordinates to result in a memory-safety failure.

Validation Summary

Reproducerlibtiff VersionResult
Original PoCVulnerable (4d0329a4)Invalid read and SIGSEGV in memmove
Corrected reproducerVulnerable (4d0329a4)Exit status 0, no ASan/SEGV
Original PoCFixed (51558511)Invalid row/col rejected, no ASan/SEGV

Conclusion

The crash in TIFFReadRGBATileExt occurs when an out-of-range image coordinate reaches the vulnerable libtiff implementation.

In the original reproducer, an incorrect tile-count calculation causes num_tiles_y to be calculated as 63 instead of the correct value 33. As a result, the reproducer can pass a row outside the valid image range to TIFFReadRGBATileExt.

In the vulnerable libtiff version, the row and column arguments were not validated before the calculation:

root@kitploit:~
read_ysize = img.height - row;

For the reproduced case, row was 34 while img.height was 33. Because read_ysize is unsigned, the subtraction underflowed to UINT32_MAX. This value was subsequently used in the source pointer calculation for memmove, producing an invalid memory read and a segmentation fault.

The upstream fix adds explicit row and column bounds validation before this calculation. Testing the fixed build confirmed that the same invalid coordinate is rejected before the underflow and memmove can occur.

The maintainer-provided corrected reproducer was also tested against the vulnerable build using the same TIFF file. It calculated the correct tile count and completed without an AddressSanitizer or SIGSEGV report.

Therefore, this analysis does not establish that the TIFF file alone triggers the memory-safety failure when the API is used correctly. The original reproducer contains an incorrect tile-count calculation, while the historical libtiff implementation lacked defensive bounds validation and allowed the resulting invalid API input to become a memory-safety failure.

Download Tool