Offensive Security Testing

DERSim can act as a controlled adversary: you arm one or more attacks and the simulator mutates the data it puts on the wire — SunSpec/Modbus, IEEE 2030.5 (CSIP), and OCPP — while its internal physics keep running truthfully. Use it to validate that your DERMS, CSMS, aggregator, or monitoring system detects compromised-device behavior, falsified telemetry, and machine-in-the-middle manipulation.

Attacks are armed and disarmed at runtime from the Offensive Security Testing tab in the dashboard, or through the /offensive REST API — per device, with no restart, and with a live truthful-vs-wire diff.

!!! note "Replaces the old --compromised_behavior flag" Earlier releases triggered a single fixed behavior with the --compromised_behavior HACK_SCRIPT command-line option. That flag has been removed. Everything it did is now available — alongside many new attack types — through the Offensive Security Testing tab and REST API. See Migrating from --compromised_behavior.

Enabling offensive testing

Offensive testing is off by default and gated by a single launch flag:

--offensive_enable yes

When it is off, the offensive features are inactive, the REST endpoints return 404, and the dashboard tab is hidden. When it is on, a persistent OFFENSIVE TESTING ACTIVE banner appears in the dashboard whenever any attack is armed, and a Panic-disarm all button clears every device in one click. DoS-style attacks enforce their own non-bypassable rate ceilings.

Only data read by or published to external systems is mutated. Every other dashboard view (Overview, Battery, Grid Support, …) shows the device's truthful internal state. The SunSpec Client tab is the exception — it connects over Modbus on purpose, so it sees the falsified values exactly as a real client would.

The dashboard tab

The Offensive Security Testing tab has four panes:

Pane What it does
Catalog Every available attack, grouped by family and filterable. Click Arm to add one to the selected device. Only attacks that apply to the device's enabled protocols are shown.
Armed The attacks armed on the device — each with an enable/disable toggle, tunable parameters, condition gates, and Remove.
Wire Diff The live truthful-vs-wire table: protocol, key, truthful value, mutated value, and the attack responsible. Refresh / Clear per device.
Banner Device selector, the ACTIVE indicator, and Panic-disarm all.

A typical loop: select a device → arm an attack → tune its parameters → watch the Wire Diff populate → disarm.

Attack categories

Attack type What it does Examples
Falsified telemetry & identity Read/emit-time value mutations on measurements, identity, nameplate ratings, and setpoints. Many are cross-protocol — one arm lands on SunSpec and CSIP (and identity also on OCPP). falsify_device_identity, meas_low_v, meas_zero_p, nameplate_low_p, settings_high_p
OCPP payload manipulation Malicious CP→CSMS message content. boot_sql_injection, meter_negative_energy, falsified_disconnection
Protocol fuzzing Walks outbound payload fields and applies one mutation per gated emit via a chosen strategy, bounded by a subtlety dial + rate ceiling. fuzz_ocpp, fuzz_sunspec, fuzz_csip
Out-of-order / impossible state State-machine and ordering violations. double_authorize, stop_before_start, csip_inconsistent_state
Resource / denial-of-service Rate-bounded flooding and oversized payloads. ws_reconnect_storm, meter_value_flood, oversized_boot_fields
Physical-world fraud Billing, capacity-market, and compliance falsification. energy_theft, over_credit_soc, capacity_fraud, reactive_power_falsification

DERSim is the charge-point / DER simulator, so every attack is something the device itself can produce. CSMS-side / DERMS-side attacks are out of scope — pair DERSim with a separate server-side tool for those.

SunSpec measurement & identity reference

The SunSpec telemetry & identity attacks cover the same falsifications as the legacy --compromised_behavior options. Each applies value = value × scaling + offset (or sets the value directly). The voltage/frequency/current/apparent/reactive/power-factor and zero/invert attacks also mutate the matching CSIP monitoring scalar, so one arm falsifies both wires.

Attack id Effect Mutation
da_manipulation Modify the device ID DA → 200 or 201
falsify_device_identity Change manufacturer & model Prefix Evil to Mn/Md (SunSpec) and BootNotification vendor/model (OCPP)
meas_p_always_nameplate Pin power to nameplate W, VA = WMaxRtg, VAMaxRtg; Var = 0
meas_q_always_{minimum,maximum,zero} Pin reactive power Var = −VarMaxAbsRtg / +VarMaxInjRtg / 0
meas_zero_p Zero power & current W, VA, Var, A = 0 (SunSpec + CSIP)
meas_invert_q Reverse reactive sign Var ×= −1 (SunSpec + CSIP)
meas_low_v / meas_high_v Falsify line voltage V ×= 0.89 / 1.11 (SunSpec + CSIP)
meas_low_l1_v / meas_high_l1_v Falsify L1 voltage VL1 ×= 0.89 / 1.11
meas_low_f / meas_high_f Falsify frequency Hz += −2.3 / +2.3 (SunSpec + CSIP)
meas_low_amps / meas_high_amps Falsify current A ×= 0.65 / 1.35 (SunSpec + CSIP)
meas_high_s / meas_low_s Falsify apparent power VA ×= 2.0 / 0.5 (SunSpec + CSIP)
meas_high_q / meas_low_q Falsify reactive power Var ×= 2.0 / 0.5 (SunSpec + CSIP)
meas_low_pf / meas_low_reversed_pf Falsify power factor PF shifted toward zero, clamped to [−1, 1] (SunSpec + CSIP)
nameplate_* Scale published DER ratings e.g. WMaxRtg, VAMaxRtg, VNomRtg × factor
settings_* Scale setpoint limits e.g. WMax, AMax, VNom × factor
change_common_model_id / change_common_model_length Overwrite common-model registers Mid / Len = constant

The same SunSpec-side control is also reachable from the 64412 SunSpec Modbus model, so an attack can be armed over Modbus as well as from the dashboard:

Condition gates

Any armed attack can carry conditions — it only fires when all of its conditions are true on the current tick. With no conditions it fires on every emit.

Condition Fires when Fields
always every tick (default)
soc_above / soc_below battery SOC crosses a threshold threshold
p_above / p_below active power crosses a threshold (W) threshold_w
every_n_ticks every Nth emit (flicker) n
after_n_ticks from the Nth emit onward (delayed onset) n
random_at_rate stochastically, per-tick probability prob_per_tick, seed
time_window inside an ISO start/end window start_iso, end_iso

For example, a voltage falsification gated by soc_above(threshold=90) and every_n_ticks(n=3) only fires once the battery is nearly full, and then only on every third emit.

Preset bundles

A bundle arms a named, one-click scenario built from several attacks. Loading a bundle replaces the device's armed set with the bundle's members.

Bundle Scenario
stuck-at-nameplate DER misreports steady full-rated output (power at nameplate, reactive zero).
low-v-storm Sustained under-voltage + under-frequency across SunSpec and CSIP.
hostile-cp A compromised charge point end to end: injection, meter fraud, SoC lie, falsified disconnect, reconnect storm.
compromised-csip-client A compromised 2030.5 client: inflated capacity, reactive-compliance falsification, contradictory DERStatus.
grid-abnormal-trip-test Over-voltage + over-frequency excursion for IEEE 1547 ride-through / trip conformance.

Arm one from the dashboard, or over REST:

POST /api/dersim/offensive/devices/<device_id>/presets/hostile-cp

Worked example: falsified identity

  1. Launch DERSim with --offensive_enable yes and point a PV DER at your aggregator or monitoring system.
  2. Arm falsify_device_identity from the catalog (or POST /api/dersim/offensive/devices/<id>/presets/falsify_device_identity).
  3. The device now advertises Evil <Manufacturer> / Evil <Model> on every wire it speaks — SunSpec common-model Mn/Md and, if OCPP is wired, the BootNotification vendor/model. The Wire Diff pane shows the deltas; your monitoring system should raise its device-identity detection.
  4. Click Remove (or Panic-disarm all). The wire view returns to truthful immediately.

Migrating from --compromised_behavior

The --compromised_behavior command-line flag has been removed. The replacement is strictly more capable:

Then Now
One global behavior, fixed at launch Per-device attacks, armed/disarmed at runtime
SunSpec/Modbus only SunSpec, OCPP, and CSIP — often the same attack on all three
No visibility Live truthful-vs-wire diff + ACTIVE banner
Restart to change Arm / tune / disarm with no restart

If your lab scripts passed --compromised_behavior <script>, replace the launch flag with a runtime POST …/presets/<id> call (single attack or bundle) after the device registers. The only offensive-related launch flag now is --offensive_enable yes.