Snapshot mode¶
Snapshot mode separates collection from analysis. You run a POSIX shell script on the target system, transfer the resulting tarball to your analyst workstation, and run privmap there. The target host needs no Python and no network egress.
This is the standard workflow for:
- Incident response on a host you cannot install software on.
- Forensic analysis after the fact.
- Air-gapped or production systems where running an arbitrary Python tool is out of policy.
- Bulk analysis of many hosts from a central workstation.
For penetration testing specifically (running the collector as an unprivileged user from a foothold, exfiltrating, analyzing locally), see the dedicated penetration testing page.
Collecting on the target¶
The collector is shipped as collect.sh in the repository. It is a
single shell script, POSIX-compliant, with no dependencies beyond
standard userland utilities (getcap, getfacl, find, awk).
This produces privmap_snapshot_<hostname>_<YYYYMMDD>.tar.gz in the
working directory. The script collects:
/etc/passwd,/etc/group,/etc/shadow(if readable),/etc/sudoers,/etc/sudoers.d/*- SUID/SGID binaries, world-writable files and directories, symlink
targets, and a recursive permission dump of
/etc,/usr,/opt,/tmp,/var - Linux capability binaries (
getcap -r /) - POSIX ACLs (
getfacl -R) on the same scan paths - Cron:
/etc/cron.d,/etc/cron.{hourly,daily,weekly,monthly},/var/spool/cron/crontabs,/etc/crontab - Systemd units from the standard search paths
/etc/init.dscripts- Running process metadata from
/proc/*/statusand/proc/*/cmdline - Group-writable file/directory listings (since v2.0)
- Login-time scripts:
/etc/profile,/etc/profile.d/*,/etc/bash.bashrc,/etc/skel/*(v2.0) - Library-loading control:
/etc/ld.so.preload,/etc/ld.so.conf,/etc/ld.so.conf.d/*(v2.0) - Polkit JS rules from
/etc/polkit-1/rules.dand the system path (v2.0) - doas configuration, sudo version string, PAM stack files,
/etc/security/*(v2.0) - SSH configuration:
sshd_configand host-key metadata (v2.0) - NFS exports, fstab, hosts.equiv,
/etc/hosts(v2.0) /proc/net/{tcp,tcp6,udp,udp6}for listener enumeration (v2.0)- Container markers:
/.dockerenv,/proc/1/cgroup(v2.0) - Per-process environment at
/proc/[pid]/environ.txt(v2.0)
Transfer the archive over whatever channel is appropriate (scp, removable media, and so on).
Analyzing on the workstation¶
privmap will:
- Extract the archive into a temporary directory with strict safety checks. See security note below.
- Run all ingesters against the extracted tree.
- Report paths to stdout.
- Clean up the temporary directory on exit.
All the live-mode flags work in snapshot mode:
privmap --snapshot snap.tar.gz --user www-data
privmap --snapshot snap.tar.gz --output json > report.json
privmap --snapshot snap.tar.gz --min-severity high
Live vs snapshot¶
| Aspect | Live mode | Snapshot mode |
|---|---|---|
| Filesystem walk | os.walk over scan paths |
Parses suid/permissions.txt from archive |
| Capabilities | getcap -r <root> |
Reads caps/file_capabilities.txt |
| ACLs | getfacl -R (live subprocess) |
Reads acl/acls.txt |
| Processes | /proc/*/status (live) |
Reads captured /proc snapshot if present |
| Permission-aware CAN_EXEC | Real stat() on each binary |
Lookup in captured permissions table |
| Cron user crontabs | /var/spool/cron/crontabs/* |
cron/user_crontabs/* in archive |
The analysis is otherwise identical. Same graph model, same DFS, same scoring. Snapshot mode is conservative: where data was not captured, the relevant edge is not emitted, never fabricated.
Security note on extraction¶
privmap defends against malicious or malformed archives during extraction. The archive is rejected with an error before any analysis runs if it contains:
- Absolute paths (e.g.
/etc/passwd) - Parent-directory traversal (e.g.
../../some/file) - Symbolic or hard links whose targets escape the temporary directory
- Special files (device nodes, FIFOs)
- More than 200,000 members
- More than 2 GiB of uncompressed content
These limits accommodate a whole-system snapshot from a real server while
refusing tar bombs and CVE-2007-4559 escapes. The implementation lives in
privmap.cli._safe_extract_tar.
Sharing snapshots safely¶
A snapshot is a complete inventory of a system's permission layout. Treat
it like a backup of /etc:
etc/shadowcontains password hashes if the collector ran as root. Strip it before sharing snapshots externally.etc/sudoersandetc/sudoers.d/*reveal trust relationships.proc/*/cmdlinemay contain secrets if applications pass them on the command line.
The collector does not collect kernel keyring entries, TLS private keys, SSH host or user keys, or application data. It collects what privilege analysis legitimately needs.