Enviar #912711: davenardella snap7 1.4.3 Memory Corruptioninformación

Títulodavenardella snap7 1.4.3 Memory Corruption
DescripciónA vulnerability was found in davenardella snap7 up to and including 1.4.3, in the function TSnap7MicroClient::opUpload() of the file src/core/s7_micro_client.cpp. The manipulation of the argument DataLen leads to memory corruption. The affected code derives the length of a memcpy from this server-supplied field of the S7 protocol response and never validates it. SUMMARY LINE Vulnerability class : Memory Corruption Affected file : src/core/s7_micro_client.cpp Affected function : TSnap7MicroClient::opUpload() Affected parameter : DataLen (S7 response header field) Affected version : up to and including 1.4.3 Vendor / product : https://github.com/davenardella/snap7 Upstream report : https://github.com/davenardella/snap7/issues/30 Proposed CVSS 3.1 : CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L (6.3) Proposed CVSS 4.0 : CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N (5.3) The proposed vectors deliberately match those already assigned to CVE-2026-16225, which covers the equivalent client-side condition in the same library and the same attacker position, so that scoring stays consistent across the product. This submission describes ONE vulnerability: a single unvalidated length. The two behaviours shown below are two ways of reaching the same defect, not two separate issues. A DataLen smaller than the header size drives the length negative; a large DataLen drives it beyond the receive buffer. One bound closes both. AFFECTED CODE The function begins at line 997. Size is declared as a signed int at line 1073. In the first-slice branch the value is taken directly from the peer: Done = ResParams->EoU == 0; if (Full) Size = SwapWord(Answer->DataLen) - 4; else Size = SwapWord(Answer->DataLen) - sizeof(TResFunUploadDataHeaderFirst); Target = pbyte(&opData) + Offset; memcpy(Target, Source, Size); Offset += Size; The memcpy is line 1116. The next-slice branch repeats the same pattern at line 1164 using sizeof(TResFunUploadDataHeaderNext), which is 4 bytes. TResFunUploadDataHeaderFirst is 40 bytes. Three separate things are unchecked: the sign of Size, the value of Size against the number of bytes actually received, and Offset plus Size against the capacity of the destination. Relevant declarations, all in the same tree: src/core/s7_micro_client.h line 294 TS7Buffer opData; src/core/s7_types.h line 358 typedef byte TS7Buffer[65536]; src/core/s7_isotcp.h lines 38 and 189 IsoPayload_Size 4096, typedef u_char TIsoPayload[IsoPayload_Size] The ISO transport layer does not mitigate this. isoRecvBuffer() validates only the TPKT length, computing Size = PDUSize(&PDU) - DataHeaderSize. The DataLen field used above is a separate field carried inside the S7 payload and is never cross-checked against the TPKT length. IMPACT This is a client-side flaw. It affects any application that calls Cli_Upload or TS7Client::Upload, which in practice means SCADA software, HMIs, historians, engineering tools and protocol gateways that use snap7 to read blocks from a PLC. The attacker position is the server end: a malicious PLC, a rogue device on the S7 network, or an attacker able to answer the upload sequence. The condition is reached on the first Upload response. No multi-slice sequence and no prior state are required beyond a normal connection and PDU negotiation. PROOF OF CONCEPT Confirmed dynamically against commit 30f37da built with clang 21.1.8 and AddressSanitizer on Linux x86_64, using a minimal S7 server on loopback that completes COTP connection, Setup Communication and StartUpload and then answers the first Upload request with a chosen DataLen. Variant 1, DataLen set to 0. Size becomes 0 minus 40, that is -40, and reaches memcpy as a size_t: ERROR: AddressSanitizer: negative-size-param: (size=-40) #0 __asan_memcpy #1 TSnap7MicroClient::opUpload() src/core/s7_micro_client.cpp:1116 #2 TSnap7MicroClient::PerformOperation() src/core/s7_micro_client.cpp:2566 #3 TSnap7MicroClient::Upload(int, int, void*, int&) src/core/s7_micro_client.cpp:2984 #4 Cli_Upload src/lib/snap7_libmain.cpp:318 Variant 2, DataLen set to 0xFFF0. Size becomes 65496 and is copied out of a 4096 byte PDU.Payload: ERROR: AddressSanitizer: memcpy-param-overlap 0x...5a0c is located 4620 bytes inside of 70208-byte region 0x...49c1 is located 449 bytes inside of 70208-byte region Source and destination both lie inside the same 70208 byte TSnap7MicroClient object, which is why the sanitizer reports an overlap rather than a plain overflow. A reproducer exists but has not been published, because there is no released fix and the upstream project has had no commits since 14 July 2025. It can be provided privately to the maintainer or to the CNA. SUGGESTED FIX Bound the length before the copy, in both the first-slice and next-slice branches: int Size = SwapWord(Answer->DataLen) - int(sizeof(TResFunUploadDataHeaderFirst)); if (Size < 0 || Size > int(IsoSize) - int(ResHeaderSize23 + sizeof(TResFunUploadParams) + sizeof(TResFunUploadDataHeaderFirst)) || uintptr_t(Size) > sizeof(opData) - Offset) { Result = errCliUploadSequenceFailed; break; } Three conditions are needed because three separate things are unchecked: the sign, the bytes actually received, which isoExchangeBuffer already places in IsoSize, and the room remaining in opData. Enforcing BlockLength, taken from ResDataHeader->MC7Len, against Offset would be a reasonable fourth. The same bound is required on the Full branch at line 1110, where the subtraction is 4 rather than 40. PRIOR ART CHECKED NVD keyword snap7, all nine results read in full. GitHub Advisory Database, both repository advisories and a global search. CISA KEV. The SourceForge tracker, 34 tickets. The GitHub issue tracker, all 29 issues and pull requests, searched by symptom and by function name rather than only by fix commits. Existing memory-safety reports in the same project cover different functions: issue 11 the SZL TS7Buffer path, issue 14 PerformFunctionWrite, issue 15 TSnap7Partner::PickData, issue 16 PerformFunctionRead, issue 17 opWriteArea, and issue 20 an uninitialised BitIndex. CVE-2025-15247 covers snap7_rs::client::S7Client::download in the Rust binding's client.rs, which is a different file and the opposite direction of transfer. Nothing found covers opUpload. Reported upstream as davenardella/snap7 issue 30 on 1 August 2026. The maintainer has not responded; the project has had no commits since 14 July 2025 and carries several unfixed memory-safety reports.
Fuente⚠️ https://github.com/davenardella/snap7/issues/30
Usuario
 mayur021 (UID 27195)
Sumisión2026-08-01 14:08 (hace 1 mes)
Moderación2026-09-12 18:11 (1 month later)
EstadoAceptado
Entrada de VulDB403157 [davenardella snap7 hasta 1.4.3 s7_micro_client.cpp opUpload DataLen desbordamiento de búfer]
Puntos20

Do you need the next level of professionalism?

Upgrade your account now!