Setup and exploit a OT lab: Modbus part 2 black blox , vlan and stuff.

biero llagas
7 min readSep 8, 2023

--

Intro

Hello everyone, back for this second part on setting up and running a lab based on the modbus protocol.

Just to remind you of part 1, we explained the following.

  • Setup portainer and add containers.
  • Basic information to make a modbus request.
  • Setup the link between OpenPLC and ScadaBR

In this second part, we’re going to get a little more technical, and explain the following.

  • Setup and interconnecte multiple vlan inside a docker environment
  • Integrate a semi realistic production environment and setup an attack into the docker environment.
  • Capture and analyze a modbus frame via an MITM attack for making a custom modbus request.

So you’ll have understood, the aim of this lab is to demonstrate how to exploit a system using a black box approach.

Define the objective

The new objectif of this lab is to send a request

The aim of this lab is to send a modbus request that will disrupt the normal behavior of the PLC. However, we don’t have theres informations.

  • The PLC’s IP address.
  • The address of the modbus register to be requested.
  • The data type to be sent.

So we have no prior information.

There are several ways to achieve this, 3 of which come to mind.

- Bruteforce the values.
- Extract information from the maintenance technician by any means necessary.
- Recover the information via the network, because we know that modbus is weak and does not have native encryption.

First is in conflict with the level of caution that must be taken in production environments, and the second is in conflict with ethics and legality. So we’ll look at the third.

It’s based on the attack nammed “ARP Spoofing”. We’ll explain and develop this attack a little further, but for now we’ll concentrate on the lab setup.

Productions environement: Vlan and Docker with portainer.

In a realistic environment, like anywhere else, a computer network is segmented into vlan, and each vlan may or may not be interconnected. In this case, we’ll have two vlan, one for the PLC, and one for the HMI. The two VLAN will be connected via a router which will have an interface in each VLAN.

This router will be configured to route all traffic between VLAN IP address ranges.

Here is the network diagram of our lab.

No transitions, here’s how to apply this network diagram.

1: Setup the virtual the VirtualBox Host-Ony Ethernet Adapter.

NOTE: I use that only because my computer have only one Ethenet interface.

Go inside the “Gestionaire de réseaux hôte” inside the VBox UI.

Create 2 new interface with a custom IP range, I use personnaly there range :

  • 192.168.71.0/24
  • 192.168.90.0/24

You should find yourself with the following screens.

In the network section of your virtual machine running portainer, add the two newly created network interfaces. Don’t forget to activate “allow all” for the promiscuity mode option, and to check “cable connected”.

We have now a virtual machine with at least two network interfaces dedicated to the futur VLAN.

2: Setup macvlan on portainer.

Next we need to assign addresses and segment the network between the two vlan’s, to do this we’ll use docker’s macvlan option, in short, macvlan links with a network interface and assigns mac addresses linked to the interface to docker.

For a more in-depth explanation of macvlan, please consult this link.

Adding macvlan is a two-step process.

To begin, you need to add a configuration network.

Secondly, you add the network you’re going to use and add it to the different docker.

Do the same thing for the second vlan, personally, I just changed the 1 by a two in the names.

3: Deploy configure and set the network for each docker

For the time being, we need 3 machines

  • The router.
  • The OpenPLC machine.
  • The ScadaBR machine.

Here are the commands to deploy, configure and install the tools required for the 3 machines.

The router

docker runvimagick/iptables

Add the two macvlan interface to the router docker.

Go back to the Console :

iptables -A FORWARD -i vlan1_name -o vlan2_name -j ACCEPT
iptables -A FORWARD -i vlan2_name -o vlan1_name -j ACCEPT
echo 1 > /proc/sys/net/ipv4/ip_forward

## if you whant you can change the ip of eatch interface to fetch directly to de default gatway
ifconfig eth1 192.168.71.1 netmask 255.255.255.0
ifconfig eth0 192.168.90.1 netmask 255.255.255.0

OpenPLC

docker run --cap-add=NET_ADMIN -p 8080:8080 -p 502:502 tuttas/openplc_v3

Add the two macvlan interface to the OpenPLC docker.

Go back again to the Console.

# go inside the Console of the docker
apt update
apt-get install iputils-ping
apt install net-tools
route add default gw IP_OF_ROUTER iface_name

ScadaBR

docker run --cap-add=NET_ADMIN --privileged -p 8081:8080 -itd bitelxux/scadabr

Add the two macvlan interface to the ScadaBR docker

Go the Console and type.

# go inside the Console of the docker
apt update
apt-get install iputils-ping
apt install net-tools
route add default gw IP_OF_ROUTER iface_name

Redo part 1 basic with biero

From this point on, the two machines should be able to ping each other. Then you can repeat the tutorial from part 1, you just have to change the IP addresses and everythings will normally be ok.

If you have latency or other problems, I advise you not to use the automatic request from scada BR, but just to make a manual request (pic related).

Great, we now have a production environment, which is pretty close to reality.

Setup the Attack.

Kali docker

docker run --cap-add=NET_ADMIN --privileged -itd kalilinux/kali-rolling

Add the two macvlan interfaces to the kali docker.

Go to the Console.

# go inside the Console of the docker
apt update
apt-get install iputils-ping
apt install net-tools
apt install tcpdump
apt install tshark

After that remove the bridge interface from the network config of the kali container.

Arpspoofing & Packet capture

Now the network shems can be represented like that

NOTE: for understanding better the request responce between the two vlan I recomend you to try to put your kali on both interface (one time with only vlan1 , and the other with only vlan2), and to have a full request respond converstions you need to make the arspoof on both interface.

For this part you will need two terminals on your kali container (or you can backgroud the arpsoofing if you want).

On the first console.

arpspoof -i IFACE_NAME IP_OPENPLC IP_ROUTER

On the second console.

tcpdump -i INTERFACE_NAME -w out_modbus.pcap

NOTE: you can analyse the packet via tshark (pic related), but for convenience sake I will make the analyse withwireshark (I have extract the pcap via the “http.server”’s python module if you want to extract the pcap from the docker).

Packet analyse

Modbus 201: network structure.

The first communication between a client (monitoring system MS, ScadaBR, OpenPLC ,etc…) and a server (PLC) is a 3-way handshake:

  • ScadaBR -> OpenPLC: SYN
  • OpenPLC -> ScadaBR: SYN/ACK
  • ScadaBR -> OpenPLC: ACK

Here the exemple of a 3-way handshake captured while working on this lab between the ScadaBR (192.168.71.3) and the OpenPLC (192.168.90.3).

After that, you may have the actual modbus packet. And talking about the modbus packet.

Modbus 202: packet structure.

Here a packet that I have captured while finishing this lab.

The legend captions is the following.

  • 1 : informations about the src IP and the Dest IP
  • 2: confirmation that the port 502 is used
  • 3: Modbus TCP uses the same Transaction ID for both the query and the response
  • 4: The message is intended to and responded by the RTU with the ID 1 (in this case there is only 1 RTU, but in real environments, there may be more of them)
  • 5: The function used is number 1 (000 0001 in binary), which matches standard Mobus function codes
  • 6: the coil value that has been requested by ScadaBR.

With all these informations we can finaly make our modbus request with mbtget.

Profit

Finally, we can request and send any number of requests to the PLC, here’s an example of an r1 request (we know it’s a read coil request, because we found it in the network capture).

I leave you here, try to write one of the coils, have fun ^^.

Thank you for taking the time to read this article to the end, if you have any questions don’t hesitate.

--

--