Docker forensics investigation requires immediate evidence preservation
When you get that 3 AM call about a potential container escape, your first moves determine whether you'll have usable evidence or spend the next week explaining to lawyers why you can't prove what data was stolen. Time is your enemy here - Docker logs rotate fast, containers get deleted, and evidence disappears while you're still figuring out what happened.
My first CVE-2025-9074 case was a disaster. Got the call at 3 AM, stumbled to my laptop, and immediately started docker stop
on the suspicious containers. Big mistake. By the time I realized I needed those containers running for memory dumps, they were gone. Evidence destroyed. Lawyers were pissed.
Here's what I should have done, and what you need to do RIGHT NOW if you're dealing with an active incident.
CVE-2025-9074: The Stupid Simple Container Escape
Docker Desktop left their management API exposed at 192.168.65.7:2375 with zero authentication. Felix Boulet found this during a routine nmap scan in August 2025 - any container on your system can hit that endpoint with a simple HTTP POST and create new containers with host filesystem access.
The attack is embarrassingly simple:
## Inside any container, this works:
curl -X POST http://[DOCKER_API]:2375/containers/create \
-H \"Content-Type: application/json\" \
-d '{\"Image\":\"alpine\",\"Cmd\":[\"sh\"],\"HostConfig\":{\"Binds\":[\"C:\\:/host\"]}}'
Note: [DOCKER_API] represents 192.168.65.7 - Docker Desktop's internal management API that was exposed without authentication.
That's it. No exploit code, no buffer overflows, just a basic HTTP request to Docker's own API. The attacker gets a container with your entire C: drive mounted at /host.
The Evidence You Need to Grab (And Where Docker Hides It)
Here's the brutal truth: Docker logs rotate every 7 days by default. If you don't grab them immediately, you're fucked. I learned this the hard way on case #3 when the client called me a week after the incident. No logs, no evidence, no way to prove what data was accessed.
Evidence that disappears fast:
- Container memory dumps (gone when containers stop)
- Docker daemon logs (rotate weekly on Windows, daily on Linux)
- Container stdout/stderr logs (deleted with container removal)
- Network connection states (ephemeral by design)
Evidence that might survive:
- Container filesystem layers in
/var/lib/docker/overlay2/
(untildocker system prune
) - Host filesystem modification timestamps (until cleanup scripts run)
- Windows Event Logs (if you're lucky and they weren't cleared)
- Your SIEM logs (if you have good log forwarding set up)
Evidence you probably won't find:
- Detailed HTTP request logs to 192.168.65.7:2375 (Docker doesn't log internal API calls by default)
- Authentication logs (there was no authentication to begin with)
- Process command lines from inside containers (unless you had sysdig running)
The \"Oh Shit\" Checklist: What to Do RIGHT NOW
Step 1: DON'T PANIC AND STOP CONTAINERS
I see people do this constantly. Your first instinct is to stop the malicious containers. Don't. You'll destroy memory evidence and lose any chance of understanding what the attacker was doing.
Step 2: Create snapshots (if you have disk space)
## Windows: VSS snapshots (this fails half the time if Docker is using the disk)
vssadmin create shadow /for=C:
## If that fails: Stop all Docker Desktop services first, then try again
## macOS: This works but takes forever on large Docker directories
sudo hdiutil create -srcfolder /Users -format UDRO forensic-$(date +%s).dmg
## Spoiler alert: It'll run out of space if you have 50GB of container images
## Linux: LVM snapshots (only works if you're using LVM, which nobody does anymore)
lvcreate -L100M -s -n forensic-snap /dev/vg0/root
## Modern Linux: Just copy the docker directory if you have space
rsync -av /var/lib/docker/ /tmp/docker-backup/
Step 3: Memory dumps (spoiler: these probably won't work)
## Windows: WinPMem crashes on containers using WSL2
winpmem_v3.3.rc3.exe --output memory-$(date +%Y%m%d).raw
## Alternative: Use DumpIt.exe, but it's slow as hell
## Linux: LiME works great until you run out of /tmp space
dd if=/dev/zero of=/tmp/test-space bs=1M count=1000 # Test if you have space first
insmod lime.ko \"path=/tmp/memory-$(hostname).lime format=lime\"
## macOS: osxpmem is a pain on M1 Macs
./osxpmem -o memory-$(date +%s).aff4
## Note: This fails on recent macOS versions due to System Integrity Protection
Step 4: Container forensics (the stuff that actually matters)
## Export containers WHILE THEY'RE RUNNING (this is key)
for container in $(docker ps -q); do
echo \"Exporting $container at $(date)\"
# This takes forever with large containers - budget 5-10 minutes each
docker export $container > evidence/container_${container}_$(date +%Y%m%d_%H%M%S).tar
# Get the full container config (contains the smoking gun bind mounts)
docker inspect $container > evidence/container_${container}_config.json
# Grab container logs before they rotate
docker logs --timestamps $container > evidence/container_${container}_logs.txt 2>&1
done
## System state snapshot - this shows what containers existed
docker ps -a --no-trunc --format \"table {{.ID}} {{.Image}} {{.Command}} {{.CreatedAt}} {{.Status}}\" > evidence/all_containers.txt
## Don't trust \"docker images\" - get the full manifest data
docker images --no-trunc --digests --format \"table {{.Repository}}:{{.Tag}} {{.ID}} {{.Digest}} {{.CreatedAt}} {{.Size}}\" > evidence/image_inventory.txt
Step 5: Network state (grab it fast, it changes constantly)
## Network connections RIGHT NOW (before containers start/stop)
if command -v ss >/dev/null; then
ss -tulpn > evidence/network_sockets_$(date +%H%M%S).txt
else
netstat -tulpn > evidence/network_connections_$(date +%H%M%S).txt
fi
## Windows-specific network info (if you can get admin rights)
if [[ \"$OSTYPE\" == \"msys\" ]]; then
netsh interface ipv4 show config > evidence/windows_network_config.txt
arp -a > evidence/arp_table.txt
# This shows Docker's internal networking - crucial for CVE-2025-9074
route print > evidence/routing_table.txt
fi
## Container network configs (these show if containers had special network access)
docker network ls --format \"{{.ID}} {{.Name}} {{.Driver}}\" > evidence/docker_networks.txt
for net in $(docker network ls -q); do
docker network inspect $net > evidence/network_${net}.json
done
Security monitoring dashboard integration for container forensics
Chain of Custody (AKA Cover Your Ass Documentation)
Your lawyers will want timestamps for everything, but here's the thing - Docker's internal API calls aren't logged by default. Hope you had network monitoring running or you're screwed.
What you MUST document:
- UTC timestamps for everything (don't fuck up timezones like I did in case #2)
- SHA-256 hashes of all evidence files
- Exact Docker version and OS details
- Who touched what evidence and when
#!/bin/bash
## Evidence collection log (lawyers love this stuff)
mkdir -p evidence/
CASE_ID=\"CVE2025-9074-$(hostname)-$(date +%Y%m%d-%H%M%S)\"
COLLECTOR=\"$(whoami) on $(hostname)\"
UTC_TIME=$(date -u +\"%Y-%m-%d %H:%M:%S UTC\")
cat > evidence/forensic_chain_of_custody.txt << EOF
=== CVE-2025-9074 CONTAINER ESCAPE INVESTIGATION ===
Case ID: $CASE_ID
Investigator: $COLLECTOR
Collection Start: $UTC_TIME
System: $(uname -a)
Docker Version: $(docker --version 2>/dev/null || echo \"Docker not available\")
Docker Desktop Version: $(docker version --format '{{.Server.Version}}' 2>/dev/null || echo \"Unknown\")
Timeline of Evidence Collection:
$(date -u): Started evidence collection
EOF
## Hash everything as you collect it
hash_evidence() {
local file=\"$1\"
if [[ -f \"$file\" ]]; then
local hash=$(sha256sum \"$file\" 2>/dev/null | cut -d' ' -f1 || echo \"HASH_FAILED\")
echo \"$(date -u +\"%Y-%m-%d %H:%M:%S UTC\"): $file - SHA256: $hash\" >> evidence/forensic_chain_of_custody.txt
fi
}
Where Docker Actually Keeps Its Logs (Good Luck Finding Them)
Docker Desktop on Windows (prepare for a scavenger hunt):
- Main logs:
%APPDATA%\Docker\log\host\
and%APPDATA%\Docker\log\vm\
- Docker service logs: Windows Event Viewer → Applications and Services → Docker Desktop
- WSL2 logs:
\\wsl$\docker-desktop-data\version-pack-data\community\log\
- The smoking gun API logs: Usually not logged anywhere (thanks Docker!)
Docker Desktop on macOS (at least it's consistent):
- Main logs:
~/Library/Containers/com.docker.docker/Data/log/
- VM logs:
~/Library/Containers/com.docker.docker/Data/log/vm/
- Console.app logs: Search for "Docker" or "com.docker.docker"
Docker Engine on Linux (the only sane option):
- Systemd systems:
journalctl -u docker.service --since \"2 hours ago\"
- SysV systems:
/var/log/docker.log
(if it exists) - Container logs:
/var/lib/docker/containers/[id]/[id]-json.log
Electronic monitoring equipment for comprehensive system analysis
Docker Config Files (Where the Secrets Hide)
What to grab:
## Docker Desktop settings (Windows)
if [[ -f \"$APPDATA/Docker/settings.json\" ]]; then
cp \"$APPDATA/Docker/settings.json\" evidence/docker_desktop_settings.json
fi
## Docker Desktop settings (macOS)
if [[ -f \"$HOME/Library/Group Containers/group.com.docker/settings.json\" ]]; then
cp \"$HOME/Library/Group Containers/group.com.docker/settings.json\" evidence/docker_desktop_settings.json
fi
## Docker daemon config (Linux)
if [[ -f \"/etc/docker/daemon.json\" ]]; then
cp /etc/docker/daemon.json evidence/docker_daemon_config.json
fi
## Docker Compose files (scattered everywhere)
find . -name \"docker-compose*.yml\" -o -name \"compose.yml\" 2>/dev/null | while read compose_file; do
echo \"Found: $compose_file\" >> evidence/compose_files_found.txt
cp \"$compose_file\" \"evidence/$(basename $compose_file .yml)_$(date +%s).yml\"
done
The Legal Reality Check
Here's what your lawyers will ask and why you probably can't answer:
"What data was accessed?"
If the attacker mounted your entire C: drive, the answer is "potentially everything." Good luck with that breach notification.
"When did this start?"
Docker Desktop doesn't timestamp API access by default. Unless you had network monitoring, you're guessing.
"How do we prove this wasn't authorized?"
CVE-2025-9074 uses legitimate Docker API calls. Your logs will show normal container creation commands. The bind mounts are the only smoking gun.
"What's our regulatory exposure?"
If you're handling PCI, HIPAA, or GDPR data on developer workstations (and who isn't), you're probably looking at mandatory breach disclosure. Budget for lawyers and regulatory fines. The vulnerability was public for 5 days before the August 20, 2025 patch - expect questions about your patch management timeline.
The evidence collection window is small, and the stakes are high. Most organizations I've worked with had insufficient logging to definitively prove what happened. Don't be one of them.
Actually useful resources:
- NIST Incident Response Guide - The only framework worth following
- SANS Digital Forensics Methodology - Good process overview
- Docker Security Docs - Mostly useless for forensics but lawyers like citations
- Felix Boulet's CVE Analysis - The researcher who found this mess
- Docker Forensics Toolkit - Post-mortem analysis tools for Docker environments
- NIST Container Security Guide - NIST SP 800-190 container security framework
- Docker Engine Security - Docker's security documentation
- CVE-2025-9074 Technical Analysis - Official vulnerability details
- Digital Forensics Framework - Open source forensics platform
- Volatility Memory Forensics - Memory analysis for container processes
- SANS FOR508 Course Materials - Container forensics training
- Docker API Reference - Complete API documentation for forensic analysis