← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-27764 · CWE-613 · Disclosed 2026-03-06

The WebSocket backend uses charging station identifiers to uniquely associate sessions but

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a valet stand that hands the keys to whoever repeats the ticket number last

CVE-2026-27764 affects all versions of Mobiliti e-mobi.hu per CISA/CVE records. The backend uses the charging station identifier as the session anchor for OCPP-over-WebSocket traffic, but it permits another endpoint to connect with that same identifier. In practice, that lets an attacker open a competing session, displace or shadow the legitimate charger, and receive backend commands or corrupt the station's telemetry stream.

The vendor's HIGH rating is basically fair. The main downward pressure is real-world friction: the attacker needs reachability to the OCPP/WebSocket edge and a valid station identifier. But there is still no authentication requirement in this CVE's path, no user interaction, all versions are affected, and the exposed service is the very control plane used to manage chargers remotely, so this stays HIGH rather than falling to a routine medium.

"Internet-reachable charger backends plus guessable station IDs make this a real hijack path, not just a session bug."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find a reachable OCPP endpoint and valid station ID

The attacker identifies an internet-reachable Mobiliti OCPP/WebSocket endpoint and a charger identifier accepted by the backend. In this ecosystem that can be done with normal recon tooling like Shodan, Censys, curl, or passive OSINT against charger maps, network docs, and naming conventions; the protocol itself commonly exposes the station identity in the WebSocket URL path or connection context.
Conditions required:
  • Attacker can reach the OCPP/WebSocket service over the network
  • At least one valid charging station identifier is known, guessed, or derived
Where this breaks in practice:
  • Many deployments will place the OCPP backend behind private APNs, VPNs, IP allowlists, or carrier NAT
  • Public internet search engines do not appear to have a reliable product fingerprint for Mobiliti specifically
Detection/coverage: External attack-surface scanners may find open WebSocket listeners, but they usually will not prove session-shadowing behavior. This needs protocol-aware validation, not just port discovery.
STEP 02

Open a competing WebSocket session

Using a generic client such as websocat or a custom OCPP client, the attacker connects with the same station ID as the legitimate charger. The vulnerability is that the backend accepts the duplicate identity instead of enforcing a single authenticated binding or rejecting reuse.
Conditions required:
  • Backend accepts inbound WebSocket connections for charger sessions
  • No stronger identity control blocks the duplicate session
Where this breaks in practice:
  • mTLS, HTTP Basic Auth, reverse-proxy authentication, or strict source-IP pinning would break this path
  • Some charging networks terminate idle or malformed sessions aggressively, which can complicate testing
Detection/coverage: Look for repeated WebSocket handshakes using the same charger ID from different IPs or ASNs. Standard vuln scanners generally miss this because they do not maintain two concurrent protocol sessions.
STEP 03

Shadow or displace the real charger

The backend binds the latest connection to the charger's identity, so the malicious session becomes the active recipient for commands meant for the real device. Depending on implementation, the legitimate charger is either kicked off outright or continues in a confused split-brain state while the attacker receives command traffic.
Conditions required:
  • Session uniqueness is keyed only on charger ID
  • Backend prefers or accepts the most recent connection
Where this breaks in practice:
  • Operational monitoring may flag charger disconnect/reconnect churn quickly
  • Some CSMS implementations may keep enough state to partially limit what the second session can do
Detection/coverage: Backend logs should show duplicate station IDs with overlapping timestamps. SIEM rules on same-ID multi-IP connections are effective if the OCPP access logs are preserved.
STEP 04

Issue or intercept OCPP actions

Once shadowing works, the attacker can receive backend-issued OCPP frames and potentially send responses or state changes as if they were the charger. That can enable charger impersonation, false meter/status data, command interception, and service disruption. The practical blast radius is usually one charger identity per successful takeover, but it scales if many IDs are known.
Conditions required:
  • The malicious session remains bound long enough to exchange OCPP frames
  • Backend trusts the active session as the charger for that ID
Where this breaks in practice:
  • Impact is narrower than tenant-wide admin compromise or code execution
  • Scaling beyond one or a few chargers requires inventory knowledge and sustained access
Detection/coverage: Telemetry anomalies, impossible charger state transitions, and backend commands acknowledged from unusual source IPs are the best hunting points.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusCISA's CSAF says no known public exploitation had been reported to CISA at publication time, and this CVE is not KEV-listed in the sources reviewed.
Proof-of-concept availabilityNo public repo or polished exploit for CVE-2026-27764 surfaced in indexed sources reviewed. Inference: exploitation should be straightforward with websocat or a small custom OCPP WebSocket client once a valid station ID and reachable endpoint are known.
EPSSUser-supplied EPSS is 0.00051 (~0.05%), which is very low. I could not verify an authoritative percentile from indexed primary sources, so treat the percentile as unconfirmed.
KEV statusNot listed in CISA KEV based on the supplied intel and sources reviewed.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L = unauthenticated network attack with low complexity, but only low CIA impact in the CNA model; the real operational concern is charger impersonation and control-plane confusion.
Affected versionsCVE.org and CISA CSAF mark all versions of Mobiliti e-mobi.hu as affected.
Fixed versionsNo fixed version published. CISA states Mobiliti did not respond to coordination, so there is no vendor patch train or backport guidance in the available advisory.
Scanning / exposure dataInference: no reliable product-specific Shodan/Censys/GreyNoise fingerprint was found in indexed public sources for Mobiliti's OCPP edge. Assume internet exposure must be measured internally from your attack-surface inventory and firewall logs.
Disclosure and reportingPublished 2026-03-06. Credited researchers are Khaled Sarieddine and Mohammad Ali Sayed, reported through CISA / ICS-CERT.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.1/10)

The single biggest amplifier is that this is still an unauthenticated remote path against a charger management control plane that is often intentionally reachable over IP networks. The biggest brake is that the attacker still needs a valid station identity and the blast radius usually starts at one charger session at a time, which keeps it out of CRITICAL.

HIGH Affected product scope: all versions with no published fix
MEDIUM Real-world exposure population of Mobiliti OCPP endpoints
MEDIUM Practical exploitability without adjacent identifier-disclosure weaknesses

Why this verdict

  • Baseline stays high: vendor scored it 7.3 HIGH, and the core path is still unauthenticated, network-reachable, and free of user interaction.
  • Exposure friction trims the score slightly: the attacker must reach the OCPP/WebSocket edge, which in mature deployments should be narrowed by VPNs, APNs, private networks, firewalls, or IP allowlists.
  • Identity friction trims it again: the attacker needs a valid charger identifier; that is materially easier if naming is predictable or identifiers leak elsewhere, but it is still a prerequisite that narrows opportunistic mass exploitation.
  • Blast radius keeps it below critical: successful exploitation typically hijacks or disrupts one charger identity per session, not the whole tenant, domain, or server OS.
  • No exploitation evidence removes urgency premium: no KEV listing, no public campaigns cited by CISA, and a very low supplied EPSS argue against an emergency-everything stop.

Why not higher?

This is not pre-auth RCE, not a tenant-wide auth bypass, and not a reliable path to backend host takeover. The attacker must first have OCPP edge reachability and a valid station identifier, and even then the impact is usually bounded to session hijack, command interception, or charger-level disruption rather than full infrastructure compromise.

Why not lower?

Dropping this to MEDIUM would understate the fact that the path is still unauthenticated remote access to a live operational control channel. All versions are affected, there is no published fix, and the vulnerable service exists specifically to let remote systems control chargers, so the reachable population can still be meaningful in real fleets.

05 · Compensating Control

What to do — in priority order.

  1. Restrict OCPP ingress — Put the OCPP/WebSocket edge behind IP allowlists, private APN/VPN paths, or equivalent network admission controls so only known charger networks can reach it. For a HIGH verdict, deploy this within 30 days if you cannot patch because this is the cleanest way to collapse the unauthenticated attack surface.
  2. Enforce strong charger identity at the edge — Require mTLS, strong HTTP authentication, or a reverse-proxy identity layer before a session can bind to a charger ID. Do this within 30 days to prevent a second endpoint from successfully reusing a station identifier even if the backend logic is weak.
  3. Alert on duplicate station IDs — Create detections for the same charger ID connecting from multiple IPs, ASNs, or geographies within a short window. Deploy within 30 days so you can catch session shadowing attempts that slip past perimeter filtering.
  4. Rate-limit connection churn per charger ID — Throttle repeated reconnects and parallel session attempts for the same station identifier at the load balancer, reverse proxy, or WebSocket gateway. This does not fix the logic flaw, but within 30 days it reduces cheap displacement and noisy DoS attempts.
  5. Inventory exposed OCPP endpoints — Treat this as an attack-surface problem first: find every public ws:// or wss:// OCPP listener, associated FQDN, and source-IP policy. Complete the exposure inventory within 30 days so you know which fleets can actually be exploited.
What doesn't work
  • A generic WAF alone is weak here because the bad action happens after a valid WebSocket upgrade and depends on application session semantics, not a simple HTTP signature.
  • Perimeter TLS encryption alone does not help if the attacker can still establish their own legitimate TLS session and reuse the charger identifier.
  • Endpoint EDR on chargers is not a meaningful primary control for this path; the abuse happens at the backend session-binding layer and many embedded chargers will not run enterprise EDR anyway.
06 · Verification

Crowdsourced verification payload.

Run this from an auditor workstation or jump host that can reach the target OCPP/WebSocket endpoint; do not run it on the charger itself. Invoke it as python3 verify_cve_2026_27764.py wss://ocpp.example.com/ocpp/CHARGER123 --subprotocol ocpp1.6 with normal user privileges; install the dependency first with python3 -m pip install websockets.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
"""
verify_cve_2026_27764.py

Best-effort verifier for CVE-2026-27764 (duplicate charger session acceptance / session shadowing).

Usage:
  python3 verify_cve_2026_27764.py wss://host/ocpp/CHARGER123 --subprotocol ocpp1.6

Exit codes:
  0 = VULNERABLE
  1 = PATCHED
  2 = UNKNOWN / test inconclusive

Notes:
- This script opens two WebSocket connections to the SAME charger endpoint/ID.
- If the second connection is accepted and the first is dropped or both remain active,
  the target likely permits duplicate session binding and should be treated as VULNERABLE.
- Some backends require full OCPP message exchange before enforcing policy; in those cases
  the result may be UNKNOWN.
"""

import argparse
import asyncio
import sys

try:
    import websockets
    from websockets.exceptions import ConnectionClosed
except Exception:
    print("UNKNOWN")
    print("Dependency missing: install with 'python3 -m pip install websockets'", file=sys.stderr)
    sys.exit(2)


async def open_ws(url, subprotocol=None):
    kwargs = {
        "open_timeout": 10,
        "close_timeout": 5,
        "ping_interval": None,
        "max_size": 2**20,
    }
    if subprotocol:
        kwargs["subprotocols"] = [subprotocol]
    return await websockets.connect(url, **kwargs)


async def probe(url, subprotocol=None):
    ws1 = None
    ws2 = None
    try:
        ws1 = await open_ws(url, subprotocol)
        await asyncio.sleep(1)

        try:
            ws2 = await open_ws(url, subprotocol)
        except Exception as e:
            # If the second connection is rejected up front, that's the desired behavior.
            print(f"DEBUG: second connection rejected: {type(e).__name__}: {e}", file=sys.stderr)
            return "PATCHED"

        await asyncio.sleep(2)

        ws1_closed = ws1.closed
        ws2_closed = ws2.closed

        # Strong vulnerable signal 1: second session accepted and first got displaced.
        if not ws2_closed and ws1_closed:
            return "VULNERABLE"

        # Strong vulnerable signal 2: both sessions remain open simultaneously for same ID.
        if not ws1_closed and not ws2_closed:
            return "VULNERABLE"

        # If both are closed quickly, backend behavior is ambiguous.
        if ws1_closed and ws2_closed:
            return "UNKNOWN"

        # If only the second is closed, backend may have protected the original session.
        if not ws1_closed and ws2_closed:
            return "PATCHED"

        return "UNKNOWN"

    except ConnectionClosed as e:
        print(f"DEBUG: connection closed during test: {e}", file=sys.stderr)
        return "UNKNOWN"
    except Exception as e:
        print(f"DEBUG: unexpected error: {type(e).__name__}: {e}", file=sys.stderr)
        return "UNKNOWN"
    finally:
        for ws in (ws2, ws1):
            try:
                if ws is not None and not ws.closed:
                    await ws.close()
            except Exception:
                pass


def main():
    parser = argparse.ArgumentParser(description="Best-effort verifier for CVE-2026-27764")
    parser.add_argument("url", help="Full WebSocket URL including the charger/station identifier")
    parser.add_argument("--subprotocol", default="ocpp1.6", help="WebSocket subprotocol, default: ocpp1.6")
    args = parser.parse_args()

    result = asyncio.run(probe(args.url, args.subprotocol))
    print(result)

    if result == "VULNERABLE":
        sys.exit(0)
    elif result == "PATCHED":
        sys.exit(1)
    else:
        sys.exit(2)


if __name__ == "__main__":
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as an external control-plane exposure review: find every Mobiliti OCPP/WebSocket endpoint you own, confirm which ones are internet-reachable, and put network and identity controls in front of them. Under the noisgate mitigation SLA, a HIGH finding means deploy those compensating controls within 30 days; because there is no published vendor fix or version yet, use that mitigation deadline aggressively and then track the noisgate remediation SLA as ≤180 days once Mobiliti releases an actual patch, keeping a documented exception open until a vendor remediation path exists.

Sources

  1. NVD record
  2. CVE.org record
  3. CISA CSAF JSON advisory ICSA-26-062-06
  4. CISA web advisory ICSA-26-062-06
  5. CWE-613 definition
  6. Open Charge Alliance vulnerability research update
  7. Open Charge Alliance OCPP security operations guide
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.