Security: Dynamically load libreoffice extension (PoC)

Only load the LibreOffice extension for opening hwp/hwpx when it is
actually needed. Adding an extension to libreoffice may allow for it to
run arbitrary code. This makes it trust more scalable by trusting
LibreOffice extensions only for the filetypes which they target.

Reasoning
---------

Assuming a malicious `.oxt` extension this means that the extension has
arbitrary code execution in the container. While this is not an
existential threat in itself, we should not expose every Dangerzone user
to it. This is achieved by dynamically loading the extension at runtime
only when needed.

This ensures that a compromised extension will in its least malicious
form be able to modify the visual content of any hancom office files but
not *every file*. In the more malicious version, if the code execution
manages to do a container escape, this will only affect users that have
converted a Hancom office file.
This commit is contained in:
deeplow 2023-07-18 11:25:58 +01:00
parent 3e895adbab
commit d16961bed6
No known key found for this signature in database
GPG key ID: 577982871529A52A
2 changed files with 25 additions and 5 deletions

View file

@ -34,15 +34,12 @@ RUN mkdir tessdata && cd tessdata \
&& find . -name '*.traineddata' -maxdepth 2 -exec cp {} /usr/share/tessdata \; \
&& cd .. && rm -r tessdata
RUN mkdir h2orestart && cd h2orestart \
RUN mkdir /libreoffice_ext && cd libreoffice_ext \
&& H2ORESTART_FILENAME=h2orestart.oxt \
&& H2ORESTART_VERSION="v0.5.7" \
&& wget https://github.com/ebandal/H2Orestart/releases/download/$H2ORESTART_VERSION/$H2ORESTART_FILENAME \
&& echo "$H2ORESTART_CHECKSUM $H2ORESTART_FILENAME" | sha256sum -c \
&& _DESTDIR="/usr/lib/libreoffice/share/extensions/h2orestart/" \
&& install -dm755 $_DESTDIR \
&& unzip $H2ORESTART_FILENAME -d $_DESTDIR \
&& cd .. && rm -r h2orestart
&& install -dm777 "/usr/lib/libreoffice/share/extensions/"
ENV PYTHONPATH=/opt/dangerzone

View file

@ -80,19 +80,24 @@ class DocumentToPixels(DangerzoneConverter):
# .hwp
"application/vnd.hancom.hwp": {
"type": "libreoffice",
"libreoffice_ext": "h2orestart.oxt",
},
"application/haansofthwp": {
"type": "libreoffice",
"libreoffice_ext": "h2orestart.oxt",
},
"application/x-hwp": {
"type": "libreoffice",
"libreoffice_ext": "h2orestart.oxt",
},
# .hwpx
"application/vnd.hancom.hwpx": {
"type": "libreoffice",
"libreoffice_ext": "h2orestart.oxt",
},
"application/haansofthwpx": {
"type": "libreoffice",
"libreoffice_ext": "h2orestart.oxt",
},
"application/hwp+zip": {
"type": "libreoffice",
@ -144,6 +149,9 @@ class DocumentToPixels(DangerzoneConverter):
if conversion["type"] is None:
pdf_filename = "/tmp/input_file"
elif conversion["type"] == "libreoffice":
libreoffice_ext = conversion.get("libreoffice_ext", None)
if libreoffice_ext:
await self.install_libreoffice_ext(libreoffice_ext)
self.update_progress("Converting to PDF using LibreOffice")
args = [
"libreoffice",
@ -303,6 +311,21 @@ class DocumentToPixels(DangerzoneConverter):
):
shutil.move(filename, "/tmp/dangerzone")
async def install_libreoffice_ext(self, libreoffice_ext: str) -> None:
self.update_progress(f"Installing LibreOffice extension '{libreoffice_ext}'")
unzip_args = [
"unzip",
"-d",
f"/usr/lib/libreoffice/share/extensions/{libreoffice_ext}/",
f"/libreoffice_ext/{libreoffice_ext}",
]
await run_command(
unzip_args,
error_message="LibreOffice extension installation failed (unzipping)",
timeout_message="unzipping LibreOffice extension timed out 5 seconds",
timeout=5,
)
async def main() -> int:
converter = DocumentToPixels()