Tommy Murphy, Jack Wilson
University of Virginia
This project seeks to modify Firefox so that the system administrator has control over which extensions users can install and run. This document describes our motivation for such a feature and discusses the technical aspects of implementing such control. Created for CS493 at the University of Virginia.
Our motivation for this project initially was for a daycare where children would use the internet to play games and some older children to research for homework. After doing some research on parental control systems we learned that using an extension to regulate viewable content was inherently inadequate because there was no guarantee that the extension would be run. By simply booting Firefox into safemode the content managing extensions would not be run, and a child would be able to bypass the filters.
As we began to research a solution to this problem we realized that there were many groups of people who would like to be able to regulate the extensions that are going to be run. Generally System Administrators would like to be able to decide which extensions should be run, and if they want require that some extensions be run.
Finally, we found a couple news articles that presented problems associated with updating extensions on non-secure channels. Google, Yahoo, Facebook, and many other sites were updating Firefox toolbars without SSL which opened them up to man in the middle attacks, in which an evil-doer could "update" their toolbar by replacing it with a malicious extension. Additionally we found that it was possible to "manually" install an extension by just editing a text file, a method that recent email virus used to install a malicious extension.
By using our version of Firefox the user would be protected from accidentally updating an extension through an insecure channel, and would be prohibited from loading any new extensions without the explicit consent of the system administrator.
We partitioned the design in two. The first part is concerned with create lists of the extensions that we are going to allow, and/or require. The second part is in charge of enforcement. As extensions are loaded we check to make sure they are permitted and then check that all required extensions are loaded. If they aren't all loaded we will prevent Firefox from starting. It is a simple design that allows basic implementation of the management system.
We created two configuration files: allowext.ini and requiredext.ini files that are sectioned off by username. Each username has an associated boolean which enables or disables the lists. Currently on the "Admin" user has the files disabled. Finally, the extensions that are allowed or required for each user are listed by MD5 hash of the extension's files. The MD5 hashes of the extension is generated by recursively generating the MD5 hashes all of the .js, .rdf, .jar, .xpt and .xul files of the extension and combining them together. This ensures the unique identity of the extensions and prevents other extensions trying to imitate other extensions by spoofing GUID numbers or other identifying information.
First we need to get the current user username from Firefox. We use different commands depending on if the machine is UNIX or WINDOWS. Firefox has code to get the username, mostly we copied that code and put it where we needed it. Once we have the username we create two nsCStringArray's to hold the allow and required lists and two booleans to hold the enabled switches. The ini files are then loaded - first finding the files in the directory that Firefox is run in. Then we load a native Firefox parser to parse the ini files. Finally we find the users section and load the enabled boolean and the extensions' MD5 hashes. Then we call the regular function to load the extensions, but we pass the two booleans and the two lists as well as the default parameters.
Next we load the extensions. If neither of the two boolean is enabled then we jump to the default Firefox behavior. Otherwise, we check to see if the extension is actually a theme, if it is we unconditionally install it. If it isn't we generate the hash for the extension on the fly. Then assuming that the enabled boolean for this user is true, we check to see if the hash is in the allow list. If it isn't in the list we deny installing it and prevent firefox from loading. If it is in the list we then check to see if it is in the required list. Assuming the required boolean is true and it is in the list then we remove the hash from the required list. Finally we call on the default behavior to load the extensions.
We have tested the code throughly, and have not found any major bugs. It is successful at detecting changes to an extension's source and will prevent Firefox from loading if a required extension is not enabled. We cannot compile the code on Windows yet, but expect it to be done soon. The code is pretty simple and doesn't try to do too much at a time. We are satisfied with our work.
There are some things that could work better and we may fix them in any future releases. We would like Firefox to exit gracefully if the required extensions list isn't complete instead of just preventing Firefox from running. Also, we would like to prevent users from disabling or uninstalling the extensions from the GUI in Firefox. Doing this will prevent the user from starting Firefox again because a required extensions will no longer be present. In order to prevent users from entering SafeMode and disabling all extensions we had to disable safemode, which could present some problems, but for the normal user in a shared environment we felt like they wouldn't need to enter SafeMode. The GUI shows that all extensions have been loaded even if they haven't been loaded, this isn't a functionality problem, but we would like things to be consistent. Finally, we would like to integrate the INI file creation into Firefox.
We have not found any versions of Firefox that regulate extensions at load time.
Click Here to download.