DigitalForensics

70 13 63 23

SQLite i forensic: WAL‑filer, frie sider og slettede rækker

SQLite i forensic: WAL-filer, frie sider og slettede rækker

Forside › Analyse og fortolkning · Gennemgået oktober 2026 · Af John Nielsen

SQLite er den database, der ligger under det meste af det, man undersøger på telefoner og computere: beskeder, opkaldslister, browserhistorik, fotobiblioteker, appdata og mange programmers indstillinger. Når en række slettes, forsvinder den ikke nødvendigvis fra filen med det samme. Den kan ligge tilbage i ubrugt plads i en side, på en fri side eller i en ældre version i WAL-filen. Det gør SQLite til en værdifuld kilde til slettede data, men også til en kilde, hvor sporene let ødelægges, hvis databasen åbnes forkert, og hvor fortolkningen kræver forsigtighed.

Filens opbygning

En SQLite-database er én fil, delt i sider af fast størrelse, typisk 4.096 bytes. Filen starter med en header på 100 bytes, der blandt andet angiver sidestørrelse, antal sider, den første side på listen over frie sider og databasens tekstkodning.

Tabeller og indeks er gemt som B-træer:

  • Bladsider indeholder selve rækkerne, kaldet celler. Hver celle har et rowid, en recordheader med feltypernes koder og selve feltværdierne.
  • Indre sider peger videre til andre sider.
  • Overløbssider rummer den del af en stor række, der ikke kan være i bladsiden.
  • Frie sider er sider, der ikke længere bruges, og som står på databasens liste over frie sider til senere genbrug.

Øverst i hver side ligger en oversigt over cellernes placering, og cellerne selv ligger fra bunden af siden og opad. Mellem de to er der ufordelt plads.

Hvad sker der, når en række slettes?

Når en række slettes, fjernes dens henvisning fra sidens oversigt. Selve cellens bytes bliver som udgangspunkt liggende, enten som en fri blok i siden eller i den ufordelte plads, indtil pladsen genbruges. Bliver en side helt tom, flyttes den til listen over frie sider, og hele indholdet kan ligge der uændret.

Tre indstillinger afgør, hvor længe sporene overlever:

  • secure_delete overskriver slettet indhold med nuller. Er den slået til, findes der normalt intet at gendanne i hovedfilen.
  • auto_vacuum fjerner frie sider fra filen, enten løbende eller på kommando.
  • VACUUM genopbygger hele databasen og fjerner al ubrugt plads.

Hvilke indstillinger en app bruger, varierer og kan ændre sig med versionerne. Det skal undersøges i den konkrete database, fx i headeren og i appens adfærd. Headeren viser, om auto_vacuum er slået til, mens secure_delete ikke gemmes i filen og derfor må udledes af, om frie sider er nulstillet.

Journal og WAL

SQLite beskytter mod halve skrivninger med en journal. Der findes to hovedtyper:

  • Tilbagerulningsjournal (filen med endelsen -journal). Før en ændring kopieres de oprindelige sider til journalen. Efter transaktionen slettes eller nulstilles den. Rester kan indeholde tidligere versioner af sider.
  • Write-Ahead Log (filen med endelsen -wal og tilhørende -shm). Her skrives ændrede sider som rammer i WAL-filen, mens hovedfilen er uændret. Ved et checkpoint kopieres de nyeste versioner til hovedfilen.

WAL er særligt interessant. Samme side kan forekomme flere gange i WAL-filen, så der kan ligge flere versioner af den samme række, herunder versioner fra før en sletning eller redigering. Efter et checkpoint begynder WAL-filen forfra, og rammerne får nye saltværdier, men gamle rammer længere fremme i filen bliver liggende, indtil de overskrives. De kan læses, selvom de ikke længere er gyldige for databasen.

Det betyder også, at en database uden sin WAL-fil kan mangle de nyeste ændringer. På telefoner og computere, der er i brug, kan de seneste beskeder ligge i WAL-filen og endnu ikke i hovedfilen.

Sikring uden at ødelægge sporene

Den hyppigste fejl er at åbne den originale database i et almindeligt databaseprogram. Når SQLite åbner en database i WAL-tilstand og lukker den igen, kan den udføre et checkpoint og fjerne WAL-filen. Dermed forsvinder ældre versioner og eventuelt de nyeste ændringer.

  • Sikr databasen sammen med alle tilhørende filer: -wal, -shm og -journal, fra samme tidspunkt.
  • Sikr helst fra en diskkopi eller et filsystemudtræk, så filerne er i den tilstand, de var på enheden. Se Udtræk fra mobiltelefoner.
  • Beregn hashværdi for hver fil, og arbejd kun på kopier.
  • Åbn kun kopier og helst med værktøjer, der læser filerne skrivebeskyttet. Gem en urørt kopi af sættet til senere kontrol.
  • Analysér hovedfil og WAL hver for sig og samlet, og dokumentér, hvilken tilstand resultaterne svarer til.

Gendannelse af slettede rækker

Værktøjer til SQLite-gendannelse gennemsøger frie blokke, ufordelt plads, frie sider, overløbssider og WAL-rammer efter byte-mønstre, der ligner gyldige celler. De bruger tabellernes skema til at genkende feltrækkefølge og typer.

Resultatet er ofte ufuldstændigt:

  • Recordheaderen kan være delvis overskrevet, så feltgrænser og typer må gættes.
  • En række kan ikke altid henføres sikkert til en bestemt tabel, hvis flere tabeller har lignende struktur.
  • Rowid og andre felter kan mangle, så rækken ikke kan sættes i sammenhæng.
  • Store tekster kan være delt over overløbssider, der er genbrugt.

Fund skal derfor vurderes enkeltvis, og det skal fremgå, hvor i filen hver række er fundet, og hvor sikker henføringen er.

Tidsstempler

SQLite har ingen indbygget dato- og tidstype. Apps gemmer tid som tal eller tekst i deres egen form: Unix-sekunder, millisekunder, Apples epoke fra 2001, WebKit-tid fra 1601 eller tekststrenge. Felterne skal omregnes korrekt, og tidszonen skal fastlægges. Se Tidsstempelformater. Databasen registrerer ikke selv, hvornår en række er slettet. Sletningstidspunktet kan kun indkredses ud fra andre spor.

Hvor SQLite bruges

Andre apps gemmer data i formater som plist og LevelDB, som har deres egne regler for sletning, se Plist, LevelDB og andre app-formater.

Typiske fejlkilder

  • Dubletter forveksles med flere hændelser. Samme række kan forekomme i hovedfil, WAL og frie sider. Det er versioner af én række, ikke flere beskeder.
  • Gamle versioner læses som slettede. En tidligere version af en redigeret række er ikke en slettet besked.
  • Manglende WAL giver et billede af databasen, der ikke svarer til enhedens tilstand.
  • Indeks forveksles med tabeller. Indeks gemmer kopier af enkelte kolonner. En gendannet indekspost viser en værdi, ikke hele rækken.
  • Værktøjets visning. Analyseværktøjer viser ofte en “rapport” over beskeder, der er bygget af flere tabeller. Kontrollér de rå rækker, før en vigtig konklusion drages.
  • Skemaændringer mellem appversioner gør, at en gendannet række fra en ældre version tolkes efter det nye skema.

Hvad det kan og ikke kan bevise

Gendannede rækker kan vise, at data har eksisteret i databasen, og sammen med WAL-versioner kan de vise, at indhold er ændret eller fjernet. De kan ikke vise, hvornår eller af hvem en sletning skete, og fravær af gendannede rækker beviser ikke, at intet er slettet.

I rapporten

Angiv de sikrede filer med hashværdier, hvordan de er sikret, og om hovedfil og WAL er analyseret hver for sig. For hver gendannet række angives fundsted, side og forskydning, tabel og henføringens sikkerhed samt omregnede tidsstempler.

Kilder og versioner

Senest gennemgået: oktober 2026.

Næste skridt

Del af: Analyse og fortolkning

Læs også: Browserhistorik som bevis: Chrome, Edge, Safari og Firefox · Plist, LevelDB og andre app-formater

→ Digital forensics-undersøgelse · For sagkyndige · Tlf. 70 13 63 23 · Digital bevissikring hos Nielco IT

Skrevet af John Nielsen, IT‑sagkyndig og indehaver af Nielco IT. Selvstændig siden 2009 og mere end 30 års erfaring med IT‑sikkerhed. Har været IT‑sagkyndig i danske retskredse og ved Den Fælles Europæiske Patentdomstol (UPC). Om John Nielsen · LinkedIn · Redaktionel politik

John Nielsen, IT-sagkyndig

Brug for en forensisk undersøgelse?

Skriv kort, hvilke systemer eller enheder det drejer sig om, og om noget haster, så vender jeg tilbage. Kun civile sager.

Tak for din henvendelse. Jeg vender tilbage hurtigst muligt.