Concluded·9 Jun 2026 · 2 min read

EtherNet/IP and S7comm: capturing tag and DB writes

EtherNet/IP · CIP · cpppo · S7comm · python-snap7 · Docker · tshark

Same method as the Modbus lab, two more protocols. The point is to check whether a modern vendor fieldbus changes the read/write-without-auth result. It does not, so this lab documents the setup and the decodes for both.

Lab setup

Two sims on a dedicated docker network, each a stand-in for a real controller:

  • EtherNet/IP (Rockwell family)cpppo, a pure-Python CIP/ENIP implementation, serving named tags on TCP 44818:
    python -m cpppo.server.enip --address 0.0.0.0:44818 MOTOR_CMD=INT SETPOINT=INT LEVEL=INT
  • S7comm (Siemens family)python-snap7 Server sharing one data block (DB1) on TCP 102 (security/s7-server.py), seeded so DB1.DBW0 = 4200 (42.0 Hz on a Hz x 100 scale).

Capture runs on the network bridge; the client writes come from a peer container.

Rockwell — EtherNet/IP

The CIP client opens a session and writes a tag. RegisterSession is a handshake, not a login — no credential is exchanged.

python -m cpppo.server.enip.client --address enip-plc:44818 SETPOINT=6000 SETPOINT
tshark decode of the CIP request and the written value 0x1770 on the wire
The CIP request over ENIP, and the written value SETPOINT=6000 (0x1770, little-endian 70 17) located in the cleartext payload. Tag names travel as ASCII.

Siemens — S7comm

The client connects (rack 0, slot 1), reads DB1.DBW0, writes 1500, reads back, restores (security/s7-write.py). Client output from the run:

BEFORE   DB1.DBW0 = 4200  (42.0 Hz)
WROTE    DB1.DBW0 = 1500  (15.0 Hz)
AFTER    DB1.DBW0 = 1500  (15.0 Hz)
RESTORED DB1.DBW0 = 4200  (42.0 Hz)

The S7comm exchange, decoded:

tshark s7comm decode: Setup Comm 0xf0, Read Var 0x04 returning 1068, Write Var 0x05 carrying 05dc
0xf0 Setup Communication carries no login. 0x04 Read Var returns 0x1068 (4200 = 42.0 Hz); 0x05 Write Var carries 0x05dc (1500 = 15.0 Hz). Read-back and restore follow.

Same shape, side by side

Rockwell — EtherNet/IP · CIPthe most-installed US plant floorRegisterSession — opens a sessionno loginWrite Tag SETPOINT =6000 (0x1770, on the wire)Siemens — S7commdominant across GCC and EuropeSetup Communication (0xf0)no loginWrite Var DB1.DBW0 =1500 (0x05dc = 15.0 Hz)
The same setpoint write, captured off two different name-brand controllers. Neither protocol asked who was writing. The value travels in the clear on both.

Both writes reach a control register with no authentication and travel in cleartext. The trust model is identical to Modbus:

Modbus TCPEtherNet/IPS7commAuthenticationnonenonenoneIntegrity / signingnonenonenoneValues readable on wireyesyesyesAnyone can writeyesyesyes
Three protocols from three eras and three vendors. The trust model is identical: the wire believes whoever is on it. This is not a bug list. It is a shared assumption that the network used to enforce.

Mitigation

Two places to defendProtocol layerCIP Security (Rockwell) and S7 access-protection levels exist, but are optional, uneven across a mixed fleet, and usually off.Network layerSegment the cell, permit only the paths that must write, and alarm on a write from a host that never writes. Works on every controller, old or new.
Both vendors ship a protocol-layer answer. Both are optional, patchy across a mixed fleet, and off by default. The boundary you can rely on across every controller is still the network.

CIP Security (Rockwell) and S7 access-protection levels exist and are worth enabling, but they are optional, uneven across a mixed fleet, and off by default. The boundary that holds across every controller, new or legacy, is the network: segment the cell, permit only the writes that must happen, and monitor for the rest.

Harness

The cpppo commands, s7-server.py, s7-write.py, and the enip.pcap / s7.pcap captures are in the modbus-copilot repo security/. Isolated lab, own equipment only.

Why this matters, in plain terms: your expensive PLC is just as naked.

Newsletter

New essays, by email.

SCADA, cloud, AI, and the plant floor — a short email when something new is published. No noise, unsubscribe anytime.