<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: performing-database-forensics
description: >-
  Database forensic analysis of MySQL, PostgreSQL, SQLite, and MSSQL.
  Covers transaction log recovery, deleted row reconstruction, query
  history extraction, privilege escalation detection, and data exfiltration
  timeline reconstruction using native database tools and binary log parsing.
domain: cybersecurity
subdomain: digital-forensics
tags:
  - database-forensics
  - mysql
  - postgresql
  - sqlite
  - mssql
  - transaction-logs
  - binlog
  - wal
  - deleted-data-recovery
  - query-history
version: "1.0"
author: defconxt
license: AGPL-3.0
compatibility: Designed for Claude Code, GitHub Copilot, OpenAI Codex, Cursor, Gemini CLI, and any agentskills.io-compatible agent.
metadata:
  mitre-attack: ["T1505.001", "T1565.001", "T1213"]
  nist-csf: ["RS.AN-1", "RS.AN-3"]
  frameworks: ["NIST SP 800-86", "CIS Database Benchmarks"]
---

# Performing Database Forensics

## Overview

Database forensics recovers evidence from database management systems
including query history, deleted records, transaction logs, privilege
changes, and data exfiltration indicators. This skill covers MySQL binlog
analysis, PostgreSQL WAL recovery, SQLite forensics, and MSSQL
transaction log examination.

## Prerequisites

| Requirement | Details |
|---|---|
| Forensic copy of database data directory (never work on live production) | Required |
| `mysqlbinlog`, `pg_waldump`, `sqlite3`, `sqlcmd` | Required |
| `undark` for SQLite deleted record recovery | Required |
| Python 3.10+ with database connectors | Required |

## Workflow

### Step 1: MySQL Binary Log Analysis

```bash
# List available binary logs
mysqlbinlog --no-defaults --list-logs /var/lib/mysql/binlog.index

# Decode binary log to SQL statements
mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -v \
  /var/lib/mysql/binlog.000042 > binlog_decoded.sql

# Filter by time range
mysqlbinlog --no-defaults \
  --start-datetime="2026-03-10 00:00:00" \
  --stop-datetime="2026-03-17 23:59:59" \
  /var/lib/mysql/binlog.000042 > binlog_timerange.sql

# Search for specific table modifications
grep -n "DELETE\|DROP\|TRUNCATE\|ALTER" binlog_decoded.sql

# Extract user privilege changes
grep -n "GRANT\|REVOKE\|CREATE USER\|DROP USER" binlog_decoded.sql
```

### Step 2: PostgreSQL WAL Recovery

```bash
# Parse WAL files for transaction records
pg_waldump /var/lib/postgresql/data/pg_wal/000000010000000000000042

# Filter by transaction ID range
pg_waldump -s 0/1500000 -e 0/1600000 \
  /var/lib/postgresql/data/pg_wal/000000010000000000000042

# Check PostgreSQL audit log
grep -E "LOG:|ERROR:|FATAL:" /var/log/postgresql/postgresql-*.log

# Extract authentication events
grep "connection authorized\|authentication failed" \
  /var/log/postgresql/postgresql-*.log
```

### Step 3: SQLite Forensic Analysis

```bash
# Recover deleted records from SQLite
undark -i evidence.db > recovered_records.txt

# Examine database schema
sqlite3 evidence.db ".schema"
sqlite3 evidence.db ".tables"

# Dump all tables with timestamps
sqlite3 evidence.db "SELECT name FROM sqlite_master WHERE type='table';" | \
  while read table; do
    echo "=== $table ==="
    sqlite3 -header -csv evidence.db "SELECT * FROM $table LIMIT 100;"
  done > full_dump.csv

# Check for WAL file (uncommitted transactions)
ls -la evidence.db-wal evidence.db-shm 2>/dev/null
sqlite3 evidence.db "PRAGMA wal_checkpoint(PASSIVE);"

# Examine freelist pages (deleted content)
sqlite3 evidence.db "PRAGMA freelist_count;"
strings evidence.db | grep -i "password\|secret\|key" > strings_output.txt
```

### Step 4: MSSQL Transaction Log Analysis

```bash
# Read transaction log using fn_dblog
sqlcmd -S localhost -d target_db -Q "
SELECT [Current LSN], Operation, Context, [Transaction ID],
       [Begin Time], [Transaction Name], [Transaction SID]
FROM fn_dblog(NULL, NULL)
WHERE Operation IN ('LOP_DELETE_ROWS', 'LOP_INSERT_ROWS', 'LOP_MODIFY_ROW')
ORDER BY [Current LSN] DESC;"

# Find who dropped a table
sqlcmd -S localhost -d target_db -Q "
SELECT [Begin Time], [Transaction Name], SUSER_SNAME([Transaction SID])
FROM fn_dblog(NULL, NULL)
WHERE [Transaction Name] = 'DROPOBJ';"
```

## Detection

```yaml
title: Database Forensics Detection
id: 43fc6e28-e0cd-4b5e-8cac-94885f85a240
status: experimental
description: Detects suspicious activity related to performing database forensics techniques in digital forensics context
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine: "*performing*database*"
  condition: selection
level: medium
tags:
  - attack.t1505.001
  - attack.t1565.001
  - attack.t1213
  - attack.collection
falsepositives:
  - Forensic investigation tools used by authorized incident response team
```


**Detection Opportunities**

| Indicator | Source | Detection Logic |
|---|---|---|
| Database Forensics Detection | windows/process_creation | Sigma rule (medium) |
| ATT&CK Coverage | MITRE ATT&CK | T1505.001, T1565.001, T1213 |

## Verification

- [ ] Database files forensically copied (not live analysis)
- [ ] Transaction/binary logs parsed for the incident window
- [ ] Deleted records recovered where possible
- [ ] User privilege changes documented
- [ ] Authentication anomalies identified
- [ ] Data exfiltration queries flagged
- [ ] Timeline of database operations established

## References

- [MySQL Binary Log Reference](https://dev.mysql.com/doc/refman/8.0/en/mysqlbinlog.html)
- [PostgreSQL WAL Internals](https://www.postgresql.org/docs/current/wal-internals.html)
- [SQLite File Format](https://www.sqlite.org/fileformat.html)
- [undark — SQLite Deleted Record Recovery](https://github.com/nicholasmckinney/undark)
- [MSSQL fn_dblog Reference](https://learn.microsoft.com/en-us/sql/relational-databases/system-functions/sys-fn-dblog-transact-sql)
