Browser, E-Mail und Cloud-Synchronisierung · Lektion 2 von 6
Firefox: places.sqlite und Sitzungsdaten
10 Min. Lesezeit
Firefox speichert seinen Verlauf in einem eigenen SQLite-Schema, eigenen JSON-Dateien und einem komprimierten Sitzungsformat, wobei die Zeitstempel von einer anderen Epoche aus gezählt werden als bei Chromium. Diese Lektion zeigt, wo sich ein Firefox-Profil befindet, welche Tabellen die Fragen „Was wurde besucht, eingegeben und heruntergeladen, und wann?“ beantworten und wie Sie die Sitzungsdateien öffnen, die geöffnete und kürzlich geschlossene Tabs dokumentieren. Lektion 4.3 behandelt den Cache und das private Surfen.
Das Profil finden
Unter Windows hat jedes Profil zwei Ordner mit demselben Namen: %APPDATA%\Mozilla\Firefox\Profiles\<random>.<name> (Roaming: die Datenbanken und JSON-Dateien dieser Lektion) und %LOCALAPPDATA%\Mozilla\Firefox\Profiles\<random>.<name> (lokal: der Cache). Das Präfix besteht aus acht zufälligen Zeichen; aktuelle Versionen nennen das für jede Installation erstellte Profil default-release, beispielsweise k3x9p2qa.default-release.
Zwei Dateien in %APPDATA%\Mozilla\Firefox\ zeigen Ihnen, welches Profil verwendet wurde. profiles.ini führt jedes Profil in einem Abschnitt [ProfileN] auf (Name, IsRelative, Path) und enthält seit Firefox 67 einen Abschnitt [Install<hash>], dessen Zeile Default= das von einer Installation verwendete Profil angibt. installs.ini wiederholt diese Zuordnung mit einem Abschnitt pro Installations-Hash. Ein Profil namens default mit Default=1 ist häufig ein nahezu leeres Altprofil. Folgen Sie daher dem Eintrag [Install…], untersuchen Sie aber dennoch alle vorhandenen Profilordner.
Unter Linux befinden sich die Profile unter ~/.mozilla/firefox/ und der Cache unter ~/.cache/mozilla/firefox/. Das Snap-Paket verwendet ~/snap/firefox/common/.mozilla/firefox/ und das Flatpak-Paket ~/.var/app/org.mozilla.firefox/.mozilla/firefox/. Ab Firefox 147 folgen neue Installationen dem XDG-Verzeichnisschema unter ~/.config/mozilla/firefox/. Suchen Sie nach jeder profiles.ini, statt sich auf einen einzigen Pfad zu verlassen.
Die meisten Firefox-Datenbanken arbeiten im Write-Ahead-Logging-Modus. Sichern Sie places.sqlite zusammen mit places.sqlite-wal und places.sqlite-shm (ebenso bei Cookies, Formularverlauf und Favicons): Aktuelle Besuche können ausschließlich im WAL vorhanden sein. Berechnen Sie die Hashwerte des Dateisatzes und arbeiten Sie anschließend mit Kopien, da das Öffnen einer Datenbank mit SQLite einen Checkpoint auslösen kann, der das WAL in die Hauptdatei überträgt und beide Dateien verändert.
places.sqlite
moz_places und moz_historyvisits
moz_places enthält eine Zeile pro URL: url, title, rev_host (der Host mit zeichenweise umgekehrter Reihenfolge und einem abschließenden Punkt, sodass aus transfer.example.com der Wert moc.elpmaxe.refsnart. wird), visit_count, typed (1, wenn die URL jemals eingegeben wurde), frecency (ein Rangwert für Vorschläge in der Adressleiste, keine Zeitangabe), last_visit_date und guid. moz_historyvisits enthält eine Zeile pro Besuch: place_id (zur Verknüpfung mit moz_places.id), visit_date, visit_type und from_visit (die id des Besuchs, der hierher führte, oder 0, wenn es keinen gibt). Beide Datumsangaben sind PRTime: Mikrosekunden seit 1970-01-01 UTC (Lektion 3.1).
| visit_type | Name | Bedeutung |
|---|---|---|
| 1 | LINK | Einem Link gefolgt |
| 2 | TYPED | In der Adressleiste eingegeben oder ausgewählt |
| 3 | BOOKMARK | Über ein Lesezeichen geöffnet |
| 4 | EMBED | Eingebetteter Inhalt; aktuelle Versionen halten diese Einträge im Arbeitsspeicher, sodass sie selten auf dem Datenträger vorliegen |
| 5 | REDIRECT_PERMANENT | Über eine permanente Weiterleitung erreicht, beispielsweise HTTP 301 |
| 6 | REDIRECT_TEMPORARY | Über eine temporäre Weiterleitung erreicht, beispielsweise HTTP 302 |
| 7 | DOWNLOAD | URL als Download abgerufen |
| 8 | FRAMED_LINK | Einem Link innerhalb eines Frames gefolgt |
| 9 | RELOAD | Seite neu geladen |
Durch das rückwärtige Verfolgen von from_visit lässt sich eine Navigationskette rekonstruieren. Firefox entfernt alte Verlaufseinträge automatisch. Ein fehlender Besuch ist daher kein Beweis dafür, dass kein Besuch stattgefunden hat.
Lesezeichen, eingegebener Text und Origins
moz_bookmarks speichert Lesezeichen (type 1), Ordner (2) und Trennlinien (3), mit fk als Verweis auf moz_places.id, parent, title sowie dateAdded und lastModified in PRTime. moz_inputhistory erfasst, was der Benutzer in die Adressleiste eingegeben und welches Ergebnis er anschließend ausgewählt hat: input (der eingegebene Text), place_id (die ausgewählte Seite) und use_count, ein mit der Zeit abnehmender Bewertungswert. Die Tabelle enthält keinen Zeitstempel; bestimmen Sie den Zeitpunkt daher anhand der zugehörigen Besuche. moz_origins enthält eine Zeile pro Kombination aus Schema und Host (prefix, host, frecency), auf die moz_places.origin_id verweist.
Downloads
Seit Firefox 26 werden Downloads in places.sqlite erfasst; ältere Profile verwendeten eine separate downloads.sqlite. Ein Download fügt einen Besuch vom Typ 7 für die Quell-URL und zwei Seitenannotationen in moz_annos hinzu, die mit der place_id dieser URL verknüpft und über moz_anno_attributes.name benannt werden:
downloads/destinationFileURI:contententhält den Speicherort als URI, beispielsweisefile:///C:/Users/jsilva/Downloads/Q1_payroll.zip.downloads/metaData:contententhält JSON mitstate(1 abgeschlossen, 2 fehlgeschlagen, 3 abgebrochen; andere Werte kennzeichnen pausierte oder blockierte Downloads),endTimein Millisekunden seit 1970 UTC,fileSize(vorhanden, wenn der Download erfolgreich war) unddeleted.
Die Zeilen in moz_annos enthalten außerdem dateAdded und lastModified in PRTime. Untermauern Sie die Befunde anhand des Dateisystems: mit dem $MFT-Eintrag der Datei und ihrem Datenstrom Zone.Identifier (Lektion 1.4).
Weitere Profildateien
favicons.sqlite: Symbole (moz_icons), die mit Seiten-URLs (moz_pages_w_icons) verknüpft sind; eine ergänzende Spur dafür, dass eine Seite geladen oder als Lesezeichen gespeichert wurde.formhistory.sqlite:moz_formhistoryspeichert Werte, die in Webformularfelder eingegeben wurden:fieldname,value,timesUsed,firstUsedundlastUsed(PRTime). Auch Suchfelder erscheinen hier, häufig mit demfieldnamesearchbar-history.cookies.sqlite:moz_cookiesmithost,name,value,creationTimeundlastAccessed(PRTime) sowieexpiry. Die Werte sind nicht verschlüsselt. Ältere Versionen speichernexpiryin Unix-Sekunden, aktuelle Versionen in Millisekunden. Prüfen Sie daher die Anzahl der Ziffern.permissions.sqlite:moz_permserfasst Website-Berechtigungen (origin,typewiedesktop-notificationodercamera,permission,modificationTime).logins.json: gespeicherte Anmeldedaten.hostname,formSubmitURLund die Zeitangaben sind lesbar;encryptedUsernameundencryptedPasswordsind mit einem Schlüssel auskey4.dbverschlüsselt (NSS-Schlüsseldatenbank, seit Firefox 58 SQLite), geschützt durch das Hauptpasswort, sofern eines festgelegt wurde.extensions.json: installierte Add-ons mitid,version,active,installDateundupdateDate(Millisekunden) sowiepath; die Pakete liegen inextensions\als.xpi-Dateien.addons.jsonspeichert Metadaten aus dem Add-on-Store zwischen. Achten Sie auf Add-ons, die der Benutzer nicht wissentlich installiert hätte.
Sitzungsdaten
Der Ordner sessionstore-backups enthält den Sitzungszustand:
recovery.jsonlz4: die laufende Sitzung, die während des Betriebs von Firefox neu geschrieben wird (standardmäßig alle 15 Sekunden).recovery.baklz4: die vorherige Kopie der Wiederherstellungsdatei.previous.jsonlz4: die Sitzung vor dem letzten Neustart.upgrade.jsonlz4-<buildID>: eine beim Aktualisieren von Firefox erstellte Kopie, benannt mit der 14-stelligen Build-ID.- Beim ordnungsgemäßen Beenden schreibt Firefox außerdem
sessionstore.jsonlz4in das Stammverzeichnis des Profils.
Die Dateien verwenden Mozillas eigenen LZ4-Container: Die Bytes 0–7 enthalten die magische Kennung mozLz40\0 (6D 6F 7A 4C 7A 34 30 00), die Bytes 8–11 die unkomprimierte Größe als 32-Bit-Ganzzahl in Little-Endian-Reihenfolge und der Rest einen einzelnen rohen LZ4-Block, keinen LZ4-Frame. Deshalb weist das standardmäßige Befehlszeilenwerkzeug lz4 die Datei zurück. Verwenden Sie ein spezialisiertes Werkzeug wie dejsonlz4 oder lz4json oder Python: lz4.block.decompress(data[12:], uncompressed_size=int.from_bytes(data[8:12], 'little')). Gleichwertig ist lz4.block.decompress(data[8:]), da diese Funktion standardmäßig ein 4 Byte langes Größenpräfix in Little-Endian-Reihenfolge liest.
Das JSON zeigt windows[].tabs[], jeweils mit entries[] (dem Vorwärts- und Rückwärtsverlauf des Tabs: url, title, Referrer), einem index, der den aktuellen Eintrag kennzeichnet, und lastAccessed; _closedTabs mit closedAt; _closedWindows; sowie formdata mit Text, der in Seitenfelder eingegeben wurde (Passwortfelder werden nicht gespeichert). Die Sitzungszeiten sind Millisekunden seit 1970 UTC. Ein Vergleich von previous.jsonlz4 mit recovery.jsonlz4 zeigt, was sich zwischen den Sitzungen geändert hat.
Firefox und Chromium im Vergleich
| Firefox-Datei | Chromium-Entsprechung | Beantwortete Fragen |
|---|---|---|
places.sqlite: moz_places, moz_historyvisits | History: urls, visits | Welche Seiten wann und auf welchem Weg erreicht wurden |
places.sqlite: moz_annos | History: downloads, downloads_url_chains | Was von wo heruntergeladen und wo gespeichert wurde |
places.sqlite: moz_inputhistory | Shortcuts: omni_box_shortcuts | Was der Benutzer in die Adressleiste eingegeben hat |
places.sqlite: moz_bookmarks | Bookmarks (JSON) | Welche Seiten bewusst gespeichert wurden und wann |
formhistory.sqlite | Web Data: autofill | Welche Werte in Webformulare eingegeben wurden |
cookies.sqlite | Network\Cookies (Werte verschlüsselt) | Welche Websites besucht und welche Sitzungen aufrechterhalten wurden |
logins.json + key4.db | Login Data + Schlüssel aus Local State | Welche Anmeldedaten für welche Websites gespeichert wurden |
sessionstore-backups\*.jsonlz4 | Sessions\Session_*, Tabs_* | Welche Tabs geöffnet und geschlossen waren und welche Formulardaten auf Seiten vorlagen |
extensions.json | Extensions\ + Preferences | Welche Add-ons installiert waren |
Durchgerechnetes Beispiel: eingegeben, dann heruntergeladen
Eine Triage-Sicherung enthält places.sqlite und das zugehörige WAL. Die Frage lautet: Hat der Benutzer gezielt eine Dateiübertragungs-Website aufgerufen, und wann wurde ein Download abgeschlossen? Führen Sie Folgendes aus:
SELECT v.id, v.from_visit, strftime('%Y-%m-%dT%H:%M:%SZ', v.visit_date/1000000, 'unixepoch') AS visit_utc, v.visit_type, p.url FROM moz_historyvisits v JOIN moz_places p ON p.id = v.place_id ORDER BY v.visit_date;
| id | from_visit | visit_utc | visit_type | url |
|---|---|---|---|---|
| 1201 | 0 | 2026-05-19T08:41:37Z | 2 | https://transfer.example.com/ |
| 1202 | 1201 | 2026-05-19T08:42:18Z | 1 | https://transfer.example.com/d/7Hq2 |
| 1203 | 1202 | 2026-05-19T08:42:25Z | 7 | https://dl.transfer.example.com/7Hq2/Q1_payroll.zip |
Der Rohwert von visit_date für Besuch 1201 beträgt 1.779.180.097.512.334. Die Ganzzahldivision durch 1.000.000 ergibt 1.779.180.097 Sekunden, also 2026-05-19T08:41:37Z; die Division schneidet die 0,512334 s ab, wie es bei einem Ergebnis in ganzen Sekunden vorgesehen ist. (datetime(visit_date/1000000,'unixepoch') liefert denselben Zeitpunkt ohne T und Z.) Besuch 1201 ist vom Typ TYPED und hat keinen Referrer, und moz_inputhistory enthält input = trans mit einem Verweis auf diese Seite. Der Benutzer hat somit den Anfang der Adresse eingegeben. Besuch 1202 entstand durch das Folgen eines Links von 1201 aus, und Besuch 1203 war ein Download, der von 1202 aus gestartet wurde.
Für den Seiteneintrag der ZIP-URL (das Ziel von Besuch 1203) lautet downloads/metaData: {"state":1,"deleted":false,"endTime":1779180163904,"fileSize":48213977}. Hier ist endTime in Millisekunden angegeben: 1.779.180.163.904 ÷ 1.000 = 1.779.180.163,904 s. Der Download wurde also um 2026-05-19T08:42:43Z abgeschlossen, 18 Sekunden nach dem Besuch vom Typ 7.
Verwechseln Sie die Epochen der Browser nicht. Chromium speichert denselben Zeitpunkt als Mikrosekunden seit 1601: (1.779.180.097 + 11.644.473.600) × 1.000.000 + 512.334 = 13.423.653.697.512.334, und die Chromium-Abfrage muss nach der Division 11.644.473.600 abziehen. Wenn Sie den Firefox-Wert mit der Chromium-Formel dekodieren, erhalten Sie 1657-05-19T08:41:37Z; dekodieren Sie den Chromium-Wert als PRTime, erhalten Sie 2395-05-19T08:41:37Z. Beide verwenden Mikrosekunden als Einheit, sodass sie sich nur durch die Epoche unterscheiden; ein 16-stelliger Wert im Jahr 2026 ist PRTime und ein 17-stelliger Wert ist Chromium-Zeit.
Werkzeuge
DB Browser for SQLite führt Abfragen wie die oben gezeigte aus. Plaso verfügt über Firefox-SQLite-Plugins wie firefox_history, firefox_downloads und firefox_10_cookies. Vergleichen Sie deren Ausgabe mit einer manuellen Abfrage, da sich die Schemata zwischen den Versionen ändern (beispielsweise liest Plaso expiry bei Cookies als Sekunden, während Firefox 142 und neuer Millisekunden speichern). Hindsight analysiert ausschließlich Chromium-basierte Browser und liest keine Firefox-Profile.
Prüfungsschwerpunkt: Rechnen Sie damit, PRTime-Werte in ISO 8601 UTC umrechnen,visit_type-Codes lesen (insbesondere 2 TYPED und 7 DOWNLOAD) und den Speicherpfad sowie den Abschlusszeitpunkt eines Downloads ausmoz_annosermitteln zu müssen. Denken Sie dabei daran, dassendTimein Millisekunden angegeben ist. Möglicherweise müssen Sie auch das aktive Profil anhand vonprofiles.inioderinstalls.iniermitteln oder den HeadermozLz40\0und seine Länge von 12 Byte erkennen.
Kernpunkte
- Das Roaming-Profil enthält die Datenbanken, das lokale Profil den Cache;
profiles.iniundinstalls.inigeben an, welches Profil jede Installation verwendet hat. - Verknüpfen Sie
moz_historyvisits.place_idmitmoz_places.id; PRTime sind Mikrosekunden seit 1970 UTC, Chromium-Zeit sind Mikrosekunden seit 1601. - Seit Firefox 26 bestehen Downloads aus einem Besuch vom Typ 7 sowie den Annotationen
downloads/destinationFileURIunddownloads/metaData, wobeiendTimein Millisekunden angegeben ist. - Der Formularverlauf, Cookie-Werte und die Formulardaten der Sitzung werden unverschlüsselt gespeichert; für gespeicherte Passwörter wird
key4.dbbenötigt. - Sitzungsdateien bestehen aus einem 12 Byte langen Header
mozLz40\0und einem LZ4-Block. Sie geben Aufschluss über geöffnete Tabs, geschlossene Tabs und eingegebene Formulardaten. - Sichern Sie stets die Dateien
-walund-shmund analysieren Sie Kopien.