Byg dit eget OT Sikkerheds Lab (OpenPLC & FUXA)

For at forstå hvordan OT (Operational Technology) netværk kan kompromitteres og – vigtigere endnu – beskyttes, er praktisk “hands-on” erfaring uvurderlig. Det er dog de færreste der lige har et par overskydende vandpumper og industrielle netværksswitche liggende derhjemme.

Derfor har jeg bygget et virtuelt ICS/OT sikkerheds-lab. I denne guide vil jeg gennemgå hvordan du kan opsætte dit eget testmiljø helt gratis, ved at benytte OpenPLC (“Hjernen”) og FUXA (“Øjnene” / SCADA HMI).

Netværksdiagram over Lab’et

Før vi dykker ned i konfigurationen, er her et overblik over min arkitektur tegnet op. Mit “Level 1” OT netværk opererer på subnet 192.168.10.0/24, hvor mit primære omdrejningspunkt er en Ubuntu Server VM.

  [ Host Maskine / Pentester ]
           | (SSH, Web Browser)
           |
  =========+==================== Subnet 192.168.10.0/24 ======
           |
  .-----------------------------------------.
  | Ubuntu Server VM (IP: 192.168.10.10)    |
  |                                         |
  |   [ OpenPLC Runtime ] <------------.    |
  |   - Port 8080 (Admin Web UI)       |    |
  |   - Port 502  (Modbus TCP)         |    |
  |                                    |    | (Modbus TCP)
  |   [ FUXA SCADA (Docker) ] ---------'    |
  |   - Port 1881 (HMI Web UI)              |
  '-----------------------------------------'

1. Konfiguration af Netværk (Netplan)

Min Ubuntu Server skal have en statisk IP for at agere pålidelig PLC og HMI server. Jeg redigerede Netplan konfigurationen så ens37 interfacet sidder fast på adresse 192.168.10.10:

sudo nano /etc/netplan/00-installer-config.yaml

Indsæt følgende konfiguration for den statiske IP:

network:
  version: 2

  ethernets:
    ens33:
      dhcp4: true

    ens37:
      dhcp4: no
      addresses:
        - 192.168.10.10/24

Gør filen sikker og anvend indstillingerne overfor netværks-daemonen:

sudo chmod 600 /etc/netplan/00-installer-config.yaml
sudo netplan apply

2. Opsætning af “Hjernen”: OpenPLC

OpenPLC fungerer som vores virtuelle hardwaredel og vil lytte efter instrukser på Port 502 via den ekstremt udbredte SCADA-protokol; Modbus TCP.

Jeg tilsluttede mig Ubuntu-maskinen via SSH og klargjorde installationen fra Git:

sudo apt install git python3-pip -y
git clone https://github.com/thiagoralves/OpenPLC_v3.git
cd OpenPLC_v3
./install.sh linux

Herefter kan OpenPLC startes (forbered dig blot på at trykke Ctrl+C for at lukke det igen kortvarigt, mens vi installerer Docker):

sudo ./start_openplc.sh

3. Opsætning af “Øjnene”: FUXA (via Docker)

FUXA er en moderne webbaseret HMI (Human-Machine Interface), der lader os tegne og styre det grafiske SCADA interface - de famøse interaktive skærmbilleder man ser i et rigtigt kontrolrum. Da moderne Industrial Edge Gateways hyppigt kører container-applikationer, satte jeg applikationen op gennem Docker for realisme.

Installer Docker og tildel rettigheder

sudo apt install docker.io docker-compose -y 
sudo usermod -aG docker $USER 
newgrp docker

Kritisk Step: FUXA har i default tilstand utrolig svært ved at skrive til sine oprettede database-mapper grundet Docker-rettigheder. Det fikses på forhånd med en overlegen rettighed herunder for at undgå at blive mødt af en irriterende “Blank Screen” fejlbesked fra containeren senere:

mkdir -p ~/fuxa_scada/fuxa_data 
cd ~/fuxa_scada 
sudo chmod -R 777 fuxa_data

Docker Compose

I nogle tutorials forsøger de at omskrive en Base64 konverteret konfiguration for at undgå YAML indenteringsfejl, f.eks via en lang echo kommando i linux. For ikke at tilføje et unødvendigt led i en lab-opsætning, valgte jeg den direkte rute: Jeg oprettede en docker-compose.yml fil direkte på hosten. Filens indhold i en terminal teksteditor ser således ud:

version: '3'
services:
  fuxa:
    image: frangoteam/fuxa:latest
    restart: always
    ports:
      - "1881:1881"
    volumes:
      - ./fuxa_data:/usr/src/app/data

Start SCADA containeren op i baggrunden:

docker-compose up -d

4. Programmering af PLC’en (Structured Text)

En PLC er ubrugelig uden logikkode. Jeg oprettede en fil, pump.st (skrevet i SCADA sproget Structured Text) der har til formål at holde liv i et simpelt input-signal til en vandpumpe:

PROGRAM main 
  VAR 
    Pump_Switch AT %QX0.0 : BOOL; 
  END_VAR 
 
  (* Memory Latch: Keep the variable alive *) 
  Pump_Switch := Pump_Switch; 
END_PROGRAM 
 
CONFIGURATION Config0 
  RESOURCE Res0 ON PLC 
    TASK task0(INTERVAL := T#20ms,PRIORITY := 0); 
    PROGRAM instance0 WITH task0 : main; 
  END_RESOURCE 
END_CONFIGURATION 

Tip: Hvorfor dette kodestykke? I PLC’er forløber kørslen i meget hurtige gentagende loops kaldet Scan Cycles. Hvis koden blot var blank, ville et boolean input være flygtigt. Kodelinjen Pump_Switch := Pump_Switch; fungerer nemlig derimod som et internt Memory Latch, der holder koden i dens forgangne state, som lader hardwaren vide at den skal huske og fastholde Modbus-kommandoen, vi vil lade FUXA sende.

Filen blev derefter uploadet til OpenPLC Dashboardet (tilgået udefra via http://192.168.10.10:8080), hvorefter jeg skød systemet i hjertet via Start PLC.

5. SCADA Digital Twin: FUXA Tilkobling

Til aller sidst skulle vi samle puslespillet og få den grafiske repræsentation (FUXA) til at snakke sammen med den simluerede process kontrolhardware (OpenPLC):

  1. Tilgå FUXA via browseres på http://192.168.10.10:1881 og åbn Editor.
  2. Under fanen Configuration -> Devices tilføjes “OpenPLC” enheden med IP 192.168.10.10 og port 502. VIGTIGT: Husk at flippe “Enable” switchen på højre.
  3. Under fanen Tags klikkes på Add. Her laves et tag, der refererer ind til vores Structured Text variable, kaldet Pump_Status som peges på Address 1 (Svarende nøjagtigt til PLC’ens interne %QX0.0 lokation ud fra Modbus specifikationen).
  4. Gå til Graphics, træk en grafisk switch ind på canvas feltet, bind den op mod dit nylavede Pump_Status tag og tilføj et simpelt Click -> Toggle event.

Klikker man nu på Play-ikonet oppe i hjørnet af FUXA applikationen, kan man se magien udfolde sig live. Vi har succesfuldt oprettet ICS kommunikation over vores Level 1 Subnet, og kan til hver en tid lytte med på 192.168.10.10 interfacet via Wireshark for se raw SCADA bytes blive udvekslet!

Kilder

> Quiz: Test din viden

1. Hvad er OpenPLC's primære funktion i OT-labbet?

2. Hvilken port kører OpenPLC webinterfacet på?

3. Hvilken port kører FUXA SCADA-interfacet på?

4. Hvilket subnet bruges til det isolerede OT-testmiljø i labbet?