Angriffsszenario: Downgrade des Protokoll-Namespace (ISO 15118-2 → DIN SPEC 70121)
Agenda
Series: V2G Security Research
- Teil 1: EV-Laden und der V2G-Protokollstack – Bedrohungsmodell und Protokollübersicht
- Teil 2: Laborumgebung – Docker-basierte V2G-Sicherheitsumgebung
- Teil 3: TLS-Downgrade
- Teil 4: SDP Response Spoofing
- Teil 5: Zertifikatsvalidierung
- Teil 6: Downgrade des Protokoll-Namespace ← Sie befinden sich hier
Nachdem wir in Teil 5 bestätigt haben, dass das EVCC die Zertifikatsvalidierung korrekt durchsetzt, wechseln wir in diesem Beitrag eine Ebene tiefer innerhalb des Handshakes: zur Aushandlung des Anwendungsprotokolls, die stattfindet, bevor überhaupt V2G-Nachrichten ausgetauscht werden.
Die zentrale Frage lautet: Kann ein manipulierter SECC die Sitzung von ISO 15118-2 auf das ältere DIN SPEC 70121 zurückstufen und damit TLS sowie Nachrichtensignaturen mit einem einzigen Schritt entfernen?
Anforderung gemäß ISO 15118-2 (§ 8.3 / SupportedAppProtocol): EVCC und SECC tauschen unmittelbar nach dem Aufbau der TCP-Verbindung einen supportedAppProtocolReq- bzw. supportedAppProtocolRes-Handshake aus. Der SECC wählt dabei das von beiden Seiten unterstützte Protokoll mit der höchsten Priorität aus. Existiert kein gemeinsames Protokoll, muss der SECC mit ResponseCode: Failed_NoNegotiation antworten und das EVCC die Verbindung beenden. Ein normkonformes EVCC, das ausschließlich ISO 15118-2 unterstützt, darf niemals auf DIN zurückfallen.
Warum DIN SPEC 70121 weniger sicher ist: DIN wurde entwickelt, bevor Sicherheitsmechanismen eine verbindliche Anforderung darstellten. Der Standard entstand vor der ISO-15118-2-Vorgabe für TLS und enthält weder Unterstützung für vertragsbasierte Authentifizierung (Plug & Charge) noch für signierte Nachrichten. Jede Sitzung, die auf DIN zurückfällt, verliert diese Schutzmechanismen stillschweigend.
| Funktion | ISO 15118-2 | DIN SPEC 70121 |
|---|---|---|
| TLS verpflichtend | Ja (§ 8.7.3) | Nein |
| Plug & Charge (Vertragszertifikate) | Ja | Nein |
| XML-Digitalsignaturen | Ja | Nein |
| Gegenseitige Authentifizierung | Ja | Nein |
Angriffsmodell
Der Angriff zielt auf den SupportedAppProtocol-Handshake ab, der unmittelbar nach dem Aufbau der TCP-Verbindung ausgeführt wird.
Wenn das EVCC sowohl ISO 15118-2 als auch DIN SPEC 70121 in seiner SAP-Anfrage auflistet, wie es bei vielen realen Elektrofahrzeugen aus Kompatibilitätsgründen üblich ist, kann ein manipulierter SECC mit OK_SuccessfulNegotiation und der Schema-ID des DIN-Eintrags antworten.
Das EVCC erkennt daraufhin eine gültige Übereinstimmung, wechselt seinen Zustandsautomaten in den DIN-Namespace und setzt die Sitzung ohne TLS, Plug & Charge oder Nachrichtensignaturen fort.
![]()
Angriffsaufbau
Das EVCC in unserer Laborumgebung (Josev) wird standardmäßig mit evcc/config/baseline.json ausgeliefert und unterstützt dort ausschließlich ISO_15118_2.
Zur Reproduktion des Downgrades ergänzen wir eine zweite EVCC-Konfiguration mit dem Namen evcc/config/attack3_din_fallback.json. Diese bildet ein reales Fahrzeug nach, das zusätzlich DIN SPEC 70121 als Fallback für ältere Ladestationen unterstützt:
{
"supportedProtocols": [
"ISO_15118_2",
"DIN_SPEC_70121"
],
"supportedEnergyServices": [
"AC"
],
"isCertInstallNeeded": false,
"useTls": true,
"chargeLoopCycle": 10
}
Beachten Sie, dass useTls weiterhin auf true gesetzt ist. Das EVCC fordert also weiterhin TLS in seiner SDP-Anfrage an.
Josev enthält außerdem Programmcode, der DIN_SPEC_70121 eigentlich aus der SAP-Anfrage entfernen soll, sobald TLS aktiv ist. Wie die spätere Verkehrsanalyse zeigt, hängt dieser Schutzmechanismus jedoch vom Ergebnis des SDP-Austauschs ab und nicht von der statischen Konfiguration. In unserem Labor greift diese Schutzfunktion daher nicht.
Auf SECC-Seite verwenden wir dieselbe Konfiguration wie zuvor:
PROTOCOLS=DIN_SPEC_70121 # ← SECC advertises only DIN in supportedAppProtocolRes
AUTH_MODES=EIM
SECC_ENFORCE_TLS=False # <-- no TLS
LOG_LEVEL=DEBUG
MESSAGE_LOG_JSON=True
Schritt 1: EVCC-Image mit der Fallback-Konfiguration erstellen
evcc/config/attack3_din_fallback.json wird bereits beim Build-Prozess in das EVCC-Image integriert (siehe evcc/Dockerfile). Nach dem Hinzufügen der Datei muss das Image daher einmal neu erstellt werden:
# All commands must be run from the project root.
docker compose build evcc
Schritt 2: Vorhandene Testumgebung bereinigen
docker compose down -v
docker rm -f attacker 2>/dev/null || true
Schritt 3: SECC- und EVCC-Container starten
Exportieren Sie die Szenario-Variablen und starten Sie beide Container.
Das EVCC enthält eine integrierte Startverzögerung von zwei Sekunden, damit der SECC vor dem ersten SDP-Multicast vollständig bereit ist.
export SECC_SCENARIO=attack3_din_only
export EVCC_SCENARIO=attack3_din_fallback
docker compose up secc evcc
Beobachten Sie die Docker-Logs. Dort erscheinen SDP-Austausch, SAP-Handshake und die anschließenden DIN-Nachrichten in Echtzeit.
![]()
Feste Adressen: Durch statische MAC-Adressen in docker-compose.yml erhalten beide Container deterministische Link-Local-Adressen:
SECC → fe80::ff:fe00:1 (MAC 02:00:00:00:00:01)
EVCC → fe80::ff:fe00:2 (MAC 02:00:00:00:00:02)
Schritt 4: Netzwerkmitschnitt erfassen
Nach dem Beenden beider Container befinden sich die PCAP-Dateien unter:
captures/
attack3_din_only/
secc_<timestamp>.pcap
evcc_<timestamp>.pcap
Öffnen Sie die SECC-Aufzeichnung in Wireshark und verwenden Sie den folgenden Display-Filter:
udp.port == 15118 || tcp.port == 15118 || v2gmsg
Traffic-Analyse
Die folgende Analyse basiert auf dem Mitschnitt in captures/attack3_din_only/.
Teilnehmer
| Rolle | IPv6 Link-Local | Port |
|---|---|---|
| EVCC | fe80::ff:fe00:2 | - |
| SECC | fe80::ff:fe00:1 | 59432 |
Schritt 1: SDP-Austausch, TLS wird herabgestuft
Noch bevor die Protokollaushandlung beginnt, stuft der SECC die Transportsicherheit herab. Es handelt sich um dasselbe Verhalten, das bereits im TLS-Downgrade-Szenario beobachtet wurde.
EVCC SDPRequest: Security: 0x00 → "Secured with TLS"
SECC SDPResponse: Security: 0x10 → "No transport layer security"
SECC Port: 59432
![]()
Das EVCC akzeptiert die SDP-Antwort ohne TLS und baut eine gewöhnliche TCP-Verbindung auf. Ein TLS-ClientHello wird niemals gesendet.
Genau dies ist der entscheidende Moment des Angriffs, da hier der TLS-Status festgelegt wird, den der anschließende SAP-Handshake übernimmt.
Schritt 2: SupportedAppProtocol Request (EVCC → SECC), beide Protokolle werden angeboten
Nach dem Aufbau der TCP-Verbindung sendet das EVCC seinen supportedAppProtocolReq mit beiden Protokollen:
{
"supportedAppProtocolReq": {
"AppProtocol": [
{
"ProtocolNamespace": "urn:din:70121:2012:MsgDef",
"VersionNumberMajor": 2,
"VersionNumberMinor": 0,
"SchemaID": 1,
"Priority": 1
},
{
"ProtocolNamespace": "urn:iso:15118:2:2013:MsgDef",
"VersionNumberMajor": 2,
"VersionNumberMinor": 0,
"SchemaID": 2,
"Priority": 2
}
]
}
}
![]()
Obwohl die EVCC-Konfiguration weiterhin useTls: true enthält, erscheint der DIN-Eintrag (urn:din:70121:2012:MsgDef) dennoch in der Anfrage.
Der Schutzmechanismus innerhalb von Josev, der DIN eigentlich bei aktivem TLS entfernen soll, greift hier nicht. Zu diesem Zeitpunkt spiegelt das Laufzeit-Flag is_tls bereits das Ergebnis des SDP-Austauschs wider, also „kein TLS“, und nicht mehr den statischen Konfigurationswert.
Schritt 3: SupportedAppProtocol Response (SECC → EVCC), DIN wird ausgewählt
Der SECC ist mit PROTOCOLS=DIN_SPEC_70121 konfiguriert, erkennt den DIN-Eintrag und akzeptiert die Verhandlung:
{
"supportedAppProtocolRes": {
"ResponseCode": "OK_SuccessfulNegotiation",
"SchemaID": 1
}
}
![]()
Damit ist die DIN-Sitzung erfolgreich etabliert.
Schritt 4: Die gesamte Sitzung läuft über DIN SPEC 70121 und unverschlüsseltes TCP
Alle folgenden Nachrichten werden nun im DIN-Namespace (urn:din:70121:2012:MsgDef) übertragen.
Die Kommunikation erfolgt über dieselbe TCP-Verbindung aus Schritt 1:
- Kein TLS ClientHello
- Keine Vertragszertifikate
- Keine XML-Signaturen
- SDP-TLS-Downgrade: Der SECC signalisiert Security: NO_TLS in seiner SDP-Antwort und das EVCC akzeptiert dies ohne weitere Prüfung.
- Der DIN-Schutzmechanismus greift nur bei bestehendem TLS: Das EVCC von Josev enthält Code, der DIN_SPEC_70121 eigentlich aus der SAP-Anfrage entfernen soll, sobald TLS aktiv ist.
![]()
Schritt 5: Sitzungsabbruch durch fachlichen Konfigurationsfehler, nicht durch eine Sicherheitsprüfung
evcc log:
ServiceDiscoveryRes received
Reason: Offered energy transfer modes [DC_extended] not compatible with AC_three_phase_core
The data link will terminate in 2 seconds; TCP connection will close in 5 seconds.
Die Sitzung wird an dieser Stelle ausschließlich beendet, weil das EVCC für AC-Laden konfiguriert ist, während der DIN-SECC lediglich DC_extended anbietet.
Dabei handelt es sich um einen Konfigurationsunterschied im Labor und nicht um einen Sicherheitsmechanismus. Der eigentliche Downgrade-Angriff war zu diesem Zeitpunkt bereits vollständig erfolgreich.
Ein DC-fähiges EVCC oder ein SECC mit kompatiblem Energieprofil würde die Kommunikation stattdessen bis zur PaymentServiceSelection und anschließend in den Ladeprozess fortsetzen – weiterhin ohne Authentifizierung und ohne Verschlüsselung.
![]()
Ergebnisse des erfolgreichen Angriffs
| Erwartung (normkonformes EVCC) | Beobachtung | |
|---|---|---|
| SDP: EVCC fordert TLS an | Security: 0x00 ✓ | Security: 0x00 ✓ |
| SDP: SECC stuft auf No-TLS herab | EVCC bricht ab | EVCC akzeptiert stillschweigend |
| SAP: EVCC bietet DIN als Fallback an | DIN wird entfernt, sobald TLS verloren geht | ❌ DIN bleibt in der Anfrage enthalten |
| SAP: SECC wählt DIN | EVCC sollte ablehnen | ❌ OK_SuccessfulNegotiation, DIN ausgewählt |
| Sitzungs-Namespace | ISO 15118-2 | urn:din:70121:2012:MsgDef |
| TLS / Plug & Charge / Signaturen | Bleiben erhalten | Gehen verloren, unverschlüsseltes TCP, nur EIM, keine XML-Signaturen |
Erkenntnis
Der Downgrade-Angriff auf den Protokoll-Namespace ist erfolgreich, sobald das EVCC neben ISO_15118_2 zusätzlich DIN_SPEC_70121 als Fallback unterstützt, was die Konfiguration vieler realer Fahrzeuge zur Kompatibilität mit älteren Ladestationen widerspiegelt.
Der Angriff funktioniert, weil zwei unabhängige Schwachstellen miteinander kombiniert werden:
# iso15118/evcc/comm_session_handler.py
if self.is_tls:
supported_protocols.remove(Protocol.DIN_SPEC_70121)
Da die SDP-Antwort die Sitzung bereits auf „kein TLS“ herabgestuft hat, besitzt self.is_tls beim Erzeugen der SAP-Anfrage den Wert False. Der Schutzmechanismus wird daher nie aktiviert und DIN_SPEC_70121 bleibt in der Anfrage enthalten. Dies geschieht ausschließlich als Folge der ersten Schwachstelle.
Da DIN weiterhin angeboten wird, kann der manipulierende SECC dieses Protokoll auswählen (OK_SuccessfulNegotiation, SchemaID: 1). Das EVCC übernimmt daraufhin den kompletten DIN-Namespace.
SessionSetupReq/Res und ServiceDiscoveryReq/Res werden anschließend vollständig über unverschlüsseltes TCP übertragen, ohne TLS, ohne Plug & Charge und ohne XML-Signaturen.
In unserem Versuch wurde die Sitzung aufgrund eines inkompatiblen Energieprofils beendet. Der eigentliche Downgrade war zu diesem Zeitpunkt jedoch bereits vollständig durchgeführt.
Die eigentliche Schwachstelle liegt daher nicht in der Logik des SAP-Handshakes selbst. Dieser wählt korrekt ein von beiden Seiten unterstütztes Protokoll aus. Problematisch ist vielmehr, dass er seine Vertrauensentscheidung von dem bereits verwundbaren SDP-Austausch übernimmt.
Eine Behebung der im TLS-Downgrade-Szenario beschriebenen Schwachstelle würde daher gleichzeitig auch diesen Angriffspfad auf den Protokoll-Namespace schließen.
Sie möchten noch mehr erfahren? Hier finden Sie eine Übersicht über alle unsere Blog-Beiträge zum Thema Cybersecurity.