Soumettre #844920: MZ Automation GmbH libiec61850 1.6.1 Memory Corruptioninformation

TitreMZ Automation GmbH libiec61850 1.6.1 Memory Corruption
DescriptionA server-side memory corruption vulnerability exists in libiec61850 version 1.6.1 in the MMS reporting implementation. The issue is reachable through the normal IEC 61850 / MMS reporting workflow and can be reproduced against the official, unmodified example server `examples/server_example_service_tracking/server_example_service_tracking.c`. The vulnerability is triggered when a remote client establishes a valid connection to the server, writes an oversized `RptID` value into a report control block (RCB), enables reporting, and triggers `GI` so that the server immediately enters the report generation and transmission path. Under these conditions, the server later crashes with an invalid free in the library code. Based on the current evidence, the most defensible security impact is remotely triggerable denial of service caused by a memory corruption condition. The vulnerable behavior is not limited to a parser-only testcase and does not depend on a synthetic decode harness. The trigger sequence goes through the normal server request-processing path used for report control block manipulation. In the verified reproduction, the server accepts write operations for `LLN0$RP$EventsRCB01$Resv`, `LLN0$RP$EventsRCB01$RptID`, `LLN0$RP$EventsRCB01$DatSet`, `LLN0$RP$EventsRCB01$TrgOps`, `LLN0$RP$EventsRCB01$RptEna`, and `LLN0$RP$EventsRCB01$GI`. The runtime log shows that these values are processed successfully, reporting is activated, a report is enqueued, and the server reaches the `SEND NEXT REPORT` stage before the failure occurs. This is important because it demonstrates that the vulnerability is triggered after the malicious report state has been accepted and stored by the server and when the library later attempts to serialize and send the report, rather than during initial packet parsing. The root cause is an ownership and lifetime mismatch in the report sending path. In `src/iec61850/server/mms_mapping/reporting.c`, the function `sendNextReportEntrySegment` creates a temporary report ID object using a stack-allocated character buffer, `rptIdBuf[130]`, and a temporary `MmsValue` structure for a visible string. The temporary object is configured so that `rptId.value.visibleString.buf` points directly to the local stack buffer and the temporary capacity is set to 129 bytes. Later in the same function, the actual report ID string is copied into this temporary `MmsValue` by calling `MmsValue_setVisibleString(&rptId, rptIdStr)`. That design is unsafe because the generic visible-string setter in `src/mms/iso_mms/common/mms_value.c` is written with the assumption that the target visible-string buffer is heap-managed and can be resized or released when the incoming string does not fit into the current capacity. The failure occurs when the attacker-controlled `RptID` exceeds the temporary capacity of the stack-backed buffer. In `mms_value.c`, `MmsValue_setVisibleString` ultimately reaches the helper `setVisibleStringValue`. When the new string length is larger than `self->value.visibleString.size`, the implementation enters a resize path and calls `GLOBAL_FREEMEM(self->value.visibleString.buf)` before allocating a larger buffer. In a normal case, this behavior is only safe if the current buffer was originally allocated from the heap. In the vulnerable report path, however, `self->value.visibleString.buf` points to `rptIdBuf`, which is a local stack object owned by the current stack frame of `sendNextReportEntrySegment`. As a result, the generic setter frees a stack address as if it were a heap pointer, producing an invalid free / bad-free condition and aborting the process. This is a classic case of memory corruption caused by inconsistent ownership assumptions between two internal components of the library. The bug therefore has a two-stage trigger model. In the first stage, the remote client injects an oversized but still accepted `RptID` value into the report control block by using the regular MMS write mechanism. In the second stage, the client triggers report generation by enabling reporting and setting `GI`, which causes the server to dequeue and encode the report. Only then does the vulnerable code path execute. This two-stage behavior explains why the write request itself appears to succeed while the crash occurs later during report generation. It also makes the issue more security-relevant than a mere malformed-input parser crash, because the library stores attacker-influenced internal state and later processes that state in a separate, legitimate service path. The issue has been reproduced with an ASan/UBSan-instrumented build of the official service tracking example. The observed client-side output shows a successful connection establishment and a valid server response to the final write request, e.g. `cr rsp 22`, `aarq rsp 143`, and `set rsp 39 ...`. On the server side, the runtime log confirms successful processing of the report control block writes, activation of reporting, and report enqueueing. Immediately after `IED_SERVER: SEND NEXT REPORT`, AddressSanitizer reports `attempting free on address which was not malloc()-ed`. The recorded stack trace identifies the crashing chain as `setVisibleStringValue` in `src/mms/iso_mms/common/mms_value.c`, then `MmsValue_setVisibleString`, followed by `sendNextReportEntrySegment`, `sendNextReportEntry`, and `Reporting_sendReports` in `src/iec61850/server/mms_mapping/reporting.c`. ASan also points out that the freed address resides inside the local stack object `rptIdBuf` in `sendNextReportEntrySegment`, which directly supports the invalid free diagnosis and rules out a generic allocator corruption explanation. A minimal proof-of-concept can be implemented in Python and does not require the use of the library’s own high-level client API. The PoC sends a COTP connection request, performs AARQ/MMS association setup, and then transmits a single MMS write sequence containing the required RCB updates. The important element is an oversized `RptID` field, verified in reproduction with a length of 219 bytes, combined with `Resv=true`, a valid `DatSet`, trigger options, `RptEna=true`, and `GI=true`. This is sufficient to place the server into the vulnerable state and immediately force entry into the report send path. The fact that the issue can be triggered by a compact raw-protocol PoC further supports the conclusion that the vulnerability lies in the library’s internal state handling and report serialization logic rather than in optional wrapper code. From a security perspective, the most reliable and currently demonstrated impact is remote denial of service. The crash happens in a server thread while handling a real client connection, causing the instrumented process to abort. In non-ASan builds, the exact manifestation may vary depending on the allocator and runtime environment, but an invalid free of stack memory is inherently undefined behavior and can reasonably be expected to result in process termination, abnormal service interruption, or other unstable behavior. There is currently no verified evidence of controlled code execution, information disclosure, or a stable integrity compromise, so those stronger claims should not be made. Nevertheless, because the defect is a genuine memory corruption bug in a network-facing service path, it is clearly security-relevant and not merely a harmless robustness issue. The attack prerequisites depend on deployment configuration. To trigger the issue, an attacker must be able to reach the MMS service and perform the relevant report control block write operations against the target server. In the verified scenario, the official example accepts the necessary operations and is therefore directly exploitable. In hardened deployments, authentication, network segmentation, or server-side access control logic may reduce the reachable attack surface. However, those operational mitigations do not eliminate the underlying vulnerability in the library code. Even in environments where write access to the RCB is intended only for trusted clients, a memory corruption bug in the report send path remains a valid security flaw because the library accepts a state that it cannot safely serialize. The defect is best classified as Memory Corruption, with CWE-590 (Free of Memory not on the Heap) as the most precise primary CWE. Depending on the taxonomy used by the platform, related categorizations such as invalid pointer release or improper resource lifetime management may also apply. The essential technical characteristic is that a pointer to stack storage is passed into a generic string update routine whose semantics include freeing and reallocating the current backing storage. Once the incoming report ID exceeds the temporary buffer size, the routine performs a `free` operation on memory that was never allocated on the heap.
La source⚠️ https://github.com/gff-cw/information/issues/2
Utilisateur
 Carnegie (UID 98671)
Soumission01/06/2026 15:28 (il y a 2 mois)
Modérer02/08/2026 21:14 (2 months later)
StatutAccepté
Entrée VulDB385411 [mz-automation libiec61850 jusqu’à 1.6.1 Report Sending Path reporting.c Reporting_RCBWriteAccessHandler déni de service]
Points20

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!