mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
d8032ac824
* docs: rewrite README, RFCs, and CONTRIBUTING * docs: fix Linux storage labels in RFC-006 (Opera/Vivaldi swapped)
130 lines
5.1 KiB
Markdown
130 lines
5.1 KiB
Markdown
# RFC-004: Firefox Data Storage
|
|
|
|
**Author**: moonD4rk
|
|
**Status**: Living Document
|
|
**Created**: 2026-04-05
|
|
|
|
## 1. Profile Structure
|
|
|
|
Firefox stores per-user data in **profile directories** beneath a platform-specific root (e.g. `~/Library/Application Support/Firefox/Profiles/` on macOS). Each profile directory has a random-prefix name like `97nszz88.default-release`.
|
|
|
|
Profile discovery enumerates subdirectories of the root and accepts any directory that contains at least one known data file. Unlike Chromium (which looks for a `Preferences` sentinel), Firefox validation simply checks for the presence of any source file from the table below.
|
|
|
|
## 2. Data File Locations
|
|
|
|
All paths are relative to the profile directory.
|
|
|
|
| Category | File | Format |
|
|
|----------|------|--------|
|
|
| Password | `logins.json` | JSON |
|
|
| Cookie | `cookies.sqlite` | SQLite |
|
|
| History | `places.sqlite` | SQLite |
|
|
| Download | `places.sqlite` | SQLite |
|
|
| Bookmark | `places.sqlite` | SQLite |
|
|
| Extension | `extensions.json` | JSON |
|
|
| LocalStorage | `webappsstore.sqlite` | SQLite |
|
|
|
|
History, Download, and Bookmark all share `places.sqlite` but query different tables within it. Firefox does not support CreditCard or SessionStorage extraction.
|
|
|
|
The master encryption key is stored separately in `key4.db` (see [RFC-005](005-firefox-encryption.md)).
|
|
|
|
## 3. Data Storage Formats
|
|
|
|
### 3.1 Passwords (logins.json)
|
|
|
|
Passwords are stored as a JSON file with a top-level `logins` array. Each entry contains:
|
|
|
|
- `formSubmitURL` / `hostname` — the login URL (formSubmitURL preferred, hostname as fallback)
|
|
- `encryptedUsername` — base64-encoded, ASN1 PBE-encrypted username
|
|
- `encryptedPassword` — base64-encoded, ASN1 PBE-encrypted password
|
|
- `timeCreated` — creation timestamp in **milliseconds**
|
|
|
|
Decryption pipeline: base64 decode the field, parse as ASN1 PBE structure, decrypt with the master key.
|
|
|
|
### 3.2 Cookies (cookies.sqlite)
|
|
|
|
Cookies are **not encrypted** — values are stored in plaintext.
|
|
|
|
```sql
|
|
SELECT name, value, host, path, creationTime, expiry, isSecure, isHttpOnly
|
|
FROM moz_cookies
|
|
```
|
|
|
|
The database must be opened with `journal_mode=off` to avoid locking conflicts with a running Firefox instance.
|
|
|
|
### 3.3 History (places.sqlite)
|
|
|
|
```sql
|
|
SELECT url, COALESCE(last_visit_date, 0), COALESCE(title, ''), visit_count
|
|
FROM moz_places
|
|
```
|
|
|
|
The `last_visit_date` column uses **microseconds** since epoch.
|
|
|
|
### 3.4 Downloads (places.sqlite)
|
|
|
|
Downloads use the `moz_annos` annotation table joined with `moz_places`:
|
|
|
|
```sql
|
|
SELECT place_id, GROUP_CONCAT(content), url, dateAdded
|
|
FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id = moz_places.id)
|
|
t GROUP BY place_id
|
|
```
|
|
|
|
Download metadata is stored as a concatenated string: `target_path,{json}` where the JSON portion contains `fileSize` and `endTime`.
|
|
|
|
### 3.5 Bookmarks (places.sqlite)
|
|
|
|
```sql
|
|
SELECT id, url, type, dateAdded, COALESCE(title, '')
|
|
FROM (SELECT * FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk = moz_places.id)
|
|
```
|
|
|
|
The `type` field distinguishes URL bookmarks (1) from folders.
|
|
|
|
### 3.6 Extensions (extensions.json)
|
|
|
|
Extensions are read from the `addons` array. Only entries with `location == "app-profile"` are included (user-installed extensions). Fields extracted: `defaultLocale.name`, `id`, `version`, `defaultLocale.description`, `defaultLocale.homepageURL`, `active`.
|
|
|
|
### 3.7 LocalStorage (webappsstore.sqlite)
|
|
|
|
```sql
|
|
SELECT originKey, key, value FROM webappsstore2
|
|
```
|
|
|
|
The `originKey` column uses a **reversed-host format**: `moc.buhtig.:https:443` represents `https://github.com:443`. The host portion is byte-reversed and dot-suffixed; the remaining fields are scheme and port.
|
|
|
|
## 4. Time Formats
|
|
|
|
Firefox uses inconsistent timestamp units across data types. All are Unix epoch-based.
|
|
|
|
| Data Type | Unit | Conversion |
|
|
|-----------|------|------------|
|
|
| Cookies (`creationTime`) | Microseconds | / 1,000,000 |
|
|
| Cookies (`expiry`) | Seconds | direct |
|
|
| History (`last_visit_date`) | Microseconds | / 1,000,000 |
|
|
| Downloads (`dateAdded`) | Microseconds | / 1,000,000 |
|
|
| Bookmarks (`dateAdded`) | Microseconds | / 1,000,000 |
|
|
| Passwords (`timeCreated`) | Milliseconds | / 1,000 |
|
|
|
|
## 5. Key Differences from Chromium
|
|
|
|
| Aspect | Chromium | Firefox |
|
|
|--------|----------|---------|
|
|
| Profile naming | Named directories (`Default`, `Profile 1`) | Random-prefix (`97nszz88.default-release`) |
|
|
| Profile detection | `Preferences` sentinel file | Any known source file present |
|
|
| Password storage | SQLite (`Login Data`) | JSON (`logins.json`) |
|
|
| Cookie encryption | Encrypted with master key | **Plaintext** |
|
|
| Shared database | Separate files per category | `places.sqlite` shared by History/Download/Bookmark |
|
|
| LocalStorage | LevelDB | SQLite (`webappsstore.sqlite`) |
|
|
| CreditCard support | Yes | No |
|
|
| SessionStorage support | Yes | No |
|
|
| Encryption scope | Passwords, cookies, credit cards | **Passwords only** (see [RFC-005](005-firefox-encryption.md)) |
|
|
|
|
## Related RFCs
|
|
|
|
| RFC | Topic |
|
|
|-----|-------|
|
|
| [RFC-005](005-firefox-encryption.md) | Firefox NSS encryption and master key derivation |
|
|
| [RFC-008](008-file-acquisition-and-platform-quirks.md) | File acquisition and platform quirks |
|