Mozilla Firefox vulnerable to injection via Gecko configuration file

Background

Code injection is the exploiting of a bug or a system’s design in order to change the behavior of a process, a website or a system. Malware authors usually exploits such bugs in order to infect computers and devices, install malicious viruses and perform different tasks like stealing user’s passwords and banking information, spying on their online activities and more.

While playing with Firefox, I’ve noticed that with two small steps, one could easily inject malicious code into Firefox and it could go unnoticed…

The vulnerability

Firefox, Thunderbird and other products use Mozilla’s Gecko layout engine. Gecko has a list of different libraries it loads automatically on startup in a plain-text file called dependentlibs.list, stored under the product’s installation folder. However, when Gecko reads the file to load the DLLs, it doesn’t check if the list was tampered with nor does it verify the digital signatures of the files (that they are signed by Mozilla or by Microsoft, the latter for Windows-related dependencies)

By altering the list and adding a new entry, one can easily cause Firefox and other Gecko-based software to load any DLL, includes spyware, keyloggers and other malicious payloads, without the user’s approval and likely without raising suspicion with security products.

Even the coming Firefox 50 is vulnerable to this injection method as demonstrated below.

(NOTE: only tested on Windows, though it potentially affects macOS, Linux and Android versions and Gecko-based products as well)

How it works

A malicious actor needs to

  1. copy a DLL into Firefox installation folder and
  2. edit the file dependentlibs.list to include a new line with the name of the copied DLL before xul.dll (otherwise it will cause an error loading Gecko’s XPCOM system)

Both steps might require administrator privileges (depending on where and how Firefox was installed).

This can be exploited either manually by convincing a user to do the changes (done in the past, but it’s a less likely scenario), or automatically during installation of other software, a common practice by many legitimate software authors, or by exploiting other vulnerabilities, not necessarily in Gecko-based products.

Demo

We created a very simple DLL that shows a message box indicating the injection was successful, here’s the code:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    if (DLL_PROCESS_ATTACH == ul_reason_for_call)
    {
        MessageBoxW(NULL, L"If you see this message, you can inject any DLL into Firefox and Thunderbird", L"Firefox/Thunderbird hacked", MB_OK);
    }
    return TRUE;
}

We compiled it for both 32 and 64 bit architectures and copied the DLLs into various Gecko-based products and manually edited dependentlibs.list

Mozilla Firefox

Mozilla Thunderbird

Other Gecko-based products (like SeaMonkey)

Mozilla’s Response

We’ve notified Mozilla last week about the vulnerability via Bugzilla but they have decided to ignore the vulnerability for two reasons: the first is that they might remove the use of dependentlibs.list in the future (though it’s not guarantied yet), and the second because there are other ways to inject Firefox [if you modify the installation directory]

You can read their response in the bug report on Bugzilla

Conclusion

Many products and websites use a configuration file to load components dynamically, but this practice requires checking what is being loaded and if the list was tampered in any way to prevent such vulnerabilities.

We hope that Mozilla will change their minds and fix the issue in the next release.