0x00 Preface

---

In the previous article 'Penetration Techniques - Exporting Saved Passwords from Firefox Browser', common methods for exporting Firefox browser passwords were introduced. Among them, firefox_decrypt.py uses NSS (Network Security Services) for decryption, supporting Master Password decryption for key3.db and key4.db. This article will explain the principles involved, develop test code to achieve Master Password verification, and share details of script development.

0x01 Introduction

---

This article will cover the following topics:

  • Introduction to Network Security Services
  • Exporting Firefox browser passwords via Python calls to Network Security Services
  • Open-source Python scripts
  • Implementation of brute-force scripts

0x02 Introduction to Network Security Services

---

Network Security Services (NSS) is a set of libraries designed to support cross-platform development of secure client and server applications.

Reference documentation:

https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS

The Firefox browser uses NSS as the foundational library for encryption algorithms and secure network protocols, employing the PKCS#11 standard for credential encryption and decryption.

Reference documentation:

https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11

0x03 Exporting passwords from the Firefox browser by calling Network Security Services via Python

---

Reference code:

https://github.com/unode/firefox_decrypt

https://github.com/Kerisa/BrowserPasswordDump/blob/master/MozillaPwd.py

The decryption process on Windows systems is as follows:

  1. Load the nss3.dll required by Network Security Services
  2. Call NSS_Init() for initialization
  3. Call PK11_GetInternalKeySlot() to obtain the internal slot (used for verifying the Master Password)
  4. Call PK11_CheckUserPassword() to verify the Master Password
  5. Read logins.json to obtain encrypted data
  6. Call PK11SDR_Decrypt() for decryption

Specific issues to note are as follows:

1. Python and Firefox versions must be consistent

On 64-bit systems, both must be either 32-bit or 64-bit

2. Add Firefox installation path to environment variables for easy invocation

The Firefox installation directory contains the nss3.dll we need to call, so you can add the Firefox installation path to the PATH environment variable. The corresponding Python code is:

import os
firefoxPath = "C:\Program Files\Mozilla Firefox"
os.environ["PATH"] = ';'.join([firefoxPath, os.environ["PATH"]])

Note:

On 64-bit operating systems, the default installation directory for 64-bit Firefox is C:\Program Files\Mozilla Firefox, and for 32-bit Firefox it is C:\Program Files (x86)\Mozilla Firefox

The Python code to call nss3.dll is:

import ctypes
NssDll = ctypes.CDLL("nss3.dll")

3. NSS initialization requires three files

The specific location is: %APPDATA%\Mozilla\Firefox\Profiles\xxxxxxxx.default\

The following three files are required:

  • cert9.db
  • key4.db
  • logins.json

The above three files can be saved in the same folder, for example, c:\test\data

The code for NSS initialization is as follows:

profilePath = "C:\\test\\data"
NssDll.NSS_Init(profilePath)

4. Read logins.json to obtain encrypted data

The encryptedUsername and encryptedPassword entries are encrypted data and need to be decrypted using NSS

Before decryption, base64 decoding is required first, then call PK11SDR_Decrypt() to decrypt and obtain the plaintext

The timeCreated, timeLastUsed, and timePasswordChanged entries are in Epoch Time format (total seconds from 00:00:00 on January 1, 1970, Coordinated Universal Time to the present, excluding leap seconds), which can be converted to actual time via the following website:

https://esqsoft.com/javascript_examples/date-to-epoch.htm

The Python code for converting the time format is as follows:

from datetime import datetime
def timestamp_to_strtime(timestamp):
return datetime.fromtimestamp(timestamp / 1000.0).strftime('%Y-%m-%d %H:%M:%S')
print timestamp_to_strtime(1580901797579)

Note:

Different versions of Firefox save records in different file names, with specific differences as follows:

  • Version greater than or equal to 32.0, the file for saving records is logins.json
  • Version greater than or equal to 3.5, less than 32.0, the file for saving records is signons.sqlite

For more detailed file descriptions, refer to:

http://kb.mozillazine.org/Profile_folder_-_Firefox

0x04 Open-source Python Script

---

Reference code:

https://github.com/unode/firefox_decrypt

https://github.com/Kerisa/BrowserPasswordDump/blob/master/MozillaPwd.py

My test code has been uploaded to GitHub, the address is as follows:

An open-source project

Test environment:

  • 64-bit Windows operating system with 64-bit Firefox browser installed
  • The default installation path for Firefox is "C:\Program Files\Mozilla Firefox"
  • The profile path is "C:\\Users\\a\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\2yi8qmhz.default-beta", including the following three files:
  • cert9.db
  • key4.db
  • logins.json

The code supports two functions:

1. Verify Master Password

Corresponding sub-function checkMasterPassword(MasterPassword)

If the MasterPassword is correct, display the correct MasterPassword and return TRUE

If the MasterPassword is incorrect, return FALSE

This can be used to implement brute-force attacks on the Master Password

2. Export saved passwords from Firefox browser

Corresponding sub-function ExportData(MasterPassword)

If no Master Password is set, set the MasterPassword parameter to ""

If a Master Password is set, the correct Master Password must be entered to decrypt and obtain the actual data

Specifically, the following information can be exported:

  • url
  • username
  • password
  • timeCreated
  • timePasswordChanged
  • timeLastUsed

0x05 Summary

---

This article introduces the method of exporting Firefox browser passwords by calling Network Security Services via Python, sharing script development details.