Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
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-2026-52134-libiec61850 — Public technical advisory and reproduction evidence for CVE-2026-52134 affecting GOOSE replay handling in libiec61850 v1.6. | Kitploit
Tools/GitHubGitHub/if-forget/cve-2026-52134-libiec61850
Vulnerability AnalysisSCADA/ICS SecurityNetwork SecurityLearning & EducationCurated ResourcesLabs & Practice
GitHubif-forget/cve-2026-52134-libiec61850

CVE-2026-52134-libiec61850

Public technical advisory and reproduction evidence for CVE-2026-52134 affecting GOOSE replay handling in libiec61850 v1.6.

View Repository
71 month 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-2026-52134: GOOSE replay and message-freshness handling in libiec61850 v1.6

Status

CVE-2026-52134 has been assigned. Publication of the corresponding CVE Record is pending.

Affected product

  • Vendor: MZ Automation GmbH
  • Product: libiec61850
  • Tested version: 1.6
  • Status of other versions: Not confirmed
  • Affected file: src/goose/goose_receiver.c
  • Affected function: parseGoosePayload()

Summary

The GOOSE subscriber receive path in libiec61850 v1.6 does not adequately reject certain replayed or stale GOOSE messages before updating subscriber-visible state and invoking the registered listener callback.

Two controlled experiments demonstrate related behavior in the same receive path:

  1. Lower-stNum rollback: after the subscriber processed stNum=2, replaying a previously captured frame caused the listener to report the older state and data again.
stNum=1
  • Non-increasing sqNum replay: when a previously captured frame with the same stNum but an older sqNum was replayed, the frame was marked invalid, but listener callbacks still occurred and replayed data remained visible.
  • These are presented as two related observations of one replay/message-freshness handling issue, not as two separate CVEs.

    Attack prerequisites

    An attacker must be able to:

    • Access the relevant IEEE 802.3 Layer-2 broadcast domain or VLAN
    • Capture legitimate GOOSE Ethernet frames
    • Inject Ethernet frames using EtherType 0x88B8

    This is not an arbitrary Internet-based remote attack.

    Technical basis

    The relevant receive logic checks sqNum when the received stNum equals the stored stNum. The tested code path does not reject a lower stNum before subscriber state is updated and the listener is invoked.

    The tested library file was not modified. The original and working copies of src/goose/goose_receiver.c had the same SHA-256 value:

    root@kitploit:~
    c42f2aec80f605c458d0bca524ccb09f2e35f9b83a02f854f95d9444616c075b
    

    Source integrity check

    Test environment

    • Ubuntu 20.04.6 LTS
    • libiec61850 v1.6
    • Linux veth0 / veth1 isolated virtual Ethernet pair
    • tcpdump
    • TShark
    • Python 3 and Scapy
    • Modified example publisher and subscriber used only as a test harness

    The test harness produced controlled state transitions and printed callback-visible stNum, sqNum, validity, and data values. The vulnerable library file itself was not modified.

    Experiment A: lower-stNum rollback

    Baseline

    The controlled publisher sent two states:

    root@kitploit:~
    State A: stNum=1, sqNum=0, data=1111
    State B: stNum=2, sqNum=0, data=2222
    

    The baseline packet capture contained two GOOSE frames in this order:

    root@kitploit:~
    Frame 1: stNum=1, sqNum=0
    Frame 2: stNum=2, sqNum=0
    

    Baseline fields and callbacks

    The subscriber output also contained an auxiliary callback for stNum=1, sqNum=0 marked valid=false before State B. This auxiliary callback is retained in the evidence but is not used as the basis for the rollback conclusion. The decisive pre-replay state was the later callback containing stNum=2 and data value 2222.

    Single replay

    The replay script loaded the two-frame baseline capture, selected frame 1, and sent it once through veth0.

    Immediately before the replay, the listener had reported:

    root@kitploit:~
    stNum=2, sqNum=0, valid=true, allData={2222}
    

    After the old frame was replayed once, the listener reported:

    root@kitploit:~
    stNum=1, sqNum=0, valid=true, allData={1111}
    

    Single replay and stNum rollback

    This demonstrates an observed subscriber-state rollback from stNum=2 to stNum=1 after replaying a previously captured lower-stNum frame.

    Additional identical replays

    Four more copies of the same old frame were sent. All four contained stNum=1, sqNum=0.

    The later copies were reported as valid=false, but callback numbers continued to increase and the replayed data remained visible:

    Duplicate replays still cause callbacks

    This secondary observation shows that marking a repeated frame invalid did not prevent listener delivery in the tested receive path.

    Experiment B: non-increasing sqNum replay

    An earlier reproduction used the official example publisher and subscriber. The publisher produced a normal sequence with:

    root@kitploit:~
    stNum=1
    sqNum=0, 1, 2, 3
    

    The first captured frame (stNum=1, sqNum=0) was then replayed after the subscriber had already processed the later sequence value.

    Original sqNum baseline

    The replayed copies were reported as invalid because the received sqNum=0 was not newer than the stored sequence value. However, the subscriber continued to print listener events containing the replayed data:

    Original sqNum replay callbacks

    This experiment supports a narrower but related observation:

    • The same-state replay was detected through the validity flag.
    • Detection did not prevent callback delivery of the replayed message in the tested example.

    The raw original replay screenshots are retained as supporting material:

    • 12-original-sqnum-replay-command-raw.png
    • 13-original-sqnum-replay-terminal-raw.png

    Those raw images contain unrelated Scapy optional-module import warnings. The warnings did not prevent the script from reporting the captured GOOSE frames and completing transmission, but the cleaner screenshots above are preferred for reviewing the technical result.

    Relationship between the two experiments

    The experiments demonstrate different branches of the same GOOSE replay/message-freshness problem:

    ObservationReceived messageObserved result
    Lower-stNum replayStored stNum=2; received old stNum=1Old state and data were delivered to the listener and reported as valid in the tested run
    Non-increasing sqNum replaySame stNum; received older or duplicate sqNumMessage was reported invalid, but listener callbacks and replayed data delivery continued

    The first observation is the primary CVE finding because it demonstrates rollback from a newer state to an older state. The second observation is supporting evidence about how invalid same-state replays continue through the listener path.

    Observed impact

    The demonstrated software-level impact is:

    • A previously accepted GOOSE state can be delivered to the listener after a newer state has already been processed.
    • Subscriber-visible state can move from a newer stNum to an older stNum.
    • Repeated stale frames can continue to cause listener activity even when later copies are reported as invalid.

    Applications that consume callback data without independent freshness enforcement may process stale or replayed values.

    The downstream effect depends on the subscriber application, configuration, interlocking logic, and protection logic.

    No physical protection relay, trip circuit, circuit breaker, or production substation network was tested or operated in these experiments.

    Suggested remediation direction

    Before updating subscriber state or invoking the listener:

    1. Reject a received stNum that is older than the last accepted stNum.
    2. When stNum is unchanged, reject a non-increasing sqNum.
    3. Ensure that a frame classified as invalid cannot overwrite the last accepted state or deliver stale data through the normal listener path.
    4. Account for legitimate restart, resynchronization, and counter-handling behavior in the final implementation.

    Temporary risk reduction

    • Restrict access to GOOSE Ethernet segments and VLANs.
    • Prevent unauthorized devices from injecting Layer-2 frames.
    • Monitor unexpected stNum rollback and repeated sqNum values.
    • Validate subscriber data freshness before using callback values in critical logic.
    • Test changes in an isolated laboratory environment before production deployment.

    Supporting evidence

    The following images provide provenance and environment information. They support the reproduction but are not individually required to understand the main result.

    Test harness inspection

    Test harness inspection

    Successful build

    Successful build

    Isolated veth network

    Isolated veth network

    Baseline capture summary

    Baseline capture summary

    Artifact checksums

    Artifact checksums

    Proposed classification

    • Weakness: replay and message-freshness validation weakness
    • Proposed CWE: CWE-294, Authentication Bypass by Capture-replay

    The demonstrated result is replay acceptance and stale-state delivery. It does not depend on proving that cryptographic authentication was enabled in the tested deployment.

    References

    • Official libiec61850 repository
    • Affected source file in the v1.6 tree
    • CVE-2026-52134 on CVE.org

    Credits

    Reported by:

    • Wang Jing
    • Li Chen Yu
    • Guo Lu Lu
    • Guo Jia Xin
    • Zhang Jia Tu
    Download Tool