Forensics w systemie Linux — jak odczytać ślady włamań
Poniżej znajdziesz praktyczny, krok‑po‑kroku przewodnik po analizie incydentów (DFIR) na systemach Linux — od przygotowania i zbierania dowodów, przez analizę dysku i pamięci, aż po korelację wydarzeń i raportowanie. Skupiłem się na technikach i narzędziach używanych przez analityków (SleuthKit, dd/dcfldd/dc3dd, auditd, LiME/Volatility, journalctl itp.) oraz na przykładach komend — wszystko w kontekście odzyskiwania śladów włamania, zachowując zasady zachowania dowodów.
1. Zasady wstępne — legalność, bezpieczeństwo, notacja
- Legalność i uprawnienia — upewnij się, że masz prawo do wykonywania analiz (zgoda właściciela, polecenie przełożonego, procedury prawne).
- Zachowaj nienaruszalność dowodów — wykonuj działania kopiujące; nie pracuj bezpośrednio na systemie produkcyjnym, jeśli chcesz zachować oryginały.
- Dokumentuj wszystko — daty, osoby wykonujące działania, polecenia, sumy kontrolne, nośniki, czas i sposób zdobycia obrazu. To podstawa łańcucha dowodowego (chain of custody).
2. Co zebrać najpierw — volatile vs non‑volatile
- Volatile (ulotne): pamięć RAM, aktywne procesy, otwarte połączenia sieciowe, tablice ARP/conntrack, zawartość cache, login sessions. Musisz je złapać przed rebootem.
- Non‑volatile: obrazy dysków/partycji, pliki logów, konfiguracje (
/etc), konta użytkowników, pliki w home, pliki cron, binaria.
Zasada: najpierw zrób zrzut pamięci, potem obraz dysku.

3. Zrzut pamięci (memory acquisition)
Dlaczego: w pamięci znajdziesz procesy, połączenia sieciowe, zaszyfrowane klucze, shell history w RAM, in‑memory malware.
Narzędzia popularne: LiME, AVML, Volatility 3 (do analizy). Przykładowy workflow: podmontuj moduł LiME i wykonaj dump pamięci na zdalny serwer lub nośnik.
Przykład (LiME):
# na maszynie ofiary: skompilowany moduł lime.ko
insmod lime.ko "path=/mnt/usb/memdump.lime format=lime"
# albo zrzut do stdout -> nc (ostrożnie, zabezpiecz)
Po przechwyceniu użyj Volatility 3 lub Volatility 2 z profilem dla jądra/architektury do ekstrakcji procesów, socketów, modułów, haszy i haseł w pamięci.
4. Tworzenie obrazu dysku (forensic imaging)
Narzędzia: dd, dcfldd, dc3dd, ewfacquire (dla E01) — wybierz narzędzie które wspiera haszowanie i zapis w bezpiecznym formacie. Ważne: używaj conv=sync,noerror lub narzędzi z wbudowanym hashowaniem. Zapisuj sumy kontrolne (MD5/SHA256).
Przykład:
# prosty obraz z dd (nie zapominaj o hashu)
sudo dd if=/dev/sdb of=/evidence/image.dd bs=4M conv=sync,noerror status=progress
sha256sum /evidence/image.dd > /evidence/image.dd.sha256
Lepiej: dcfldd lub dc3dd mają opcje tworzenia hashów w trakcie tworzenia obrazu.
5. Analiza systemu plików i timeline (SleuthKit, fls, mactime)
The Sleuth Kit (TSK) oferuje narzędzia do przeglądania obrazu dysku bez modyfikacji — fls, icat, ils, ffind. Na ich podstawie można wygenerować timeline (pliki z odczytami MAC times — Modified, Accessed, Changed) i przejrzeć zmiany plików w czasie przy pomocy mactime. To pomaga odtworzyć chronologię działań atakującego.
Przykład:
fls -r -m / image.dd > fls_output.txt
mactime -b fls_output.txt > timeline.txt
Szukaj: nagłych tworzeń/usunięć plików, nietypowych timestampów, modyfikacji plików binarnych, założonych backdoorów.
6. Logi systemowe — gdzie szukać i jak czytać
Najważniejsze lokalizacje i polecenia:
/var/log/auth.log(Debian/Ubuntu) lub/var/log/secure(RHEL/CentOS) — logi logowania,sudo, błędne hasła.journalctl— systemd‑journal: pozwala przeglądać dzienniki, filtrować po bootach, usługach, PID. Możesz eksportować pliki journal i analizować offline./var/log/syslog,/var/log/messages— ogólne wydarzenia systemowe.wtmp/utmp— narzędzialast,whopokazują sesje./var/log/faillog,/var/log/btmp— nieudane próby logowania.
Przykłady:
# ostatnie logowania
last -a
# przegląd journal od czasu określonego
journalctl --since "2025-09-15 08:00" --until "2025-09-16 08:00"
# eksport journal do pliku (do analizy offline)
journalctl --utc --output=short-iso > /evidence/journal.txt
Szukaj: nietypowych godzin logowań, powtarzających się nieudanych prób, sudo bez kontekstu, uruchomienia shelli z netcat/ reverse shell, zmiany uprawnień.
7. Auditd i monitoring aktywności systemowej
auditd to system audytu jądra — jeśli był aktywny, da bardzo szczegółowy zapis uruchomień plików, execve, zmian uprawnień, otwarć plików itp. Jeśli nie był skonfigurowany przed incydentem, rozważ jego włączenie do dalszej detekcji. Elastic Security i wielu autorów zalecają auditd jako źródło detekcji.
Podstawowe polecenia:
ausearch -m EXECVE --start recent-date --end recent-date
aureport --summary
8. Procesy, otwarte pliki i połączenia sieciowe
Na żywym systemie:
ps auxf,top/htop— procesy; szukaj obcych nazw, procesów uruchomionych z nietypowych ścieżek.lsof -i -Pn— otwarte gniazda sieciowe.ss -tulpnlubnetstat -tulpen— nasłuchujące porty i powiązane PIDy.chkconfig --list/systemctl list-units --type=service— usługi systemowe; sprawdź nowe lub podejrzane jednostki systemd.
Szukaj: procesów z nazwami maskującymi (np. systemd z dziwnym PID/ścieżką), otwartych połączeń do egzotycznych adresów, nietypowych nasłuchujących portów.
9. Hakerzy zostawiają artefakty konfiguracji — gdzie patrzeć
/etc/passwd,/etc/shadow— nowe konta, nietypowe UID (0).~/.ssh/authorized_keys— dodane klucze publiczne./etc/cron.*icrontab -l— zaplanowane zadania (backdoory)./etc/systemd/system/— niestandardowe usługi (możliwy autostart backdoorów).- SUID/SGID pliki:
find / -perm /6000 -type f -ls— mogą być wykorzystane do eskalacji. - Modyfikacje binariów: porównaj sumy kontrolne z zaufanym repozytorium lub sprawdź daty modyfikacji binarek systemowych.
10. Rootkit i skanery integralności
- Narzędzia:
rkhunter,chkrootkit(szybkie sprawdzenie),AIDE,tripwire(monitoring integralności). Nie polegaj wyłącznie na nich — rootkity kernelowe mogą ukrywać wpisy. - Porównuj sumy kontrolne plików systemowych z czystą instalacją lub repo.
11. Analiza sieci i artefakty ruchu
- Zrzuty pakietów (pcap) jeśli dostępne —
tcpdump -wna podejrzanych interfejsach. iptables -L -n -v,conntrack -L— zapisy połączeń i reguły.- Logi serwerów (nginx, apache) w
/var/log— sprawdź nieautoryzowane uploady, wykorzystania luk (webshell).
12. Korelacja i timeline — jak połączyć wszystko
Po zebraniu: połącz timeline z pamięci (procesy + sockets), timeline plików (mactime), oraz wpisów z journalctl i /var/log/auth.log. Celem jest ustalenie sekwencji: wejście -> eskalacja -> działania -> exfiltration / persistence. Narzędzia takie jak mactime, SIEM (Elastic, Splunk) lub prosty skrypt do łączenia zdarzeń pomogą w korelacji.
13. Przykładowe „czerwone flagi” (co może wskazywać na włamanie)
- Nowe konto
rootlub konto z UID 0. - Nowe klucze SSH w
authorized_keys. - Nietypowe
cronwpisy. - Niezwykłe pliki SUID/SGID lub zmienione binaria.
- Procesy uruchomione z
/tmp,/var/tmplub z katalogów domowych. - Połączenia sieciowe do podejrzanych IP lub szyfrowanych kanałów w niestandardowych portach.
- Usługi systemd o nietypowych nazwach.
14. Raportowanie i działania po incydencie
- Zachowaj kopie dowodów (obrazy dysków, pamięć, logi).
- Przywróć system z zaufanej kopii (reinstall), nie używaj naprawczych „łatek” na zainfekowanym systemie.
- Zgłoś incydent — wewnętrzne procedury, prawne, CERT, jeśli wymagane.
- Wnioski i wzmocnienia — wdrożenia monitoringu (
auditd, OSSEC, EDR), rotacja kluczy/hasel, poprawa zasad dostępu i backupów.
15. Krótkie podsumowanie poleceń (cheat‑sheet)
# zrzut pamięci (LiME) - przykładowo
insmod lime.ko "path=/mnt/usb/memdump.lime format=lime"
# obraz dysku
sudo dc3dd if=/dev/sdb of=/evidence/image.dd hash=sha256
# timeline (TSK)
fls -r -m / image.dd > fls.txt
mactime -b fls.txt > timeline.txt
# przeglądanie journal
journalctl --since "2025-09-20" --until "2025-09-21" --output=short-iso > journal.txt
# procesy / sieć
ps auxf
lsof -i -Pn
ss -tulpn
# szukanie podejrzanych SUID
find / -perm /6000 -type f -ls
Źródła i dalsza literatura
Dla pogłębienia: dokumentacja Sleuth Kit, artykuły o auditd, poradniki o zrzucie pamięci LiME/AVML oraz przewodniki po tworzeniu obrazów dysków (dd, dcfldd, dc3dd). Poniżej kilka istotnych odnośników, których użyłem przygotowując ten przewodnik.
Gotowe — przygotowałem skrypt automatycznego zbierania dowodów.
#!/usr/bin/env bash
# forensic_collection_script.sh
# Skrypt do automatycznego zbierania dowodów (Linux)
# UWAGA: używaj tylko jeśli masz odpowiednie uprawnienia i zgodę. Zapisz kopię oryginalną i dokumentuj łańcuch dowodowy.
# Zapisuje zrzut pamięci (jeśli dostępny), listę procesów, otwarte pliki, połączenia sieciowe, logi systemowe, klucze SSH, cron, informacje o systemie
# generuje sumy kontrolne i manifest. Kompresuje pakiet dowodowy na końcu.
set -euo pipefail
IFS=$’\n\t’
TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ)
HOST=$(hostname -s)
OUTDIR=”/tmp/evidence_${HOST}_${TIMESTAMP}”
mkdir -p „$OUTDIR”
LOGFILE=”$OUTDIR/collector.log”
exec > >(tee -a „$LOGFILE”) 2>&1
manifest_file=”$OUTDIR/manifest.txt”
echo „Forensic collection – host: $HOST – started: $TIMESTAMP (UTC)” | tee -a „$manifest_file”
# Helper: run a command and record it in manifest
run_cmd() {
echo „[CMD] $*” | tee -a „$manifest_file”
„$@”
}
hash_file() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum „$1” | tee -a „$manifest_file”
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 „$1” | tee -a „$manifest_file”
else
echo „No sha256 utility found” | tee -a „$manifest_file”
fi
}
# 1) Check for required privileges
if [ „$EUID” -ne 0 ]; then
echo „Warning: skrypt najlepiej uruchomić jako root (sudo). Kontynuuję, ale niektóre zbiory mogą się nie udać.” | tee -a „$manifest_file”
fi
# 2) Collect volatile data: memory (try AVML -> LiME), processes, network, lsof
collect_memory() {
echo „\n== memoriaz collection ==” | tee -a „$manifest_file”
if command -v avml >/dev/null 2>&1; then
echo „Found AVML, creating memory dump via avml…” | tee -a „$manifest_file”
out=”$OUTDIR/memdump_avml_${TIMESTAMP}.lime”
avml -z „$out” && hash_file „$out” || echo „avml failed” | tee -a „$manifest_file”
elif [ -f „/usr/local/bin/lime.ko” ] || [ -f „./lime.ko” ]; then
echo „LiME kernel module found locally, attempting insmod…” | tee -a „$manifest_file”
# user must ensure lime.ko is compatible with kernel
modfile=”./lime.ko”
if [ -f „/usr/local/bin/lime.ko” ]; then modfile=”/usr/local/bin/lime.ko”; fi
out=”$OUTDIR/memdump_lime_${TIMESTAMP}.lime”
echo „Attempting: insmod $modfile path=$out format=lime” | tee -a „$manifest_file”
if insmod „$modfile” „path=$out” „format=lime” 2>/dev/null; then
echo „LiME insmod OK” | tee -a „$manifest_file”
hash_file „$out” || true
else
echo „LiME insmod failed (kernel mismatch?). Skipping memory dump.” | tee -a „$manifest_file”
fi
else
echo „No memory acquisition tool (avml or LiME) found. Skipping memory dump.” | tee -a „$manifest_file”
fi
}
collect_processes_network() {
echo „\n== processes and network ==” | tee -a „$manifest_file”
ps auxwwf > „$OUTDIR/processes.ps.txt” || true
hash_file „$OUTDIR/processes.ps.txt”
ss -tulpen > „$OUTDIR/ss_tulpen.txt” 2>/dev/null || netstat -tulpen > „$OUTDIR/netstat_tulpen.txt” || true
[ -f „$OUTDIR/ss_tulpen.txt” ] && hash_file „$OUTDIR/ss_tulpen.txt”
[ -f „$OUTDIR/netstat_tulpen.txt” ] && hash_file „$OUTDIR/netstat_tulpen.txt”
lsof -i -Pn > „$OUTDIR/lsof_i.txt” 2>/dev/null || true
hash_file „$OUTDIR/lsof_i.txt” || true
# active TCP connections
ss -tna > „$OUTDIR/ss_tna.txt” || true
hash_file „$OUTDIR/ss_tna.txt” || true
}
collect_logs_and_journal() {
echo „\n== logs and journal ==” | tee -a „$manifest_file”
# journalctl export
if command -v journalctl >/dev/null 2>&1; then
journalctl –utc –output=short-iso > „$OUTDIR/journal.txt” 2>/dev/null || true
hash_file „$OUTDIR/journal.txt” || true
fi
# typical log files
for f in /var/log/auth.log /var/log/secure /var/log/syslog /var/log/messages; do
if [ -f „$f” ]; then
cp –preserve=timestamps „$f” „$OUTDIR/” || true
hash_file „$OUTDIR/$(basename $f)” || true
fi
done
# web server logs (if any)
for dir in /var/log/nginx /var/log/apache2 /var/log/httpd; do
if [ -d „$dir” ]; then
mkdir -p „$OUTDIR/$(basename $dir)”
cp -a „$dir”/* „$OUTDIR/$(basename $dir)/” 2>/dev/null || true
# hash files
find „$OUTDIR/$(basename $dir)” -type f -print0 | xargs -0 -r sha256sum >> „$manifest_file” 2>/dev/null || true
fi
done
}
collect_files_and_config() {
echo „\n== files and configuration ==” | tee -a „$manifest_file”
# passwd / shadow (copy only accessible by root)
cp –preserve=timestamps /etc/passwd „$OUTDIR/” 2>/dev/null || true
cp –preserve=timestamps /etc/group „$OUTDIR/” 2>/dev/null || true
if [ -f /etc/shadow ]; then cp –preserve=timestamps /etc/shadow „$OUTDIR/” 2>/dev/null || true; fi
hash_file „$OUTDIR/passwd” || true
# ssh keys
find /root /home -maxdepth 3 -type f -name authorized_keys -print0 2>/dev/null | xargs -0 -r -I{} bash -c 'cp –preserve=timestamps „{}” „$OUTDIR/” && echo „copied {}” >> „$manifest_file”’ || true
# cron
crontab -l > „$OUTDIR/crontab_root.txt” 2>/dev/null || true
hash_file „$OUTDIR/crontab_root.txt” || true
cp -a /etc/cron.* „$OUTDIR/cron_dirs” 2>/dev/null || true
# systemd units (custom)
mkdir -p „$OUTDIR/systemd_units”
cp -a /etc/systemd/system/* „$OUTDIR/systemd_units/” 2>/dev/null || true
find „$OUTDIR/systemd_units” -type f -print0 | xargs -0 -r sha256sum >> „$manifest_file” 2>/dev/null || true
# SUID files list
find / -perm /6000 -type f -ls > „$OUTDIR/suid_files.txt” 2>/dev/null || true
hash_file „$OUTDIR/suid_files.txt” || true
}
collect_disk_image_optional() {
# Optional: create raw image if IMAGING_DEVICE env var set (e.g. IMAGING_DEVICE=/dev/sda)
if [ -n „${IMAGING_DEVICE:-}” ]; then
device=”$IMAGING_DEVICE”
out=”$OUTDIR/disk_image_${HOST}_${TIMESTAMP}.dd”
echo „\n== Disk imaging requested ($device) ==” | tee -a „$manifest_file”
if command -v dc3dd >/dev/null 2>&1; then
echo „Using dc3dd to image $device -> $out” | tee -a „$manifest_file”
dc3dd if=”$device” of=”$out” hash=sha256 || echo „dc3dd failed” | tee -a „$manifest_file”
hash_file „$out” || true
elif command -v dcfldd >/dev/null 2>&1; then
echo „Using dcfldd to image $device -> $out” | tee -a „$manifest_file”
dcfldd if=”$device” of=”$out” hash=sha256 || echo „dcfldd failed” | tee -a „$manifest_file”
hash_file „$out” || true
else
echo „No forensically-aware imaging tool found (dc3dd/dcfldd). Falling back to dd (not recommended).” | tee -a „$manifest_file”
dd if=”$device” of=”$out” bs=4M conv=sync,noerror status=progress || true
hash_file „$out” || true
fi
fi
}
collect_network_packets_optional() {
# Optional: capture short network trace if CAPTURE_IF env var set (e.g. CAPTURE_IF=eth0)
if [ -n „${CAPTURE_IF:-}” ]; then
iface=”$CAPTURE_IF”
out=”$OUTDIR/pcap_${iface}_${TIMESTAMP}.pcap”
echo „Capturing 120 seconds of traffic on $iface to $out” | tee -a „$manifest_file”
timeout 120 tcpdump -n -i „$iface” -w „$out” || true
hash_file „$out” || true
fi
}
collect_system_info() {
echo „\n== system info ==” | tee -a „$manifest_file”
uname -a > „$OUTDIR/uname.txt” || true; hash_file „$OUTDIR/uname.txt” || true
lsb_release -a > „$OUTDIR/lsb_release.txt” 2>/dev/null || true; hash_file „$OUTDIR/lsb_release.txt” || true
dmesg –ctime > „$OUTDIR/dmesg.txt” 2>/dev/null || true; hash_file „$OUTDIR/dmesg.txt” || true
ip addr show > „$OUTDIR/ip_addr.txt” 2>/dev/null || true; hash_file „$OUTDIR/ip_addr.txt” || true
df -h > „$OUTDIR/df_h.txt” 2>/dev/null || true; hash_file „$OUTDIR/df_h.txt” || true
}
# Run collectors
collect_memory
collect_processes_network
collect_logs_and_journal
collect_files_and_config
collect_system_info
collect_disk_image_optional
collect_network_packets_optional
# Finalize: list files, compute full archive hash, compress
echo „\n== Finalizing ==” | tee -a „$manifest_file”
find „$OUTDIR” -type f -print0 | xargs -0 -r sha256sum >> „$manifest_file” 2>/dev/null || true
archive=”${OUTDIR}.tar.gz”
# Use –no-overwrite-dir to be safe; preserve timestamps
tar -czf „$archive” -C „$(dirname „$OUTDIR”)” „$(basename „$OUTDIR”)” || true
if [ -f „$archive” ]; then
echo „Archive created: $archive” | tee -a „$manifest_file”
hash_file „$archive”
fi
echo „Collection finished. Evidence directory: $OUTDIR” | tee -a „$manifest_file”
echo „Na koniec: upewnij się, że kopia została przeniesiona na bezpieczny, write-once nośnik i zanotuj łańcuch dowodowy.” | tee -a „$manifest_file”
# exit
exit 0
Co zawiera i jak go użyć (krótkie instrukcje):
- Skrypt zbiera (w zależności od dostępności narzędzi): zrzut pamięci (AVML/LiME), listę procesów, otwarte pliki, połączenia sieciowe, eksport
journalctl, typowe pliki z/var/log, kopie/etc/passwd,/etc/shadow(jeśli dostępne),authorized_keys, wpisy cron, jednostki systemd, listę plików SUID i inne informacje diagnostyczne. - Tworzy katalog dowodowy w
/tmp/evidence_<host>_<timestamp>/, generuje manifest z poleceniami i sumami kontrolnymi SHA‑256, a na końcu kompresuje katalog do archiwum.tar.gzi hashuje je. - Opcjonalne: utworzenie obrazu dysku jeśli ustawisz zmienną środowiskową
IMAGING_DEVICE=/dev/sdXprzed uruchomieniem; krótkie przechwycenie ruchu jeśli ustawiszCAPTURE_IF=eth0. - Uruchomienie: zapisz plik i nadaj prawa wykonywalne, np.
chmod +x forensic_collection_script.shi uruchomsudo ./forensic_collection_script.sh. Jeśli chcesz imaging dysku:sudo IMAGING_DEVICE=/dev/sda ./forensic_collection_script.sh. - Ważne: uruchamiaj tylko gdy masz uprawnienia i zgodę. Zbieranie może wpływać na system (szczególnie imaging i insmod LiME). Dokumentuj łańcuch dowodowy i przechowuj archiwa na bezpiecznym nośniku.
Jeśli chcesz, mogę:
- zmodyfikować skrypt pod twoją dystrybucję (Debian/Ubuntu vs RHEL/CentOS) — od razu naniosę poprawki,
- dodać eksport do zdalnego serwera (np. z użyciem
nc/scp) z uwzględnieniem szyfrowania, - albo wygenerować wersję
systemd/Ansible playbook do automatycznego uruchamiania na wielu hostach.
Którą opcję wybierasz?






