Write-up Attacking ICS Plant 1

Andrea Dainese
December 02, 2020
Post cover

This post explore my first TryHackMe room: Attacking ICS Plant #1 . Because the VM can be unresponsive, I also provide the OVA for offline labs.

The room allows exploration of a simulated bottle-filling plant, gaining basic knowledge on ICS protocol weakness.

Note: VirtuaPlant can be downloaded from GitHub . The VM is based on Debian 8, and it’s configured by DHCP. I added additional scripts to simulate plant personnel. No SSH password is required, so I don’t provide it.

Task 1: Introduction to OT/ICS

Read and understand that:

  • industries are managed by sophisticated, mission-critical computers (SCADA systems);
  • security is not the priority in OT/ICS;
  • operators can manually override the behavior of the plant via mouse/keyboard/touchscreen, locally or remotely;
  • malicious software can override the behavior of the plant-like HMI does.

Task 2: Introduction to Modbus protocol

Read and understand how the Modbus protocol works.

To properly continue the lab, download an install pymodbus Python3 module:

pip3 install pymodbus==1.5.2

Then download, unpack and analyze the attached scripts.

The script discovery.py is used to understand how the plant is working, therefore it contains the answer to the first question.

The script set_registry.py is used to set a custom value to a single register, therefore it contains the answer to the second question.

Task 3: Discovery

Before attacking a plant we need to understand how it works. Deploy the VM and connect using a browser to it using HTTP. Mind that pressing the ESC button on the browser will restart the plant.

We can see the following phases (1st answer):

  1. Initialization: the plant is starting from the beginning. The roller moves the first bottle under the nozzle.
  2. Filling: once a bottle is under the nozzle, the nozzle opens and the water flows in the bottle.
  3. Moving: once the bottle is filled, the roller starts again moving the next empty bottle under the nozzle.

Looking how the plant is working, we can see two sensors (2nd answer) and three actuators (3rd answer):

  • water level sensor is red (11th answer)
  • bottle position sensor is green (12th answer)
  • actuator to start/stop the plant
  • actuator to open/close the nozzle
  • actuator to start/stop the roller

Now we need to detect which registries are controlling sensors and actuators. Start the script discovery.py and restart the plant (pressing the ESC button).

The plant is using a 16bit long (4th answer) holding register, which allows sixteen binary values (6th and 7th answers), but only 5 registries are used.

Let’s check which bits are changing their values in each phase:

  1. Initialization: registry 3 = 1, registry 16 = 1 (8th answer)
  2. Filling: registry 2 = 1, registry 4 = 1 (9th answer)
  3. Moving: registry 1 = 1, registry 3 = 1 (10th answer)

Four (5th answer) registries are continuously changing their values once the plant is initialized.

Because the roller is moving in phases 1 and 3, while it’s stopped in phase 2, the registry 3 (13th answer) is the only one that can be associated with the roller:

  1. Initialization: roller is on (registry 3 = 1)
  2. Filling: roller is off (registry 3 = 0)
  3. Moving: roller is on (registry 3 = 1)

In phase 3 the roller is off until the bottle is filled: we can deduce that the water level sensor is associated with registry 1.

We can also deduce that actuator to start/stop the plant is associated with registry 16.

Let’s recap:

  • Three phases:
    • Initialization: once the plant is started, the roller is on waiting for the first bottle.
    • Filling: once a bottle is under the nozzle, the nozzle opens and the water flows in the bottle.
    • Moving: once the bottle is filled, the roller starts again moving the next empty bottle under the nozzle.
  • Actuators:
    • Start/stop the plant: registry 16.
    • Start/stop the roller: registry 3.
    • Open/close the nozzle: registry 2 or 4. We need to spend additional time on that.
  • Sensors:
    • water level: registry 1 (red sensor)
    • bottle position: registry 2 or 4 (green sensor). We need to spend additional time on that.

Task 4: Play to learn

Using the script set_registry.py we can play with registries 2 and 4 forcing a specific value. After a while, we can realize that nozzle is associated with registry 4 (1st answer) and we can deduce that the bottle position sensor is associated with registry 2.

We finally figured out how the plant works describing all changing registries:

  • Registry 1: associated with the bottle sensor. Value is 1 if the bottle is under the nozzle.
  • Registry 2: associated with the water level sensor. Value is 1 if the bottle is filled.
  • Registry 3: associated with the roller actuators. Value 1 turns the roller on.
  • Registry 4: associated with the nozzle. Value 1 opens the nozzle.
  • Registry 16: associated with the plant. Value 1 starts the plant

Task 5: Attack

Because the Modbus protocol is a clear-text unauthenticated protocol, and the registries are writable by anyone, we can alter how the plans is working by abusing its registries:

  • Force registry 16 = 0 to stop the plant. Force also registry 3 = 0 to stop the roller and registry 4 = 0 to close the nozzle (script attack_shutdown.py answers the 1st question, script attack_shutdown2.py improves the attack and answers the 4th question).
  • Force registry 16 = 1 to start the plant. Force registry 3 = 1 to start the roller and registry 4 = 1 to leave the nozzle open (script attack_move_fill.py answers the 2nd question, script attack_move_fill2.py improves the attack and answers the 5th question).
  • Force registry 16 = 1 to start the plant. Force registry 3 = 0 to stop the roller and registry 4 = 1 to leave the nozzle open (script attack_stop_fill.py answers the 3rd question, script attack_stop_fill2.py improves the attack and answers the 6th question).