Pages

Showing posts with label firefox. Show all posts
Showing posts with label firefox. Show all posts

Thursday, November 2, 2017

Forensics Quickie: Methodology for Identifying "Clear Recent History" Settings for an Old Version of Firefox

FORENSICS QUICKIES! These posts will consist of small tidbits of useful information that can be explained very succinctly.

I saw this tweet from @phillmoore recently.

Archived tweet here.

Further down in this thread, we also see that the target browser is a ~5 year old version of Firefox. I've written in the past about verifying program behavior using source code. In fact, the previous post uses Firefox as an example. Given the information that we have -- and even though this is somewhat of a fringe case -- let's run through how to get the answer. Remember: it's one thing to know that an artifact exists; it's another to know how to find, understand, and make use of it

So, from start to finish, let's delve into how you'd go about answering the question Phill posted.

Scenario
You want to determine where an older version of Firefox stores the settings for the "Clear Recent History" dialog.

The Solution
First, we need to identify a version of Firefox that is about 5 years old. Mozilla hosts a page that lists all past releases of Firefox and links each to their respective release notes -- including the dates of release. Clicking around a bit, I found that Firefox version 17.0 was about 5 years old (Nov 2012).

With that out of the way, I needed to locate the source code and compiled executables archive for past releases. Googling brought me to Mozilla's "Downloading Source Archives" page. There are tons of ways to download the source, but I wanted a quick and easy way, so I navigated to: https://archive.mozilla.org/pub/.

Following down the index, I found what I needed at:
  • https://archive.mozilla.org/pub/firefox/releases/17.0/source/
    • firefox-17.0.source.tar.bz2
and
  • https://archive.mozilla.org/pub/firefox/releases/17.0/win32/en-US/
    • Firefox Setup 17.0.exe

Now that I have the v17 source code and installer, I can start testing. I'm targeting the "Clear Recent History" dialog, so I install Firefox v17 on a clean VM, and use the "Firefox" tab within the browser to navigate to History > Clear Recent History...

Default "Clear Recent History" Dialog for Firefox v17.

I'd like to find where the logic for this dialog is located within the source code. To make that easier, I need to grab a fairly unique string from this dialog -- one that won't come back with a lot of hits across many different source files. "Time range to clear" seems unique enough, so let's go with that.

There are many different ways to go about searching the extracted source code, but since I'm on Windows and want to run a quick and dirty search across many files, I'll just use AstroGrep.

Using AstroGrep to recursively search Firefox source code for a unique string.

I provide my search path that contains the source code, define my search string, and perform the search recursively across all file types. The results show two files that contain my unique string. The sanitize.dtd file sounds interesting, so let's open that one up.

Contents of "sanitize.dtd" showing our unique string along with some other context.

The first hit for our unique string can be seen at line 12. By looking around this area, we can gather some clues in order to pivot to other files that have more meat to them. Particularly interesting are lines 5 and 6. I'm looking for the settings within the dialog titled "Clear Recent History," so let's run an AstroGrep search for "sanitizeDialog2."

Using AstroGrep to recursively search Firefox source code for "sanitizeDialog2."

Again, the search string is unique enough to cut down on the amount of results we need to review. The file named sanitizeDialog.js seems to be what we're looking for here.

Contents of "sanitizeDialog.js" showing our searched string.

Line 64 shows our searched string. It also looks like we have something more than just localization and property data in this file. Browsing through this file would probably be a good idea.

Contents of "sanitizeDialog.js" showing the sanitize() function.

Line 100 contains the beginning of the sanitize() function and references the updatePrefs() function. A few lines down, we see what that's all about.

Contents of "sanitizeDialog.js" showing the updatePrefs() function.

The updatePrefs() function provides even more clues. It gets the timespan that the user sets within the dialog and hints at what we saw on line 105: the prefDomain of "privacy.cpd." We see "downloads" and "history" tacked on to that string, which leads me to believe that we're getting really close.

An AstroGrep search for "privacy.cpd" finally leads us to our destination.

Using AstroGrep to recursively search Firefox source code for "privacy.cpd."

The very first result, firefox.js, shows a few lines that not only contain "privacy.cpd," but also some familiar labels. These labels more or less line up with the checkboxes we saw in our "Clear Recent History" dialog at the beginning of this post. It gets even more interesting as we review the contents of firefox.js.

Contents of "firefox.js" showing the default "clear history" values and time span values.

As we can see, the source code is set up to check some of the items in the dialog by default. There are some other interesting lines here, but we'll get to that in a minute. What really caught my eye was line 495. Having done some research on Firefox proxy settings in the past, I knew that those settings were stored in the prefs.js file located in Firefox profiles. Couple that with the location of the firefox.js file within the source code folder structure (C:\4n6k\firefox-17.0.source\mozilla-release\browser\app\profile), and there's a really good chance all of what we need is in our profile's prefs.js. (which is typically located at C:\Users\4n6k\AppData\Roaming\Mozilla\Firefox\Profiles\<RandomChars>.default).

We can test this theory by performing a set of actions (as a normal user would) and documenting the results.

Test #01: Perform a default "Clear Recent History"

The first test was to open Firefox v17 on a VM that did not have Firefox already installed and clear the history using the default values within the dialog.

Here's what a default "Clear Recent History" action looks like on Firefox v17:

A default "Clear Recent History" action on Firefox v17. No settings were changed.

By default, the time range is set to "Last Hour," and the "Browsing & Download History," "Cookies," "Cache," and "Active Logins" checkboxes are selected. The "Offline Website Data" and "Site Preferences" checkboxes are not selected.
Note: prefs.js - Complete Re-write Upon Exit

Upon hitting the "Clear Now" button, Firefox (at least in the case of v17) must be closed in order for us to accurately test changes to the prefs.js file. The prefs.js file gets written to upon closing the application. And, per the warning at the top of the file, the entirety of the file will get re-written upon application exit. In other words, the born time and last written time get updated upon Firefox's exit; it is a brand new file. Every prefs.js file in these tests was acquired after application closure.


A quick comparison of the two prefs.js files using Beyond Compare shows very few changes. None are relevant to what we're testing.

Using Beyond Compare to compare two prefs.js files. No relevant differences are seen here.

Test #02: Perform a default "Clear Recent History" after form data input

In the previous test, the "Form & Search History" checkbox is grayed out. I wanted to test the default history clear while that checkbox was enabled, so I browsed to Twitter and logged in. That was enough to save some form data for the username field.

A default "Clear Recent History" action on Firefox v17 with form data present.

Note that I did not check the "Form & Search History" checkbox. It was checked by default after some form data was introduced. This variance did not show anything new; there was no relevant change in the prefs.js file.

Using Beyond Compare to compare two prefs.js files. No relevant differences are seen here.

Test #03: Perform a "Clear Recent History" with all boxes selected + 2hr time span

For this test, a few websites were browsed, form data was input, all checkboxes were selected, and the "time range to clear" was changed from the default "1 hour" to 2 hours.

A modified "Clear Recent History" action on Firefox v17. All boxes are selected and time span is changed..

With these changes, we finally see some relevant items get written to the prefs.js file.

Using Beyond Compare to compare two prefs.js files.Some relevant differences are detected.

We see the following get written:
  • user_pref("privacy.cpd.offlineApps", true);
  • user_pref("privacy.cpd.siteSettings", true);
  • user_pref("privacy.sanitize.timeSpan", 2);
Also note the "2" value after the timeSpan line. Remember: the value at that position is defined in the source code:
  • 0 - Clear everything
  • 1 - Last Hour
  • 2 - Last 2 Hours
  • 3 - Last 4 Hours
  • 4 - Today
Test #04: Perform a "Clear Recent History" with first box selected + 4hr time span

For this test, a few more websites were browsed, form data was input, all checkboxes were deselected except for the first one (unchecking everything will gray out the "Clear Now button"), and the "time range to clear" was changed from the default "1 hour" to 4 hours.

A modified "Clear Recent History" action on Firefox v17. Only one box is selected and time span is changed..

With these changes come more changes in the prefs.js file.

Using Beyond Compare to compare two prefs.js files.More relevant differences are detected.
 
The key is to understand that if something deviates from the default "Clear Recent History" settings, there will be an entry for it in the prefs.js file. Note that this recent change caused entries to show up for cache, cookies, formdata, and sessions. This is because they have been switched to the opposite of what the default settings are set to. As an example, cache is checked in the default settings. When it is unchecked, it deviates from the default, and therefore, Firefox needs to make note of it in prefs.js. Likewise, "Offline Website Data" (aka offlineApps) is NOT checked in the default settings. When it is checked, it deviates from the default, and therefore, Firefox needs to make note of it in the prefs.js.

One final anecdote is that the checkboxes and time span within the "Clear Recent History" dialog do not get updated/saved until you click the "Clear Now" button (at least in the case of v17). That is, if you check/uncheck items or change the time span value and hit cancel, your settings will not be persistent -- neither in the current session nor the prefs.js file.

With that, we now have a better idea of how one of the many facets of Firefox operates. There is much, much more there (especially in prefs.js), but testing specific functionality in depth goes a long way in understanding how things work.

If there's one takeaway from all of this, it's to make sure you're leveraging what is available. If you have source code to look through, identifying the behavior of a given application can be a walk in the park. 

...unless it's written in Perl.




-4n6k


References
1. Reference to Original Tweet 01
2. Forensics Quickie: Verifying Program Behavior Using Source Code (by 4n6k)
3. Reference to Original Tweet 02
4. Mozilla Firefox Release Notes Archive
5. Downloading Source Archives (Mozilla)
6. Firefox Source Code Archive
7. AstroGrep Homepage


Saturday, March 29, 2014

Forensics Quickie: Verifying Program Behavior Using Source Code

FORENSICS QUICKIES! These posts will consist of small tidbits of useful information that can be explained very succinctly.

Recently, I stumbled upon a question related to the behavior of a given program. That program was Mozilla Firefox and the behavior in question was how profile directory names were generated. Through this post, I will cover how to approach this question and how to solve it with available resources (source code).

The Question
How are Firefox profile directory names generated?

The Answer (and the road to get there)
To answer this question, we first have to understand which artifacts we are examining. In this case, we are dealing with Firefox profiles. Those are located in a user's AppData folder. By navigating AppData, we eventually find C:\Users\someUser\AppData\Roaming\Mozilla\Firefox\Profiles.

The Firefox 'Profiles' folder showing the directory for the profile named "default."

We see a folder for the only Firefox profile used on the system. Reasonably, this account is named "default" by default. But what about that seemingly random prefix?

Let's see if we can glean anything from trying to create a profile in Firefox. First, let's open up the Profile Manager by typing "firefox.exe -p" in the 'Run...' dialog (Windows key + R).

We can confirm that there is only one profile and it is named "default."

When we try to create a profile, we see the following window:


Great. We can actually see where it is going to be saved. And no matter what we enter in the text input field, the prefix stays the same. This tells us that the folder for this new profile isn't generated based on the profile name we enter. But there are other possibilities, such as the folder name being based on the current time.

There are many other tests we could run, but we actually don't need to -- the source code for Firefox is freely available online. Once we download and extract the source code, we can try to find the function that handles the generation of the profile's folder name.

Uncompressed, the Firefox source code is about 585MB. That's a lot of code to review. A better way to sift through all of this data is to either index it all and search it or to just recursively grep the root folder. I decided on the latter.

To find out where to look first, we can try to find a constant, unique phrase around the text in question. In the above image, the string "Your user settings, preferences and other user-related data will be stored in:" is right before the path name with which we are concerned. So let's grep for that and see if we can find anything.

There are many ways to grep data, but this was a quick and dirty job where I wasn't doing any parsing or modifying, so I used AstroGrep. I went ahead and searched for the a watered down version of the aforementioned unique phrase: "will be stored in." The results showed that the file named CreateProfileWizard.dtd contained this unique phrase (there were many files that were responsive, but based on the phrase's context and the filename for the file in which the phrase was found, we can determine relevancy).

A snippet of the responsive "CreateProfileWizard.dtd"  file containing our unique phrase.

Now, it's just a matter of tracing this phrase back to its source. So we grab another unique phrase that is relevant to our discovery, such as "profileDirectoryExplanation," and see if we can find any more relevant files. Grepping for it comes back with more results -- one of which is createProfileWizard.xul. I didn't see much in this file at first glance (though there is quite bit of good info such as "<wizardpage id="createProfile" onpageshow="initSecondWizardPage();">" -- which will be seen soon), so I decided to see what else was in same directory as this file. There, I found createProfileWizard.js.

A snippet of the "createProfileWizard.js" file showing the functions used to generate the profile directory names.

Skimming the code, we can see that a salt table and Math.random() are used to determine the 8 character prefix. At line 68, we see the concatination of kSaltString ('0n38y60t' in the animated gif), a period ('.'), and aName (our text input field variable -- in our example, "abcdefg" or "4n6k").

In the end, the point is that having source code available makes research more streamlined. By looking at the Firefox source, we were able to determine that the profile directory names aren't based on a telling artifact.

Using what is available to you is invaluable. By having a program's source code [and approaching an issue with an analytic mindset], verifying program behavior is made so much easier.

I'll end with this: open source development is GOOD -- especially for forensics. Whether it's a tool meant to output forensic artifacts or just another Firefox, we are able to more confidently prove why we are seeing what we're seeing.

-4n6k

* Special thanks to Tom Yarrish (@CdtDelta) for spawning this post.