Where are they stored? What is their format? Is it possible to print the in user's session? Can your administrator have access to them easily?
Firefox passwords are stored encrypted in a SQLite database in the user's directory. But, by default, the encryption key is hardcoded in plain text in Firefox source code, and Firefox offers the user a tool to print these passwords.
French version available on the site.
Tools
plugin Firefox SQLite manager https://addons.mozilla.org/fr/firefox/addon/5817
sources of Firefox ftp://ftp.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/latest/source/
User: print the passwords
Printing saved passwords from user's session is trivial [1].In Firefox:
Edit -> Preferences -> saved passwords -> show passwords
Administrator: print user's password
Passwords are stored in two files in directory /home/xxx/.mozilla/firefox/xxx.default/ in Ubuntu, in directory Application Data of the user in Windows,signons.sqliteAfter downloading them, put them in your own firefox directory.
keys3.db
In order to complete that, administrator rights are needed on user's computer.
Analysis of Firefox passwords management
We'll now see that visited websites passwords are stored in a sqlite database. They are base64 encoded and encrypted with 3DES algorithm, using a key defined with Firefox main password. When this main password is not defined, a key, hard coded in the source, is used.
copy signons.sqlite and keys3.db from directory /home/xxx/.mozilla/firefox/xxx.default/ (in Ubuntu, in directory Application Data in Windows),
signons.sqliteStart Firefox plugin sqlite manager
keys3.db
Database -> Connect Database -> signons.sqlite
How usernames and passwords are encrypted in Firefox?
Edit following file written in javascript
/toolkit/components/passwordmgr/src/storage-mozStorage.jsThe two encryption javascript functions are:
_encrypt(PlainText)The function decryptString of service _decodeRing in in library nsddr.cpp [4]:
(...)
PlainOctet = _utfConverter.ConvertFromUnicode(PlainText)
CipherText = _decoderRing.encrytpString(PlainOctet)
_decrypt(CipherText)
(...)
PlainOctet = _decoderRing.decryptString(CipherText)
PlainText = _udtConverter.ConvertToUnicode(PlainOctet)
/security/manager/ssl/src/nsSDR.cppThe function decryptString() calls two other functions:
decode()decode() calls function PL_Base64Decode() which decodes from base 64 to plain text (cf Wikipedia [5] about base 64. Here is an online encoder/decoder: [6] )
decrypt()
decrypt() calls three functions:
PK11_GetInternalKeySlot()These three functions use:
PK11_Authenticate()
PK11SDR_Decrypt()
- the cryptographic API PKCS #11 defined by RSA [7] and [8].
- the cryptographic library Mozilla NSS [9]
PK11SDR_Decrypt() is defined in:
/security/nss/lib/pk11wrap/pk11sdr.cTo better understand how Firefox encrypts passwords of this databse, have a look first to the following function:
PK11SDR_encrypt()It is in file:
/security/nss/lib/pk11wrap/pk11sdr.cHere is an excerpt from its source:
/* 1. Locate the requested keyid, or the default key (which has a keyid)You can see that:
* 2. Create an encryption context
* 3. Encrypt
* 4. Encode the results (using ASN.1)
*/
slot = PK11_GetInternalKeySlot();
/* Use triple-DES */
type = CKM_DES3_CBC;
/*
* Login to the internal token before we look for the key, otherwise we
* won't find it.
*/
rv = PK11_Authenticate(slot, PR_TRUE, cx);
/* Find the key to use */
pKeyID = keyid;
if (pKeyID->len == 0) {
pKeyID = &keyIDItem; /* Use default value */
ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params);
PK11_CipherOp(ctx, sdrResult.data.data, (int*)&sdrResult.data.len, sdrResult.data.len,
paddedData.data, paddedData.len);
PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg);
SEC_ASN1EncodeItem(0, result, &sdrResult, template);
- encryption algorithm is 3DES CBC,
- encryption key is stored in an encryption "context" and is identified by a token,
- if the main password in Firefox is not defined, passwords in the sqlite databas are still encrypted using a default key.
What is the default key?
A bit earlier in the source code, keyIDItem is defined:
static unsigned char keyID[] = {Then, recap:
0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
static SECItem keyIDItem = {
0,
keyID,
sizeof keyID
};
Mozilla Firefox stores passwords entered during web surfing in the signons.sqlite database. They are first encrypted with 3DES, with a key derived from the master key of Firefox. If this one is not defined, a default key is used with string 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01. It is then encoded in base64 and stored in database.
Administrator: configure firefox to save the passwords without notifying the user
This paragrpah is base on the article of Raymond [2]
It is easy to modify Firefox code, so that it does not notify users about saving passwords:
When the user completes the form with the couple Id-password, Firefow calls java functions:
- _onFormSubmit() in nsLoginManagerPrompter.js
- promptToSavePassword() in nsLoginManagerPrompter.js
- _showSaveLoginNotification() in nsLoginManagerPrompter.js
- addLogin() in nsLoginManager.js
In Ubuntu, go to directory /usr/lib/xulrunner-1.9.1.7/components (in Windows: Program Files\Mozilla\Firefox\Components). Edit
nsLoginManagerPrompter.js
remark: if you download Firefox sources, these functions are in toolkit/components/passwordmgr/src
Here is function _showSaveLoginNotification():
replace with:
/*
* _showSaveLoginNotification
*
* Displays a notification bar (rather than a popup), to allow the user to
* save the specified login. This allows the user to see the results of
* their login, and only save a login which they know worked.
*
*/
_showSaveLoginNotification : function (aNotifyBox, aLogin) {
// Ugh. We can't use the strings from the popup window, because they
// have the access key marked in the string (eg "Mo&zilla"), along
// with some weird rules for handling access keys that do not occur
// in the string, for L10N. See commonDialog.js's setLabelForNode().
var neverButtonText =
this._getLocalizedString("notifyBarNeverForSiteButtonText");
var neverButtonAccessKey =
this._getLocalizedString("notifyBarNeverForSiteButtonAccessKey");
var rememberButtonText =
this._getLocalizedString("notifyBarRememberButtonText");
var rememberButtonAccessKey =
this._getLocalizedString("notifyBarRememberButtonAccessKey");
var notNowButtonText =
this._getLocalizedString("notifyBarNotNowButtonText");
var notNowButtonAccessKey =
this._getLocalizedString("notifyBarNotNowButtonAccessKey");
var brandShortName =
this._brandBundle.GetStringFromName("brandShortName");
var displayHost = this._getShortDisplayHost(aLogin.hostname);
var notificationText;
if (aLogin.username) {
var displayUser = this._sanitizeUsername(aLogin.username);
notificationText = this._getLocalizedString(
"saveLoginText",
[brandShortName, displayUser, displayHost]);
} else {
notificationText = this._getLocalizedString(
"saveLoginTextNoUsername",
[brandShortName, displayHost]);
}
// The callbacks in |buttons| have a closure to access the variables
// in scope here; set one to |this._pwmgr| so we can get back to pwmgr
// without a getService() call.
var pwmgr = this._pwmgr;
var buttons = [
// "Remember" button
{
label: rememberButtonText,
accessKey: rememberButtonAccessKey,
popup: null,
callback: function(aNotificationBar, aButton) {
pwmgr.addLogin(aLogin);
}
},
// "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 */ }
}
];
this._showLoginNotification(aNotifyBox, "password-save",
notificationText, buttons);
},
_showSaveLoginNotification : function (aNotifyBox, aLogin) {
var pwmgr = this._pwmgr;
pwmgr.addLogin(aLogin);
},
references
1) Où sont stockés les mots de passe Firefox? - http://www.memoclic.com/593-firefox/7155-firefox-securite-mots-de-passe-confidentiel.html
2) Raymond - Hacking Firefox to always auto save password without showing notification bar http://www.raymond.cc/blog/archives/2009/11/05/hacking-firefox-to-always-auto-save-password-without-showing-notification-bar/
3) Isamil Guneydas - How FF store your passwords? Is it secure? http://realinfosec.com/?p=111
4) mikeblas - DecryptString() - http://www.hardforum.com/archive/index.php/t-1050986.html
5) Wikipedia -Base64 - http://en.wikipedia.org/wiki/Base64
6) antonin Foller - Motobit - http://www.motobit.com/util/base64-decoder-encoder.asp
7) public key cryptographic standards - http://fr.wikipedia.org/wiki/Public_Key_Cryptographic_Standards
8) master password / personnal data encryption - http://old.nabble.com/Master-Password---personal-data-encryption-td24991602.html
9) bibliothèque cryptographique de Mozilla NSS - http://www.mozilla.org/projects/security/pki/nss/nss-guidelines.html
10) FZ blog - obtenir les credentials de Mozilla - http://fz-corp.net/?p=199
deepen the subject:
1) Brandon Cannaday - How Google chrome stores passwords - http://www.switchonthecode.com/tutorials/how-google-chrome-stores-passwords
Aucun commentaire:
Enregistrer un commentaire