In meinem vorherigen Post habe ich eine Schwachstelle der Ladekarten für Elektroautos demonstriert: Lediglich die Nummer der Ladekarte wird verwendet, um einen Ladevorgang einem Benutzerkonto zuzuordnen. Diese Schwachstelle ist in praktisch allen Ladeverbünden vorhanden.
Leider hört das Problem hier nicht auf. Im Folgenden zeige ich, wie unsicher die Ladestationen selbst sind und wie die Backend-Prozesse funktionieren.
Wie ist eine Ladestation aufgebaut?
Obiges Bild zeigt einen Prototyp einer Ladestation für ein Forschungsprojekt — wohlgemerkt, das ist ein Prototyp für die Softwareentwicklung und kein fertiges Gerät. Kommerziell erhältliche Ladestationen sind prinzipiell aber ähnlich aufgebaut. Oben links ist der Laderegler. Dieser kümmert sich unter anderem um die Sicherheitsprüfungen und die Kommunikation mit dem Auto selbst; genaueres beschreibe ich auf der Seite meines Elektroauto-Simulators. Drumherum sieht man RCD- und Leitungsschutzschalter sowie einen Schütz, über den der Ladestrom geschaltet wird. Unten wird später noch ein LTE-Modem für die Internetverbindung integriert.
Nicht abgebildet ist ein kleiner Steuerrechner, der die Ladekarten ausliest und mit dem Backend kommuniziert. Dieser Rechner gibt dem Laderegler auch die Freigabe fürs Laden. Ebenso nicht gezeigt ist ein Kartenleser, mit dem die Ladekartennummer ausgelesen wird. Bei den kommerziellen Systemen ist der gesamte Aufbau etwas kompakter, aber prinzipiell sind genau diese Komponenten enthalten.
Open Charge Point Protocol
Der Steuerrechner nutzt üblicherweise das Open Charge Point Protocol. Das ist ein recht einfaches, SOAP/XML-basiertes Protokoll, das via HTTP die Ladestation mit dem Backend-System verbindet. Obwohl die Protokollversion 1.5 schon 2012 veröffentlicht wurde nutzen die meisten Ladesäulen noch diese Version. Der Nachfolger, Version 1.6, kommt erst sehr langsam in den Markt. Ich beziehe mich im Folgenden also auf die Version 1.5, aber die Schwachstellen existieren unverändert auch in Version 1.6.
Das Protokoll regelt nicht nur die Authorisation einer Ladekarte, sondern kann z.B. auch Firmwareupdates der Ladesäule anstoßen. Auch ist es z.B. für einen Callcentermitarbeiter möglich, die Verriegelung einer Ladesteckdose aus der Ferne zu öffnen oder einen Reboot anzustoßen.
Im Kern des Protokolls steht aber die Prüfung einer Ladekarte und das Freigeben eines Ladevorgangs. Auf Seite 13 der Spezifikation findet man folgendes Beispiel eines Ladeablaufs:
Die Ladestation prüft mit dem Authorize-Request zunächst, ob die Karte gültig ist. Sobald die Ladestation eine gültige Authorize-Antwort erhalten hat startet der Ladevorgang. Das teilt die Ladestation dem Backend über den StartTransaction-Request mit - darin sind z.B. auch Zählerstände für die Abrechnung enthalten.
In beiden Nachrichten wird die Kartennummer als “ID-Tag” übertragen. Das XML-Schema für AuthorizeRequest sieht so aus:
<s:complexType name="AuthorizeRequest">
<s:sequence>
<s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1"/>
</s:sequence>
</s:complexType>
Der Typ IdToken
ist lediglich ein String mit 20 Zeichen maximaler
Länge:
<s:simpleType name="IdToken">
<s:restriction base="s:string">
<s:maxLength value="20"/>
</s:restriction>
</s:simpleType>
Es gibt also keine Signaturen, keine asymmetrische Kryptographie. Die Freigabe der Ladestation erfordert nur eine vorab bekannte Kartennummer. Um es deutlich zu sagen: Jeder, der die Kartennummer kennt, kann Ladevorgänge über das zugehörige Kundenkonto abwickeln.
Leider wird diese Nummer nur sehr schlecht geschützt. In den meisten Fällen kann man die Kartennummer aus dem Netzwerkverkehr auslesen. Bei den mir bekannten Ladestationen (allesamt von großen Herstellern und preislich nicht im unteren Segment angesiedelt) ist die Verschlüsselung des HTTP-Datenverkehrs optional und lässt sich leicht umgehen. Ab Werk kommunizieren die Ladestationen allesamt unverschlüsselt.
Ein Schreibtischexperiment
Ich möchte nicht in die Infrastrukturen von Dritten eingreifen. Daher habe ich eine kleine OCPP-Backend-Infrastruktur geschrieben, mit der ich Ladestationen testen kann. Als Ladestation nutze ich die Technik eines großen deutschen Herstellers. Wie so ein Ladeablauf aussieht zeigt folgendes Video:
Für einen Angreifer ist es also trivial, die Kartennummern aus dem Datenverkehr zu extrahieren: Das Kommando
ngrep -d any -Wbyline -i '<idtag>(.*)</idtag>' port 8080 | grep idTag
sucht nach allen Vorkommen des XML-Elements <idtag>
im Datenstrom.
Damit die Ausgabe übersichtlich bleibt zeigt obiges Kommando nur die
Kartennummern an und unterdrückt alle anderen Ausgaben.
Wo ist das Problem?
Was kann man mit den Kartennummern nun machen? Es ist natürlich möglich, damit Karten zu klonen. Das funktioniert auf jeden Fall, aber es gibt noch andere Szenarien. Angenommen, ich betreibe eine Reihe von Ladestationen und habe mich einem Ladeverbund angeschlossen. Dann könnte ich mir ein kleines Programm schreiben, das einen Ladevorgang via OCPP simulieren kann. Dann kann ich die Kartennummern dazu verwenden, dem Backend des Ladenetzwerks Ladevorgänge vorzugaukeln, die nicht stattgefunden haben. Um nicht leicht entdeckt zu werden sammele ich reale Kartennummern über meine Ladestationen ein und speichere diese. Dann verwende ich die Kartennummern immer mal wieder in meinem OCPP-Client zur Simulation eines Ladevorgangs — und schon klingelt meine Kasse.
Im Roaming-Fall ist das Problem übrigens das Gleiche: Ladeverbünde kommunizieren über das OCPI-Protokoll. Dort werden die Kartennummern ebenfalls als Token verwendet. Allerdings gibt es verschiedene Möglichkeiten, wie Ladeverbünde das Roaming untereinander koordinieren: Neben Echtzeitabfragen kann ein Ladeverbund auch einem anderen Ladeverbund eine Liste aller gültigen Token übermitteln. Der Ladeverbund guckt also in seiner Kopie der Liste der gültigen Token nach, ob eine entsprechende Karte vorhanden ist. Im Zweifelsfall bekommt also z.B. New Motion erst nach einem Monat mit, das eine Kundenkarte an einer Ladestation der Stadtwerke Kaiserslautern benutzt wurde.
Was nun?
Leider basiert die komplette Sicherheitsarchitektur der Ladesäulen darauf, das die Kartennummern geheim bleiben. Das ist für eine Infrastruktur, die im öffentlichen Raum installiert wird, eine mehr als sportliche Ansage. Letztlich ist die Ladefreigabe anhand einer Kartennummer nicht sicher zu bekommen. Einzig eine asymmetrische Signatur, die eine Challenge vom Backend direkt auf der Karte signiert und zurück zum Backend transportiert, könnte die gegenwärtige Infrastruktur sicher machen.
Gleichzeitig ist es trivial möglich, den Datenverkehr zu beobachten und daraus z.B. die Kartennummern herauszufiltern. Das OCPP-Protokoll ist oft derart schlecht umgesetzt, das man annehmen muss, das sämtliche Protokolldaten unverschlüsselt übertragen werden. Es ist mir mit einfachen, selbst generierten Zertifikaten gelungen, einer Ladestation ein “offizielles” Backend vorzugaukeln. Die Ladestationen prüfen also nicht, ob ein Backendzertifikat wirklich zum richtigen Backend gehört — damit sind “Man In The Middle”-Angriffe (MITM) trivial möglich. Die Hersteller der Ladestationen müssen hier gründlich nachbessern.
Leider dürften Kunden gerade im Roaming-Fall nur sehr wenig Chancen haben, sich gegen eine unberechtigte Abbuchung zu wehren. Ein halbherziges Bekenntnis z.B. von New Motion im Forum von Going Electric ist in meinen Augen nicht genug. Die komplette Infrastruktur gehört neu gedacht. Das fängt bei der Verschlüsselung der Kommunikation an und muss endlich saubere Signaturen auf der Ladekarte selbst umfassen.