Jak monitorować polecenia użytkowników na serwerze Linux
Historia powłoki nie jest wiarygodnym audytem. Porównaj logi sudo, sesje I/O, hooki powłoki oraz reguły auditd execve. Dowiedz się, jak bezpiecznie eksportować logi z serwera.
Co faktycznie rejestruje polecenia uruchamiane przez użytkowników na serwerze
Aby przeprowadzić audyt poleceń uruchamianych przez użytkowników na serwerze, wymagany jest zapis, którego użytkownik nie może edytować. Historia powłoki (shell history) nie spełnia tego wymogu. Jest to plik pomocniczy, którego właścicielem jest konto użytkownika, a każda osoba mająca dostęp do powłoki może go wyłączyć lub usunąć.
Istnieją cztery warstwy zapewniające wiarygodny zapis, z których każda wiąże się z określonym kosztem. sudo zapisuje jedną linię na polecenie w syslog. Rejestrowanie wejścia/wyjścia (I/O logging) w sudo przechwytuje całą sesję dla danego konta. Hook powłoki, taki jak PROMPT_COMMAND, rejestruje to, co wpisał interaktywny użytkownik bash. Podsystem audytu jądra rejestruje samo wywołanie systemowe execve, dlatego jest to jedyna warstwa widząca każdy proces. Niniejszy przewodnik opisuje te rozwiązania, wskazuje ograniczenia każdej z warstw i kończy się kwestią decydującą o wartości całego procesu: eksportem zapisów z maszyny, zanim osoba poddawana audytowi uzyska do nich dostęp.
Ostrzeżenie przed rozpoczęciem: podsystem audytu działa na poziomie jądra, dlatego nie można go testować wewnątrz kontenera współdzielącego jądro hosta. Powyższe polecenia należy uruchamiać na serwerze KVM VPS, gdzie użytkownik posiada własne jądro.
Dlaczego historia powłoki nie stanowi ścieżki audytu
~/.bash_history nie sprawdza się jako dowód z czterech prozaicznych powodów i żaden z nich nie wymaga od atakującego szczególnej przebiegłości.
Należy do użytkownika. Plik ma uprawnienia 600 i jest własnością danego konta, więc rm ~/.bash_history nie wymaga żadnych specjalnych uprawnień. Podobnie jak otwarcie go w edytorze i usunięcie dwudziestu istotnych linii.
Jest zapisywana przy wyjściu z powłoki. Sesja zakończona poleceniem kill -9 $$ lub zerwanym połączeniem nie zapisuje niczego. history -c przed exit daje ten sam efekt i sprawia wrażenie, jakby nic się nie wydarzyło.
Można ją wyłączyć jednym słowem. unset HISTFILE zatrzymuje zapisywanie pliku dla danej sesji. set +o history natychmiast przerywa rejestrowanie. HISTCONTROL=ignorespace ukrywa każde polecenie poprzedzone spacją. Wszystko to jest częścią man bash, ponieważ mechanizm ten ma pozostawać pod kontrolą użytkownika.
Rejestruje to, co wpisano, a nie to, co zostało uruchomione. Alias lub funkcja powłoki sprawiają, że tekst w pliku nie odpowiada programowi, który faktycznie wykonał kernel.
Brakuje również znaczników czasu, chyba że zmienna HISTTIMEFORMAT była ustawiona w momencie zapisu wpisu, ponieważ bash zapisuje linie znacznika #1755043200 tylko wtedy, gdy ta zmienna jest zdefiniowana.
W przypadku współdzielonego logowania historia nie pozwala również ustalić sprawcy. Trzy osoby korzystające z jednego konta deploy generują jeden przeplatany plik pod jednym uid. Żadna warstwa logowania nie przypisze działania do konkretnej osoby, gdy dwie osoby współdzielą uid, co stanowi praktyczny argument za używaniem jednego nieuprzywilejowanego konta na osobę zamiast współdzielonego loginu.
Historia powłoki dobrze wywiązuje się ze swojego rzeczywistego zadania, którym jest pomoc w ponownym wpisaniu wczorajszego polecenia. Traktuj ją jako wskazówkę. Nigdy nie przedstawiaj jej jako dowodu.
Co rejestruje sudo i gdzie kończy się śledzenie
Narzędzie sudo wysyła wiersz dotyczący każdego uruchomionego polecenia do mechanizmu authpriv syslog.
sudo grep 'sudo:' /var/log/auth.log | tail -5
journalctl -t sudo -n 5Każdy wiersz zawiera nazwę użytkownika, terminal, katalog roboczy, użytkownika docelowego oraz wykonane polecenie:
sudo: alice : TTY=pts/0 ; PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/apt updateJeśli /var/log/auth.log nie istnieje, oznacza to, że rsyslog nie jest zainstalowany w danym obrazie, a wpisy znajdują się wyłącznie w journal. Przed poleganiem na dzienniku należy sprawdzić, czy nie jest on ulotny:
journalctl --list-bootsWyświetlenie tylko bieżącego uruchomienia systemu oznacza, że /var/log/journal nie istnieje, więc journal znajduje się w /run i każdy wiersz jest usuwany przy restarcie. Należy włączyć trwałość dziennika:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journaldOto ograniczenie. sudo rejestruje polecenie, które otrzymało do wykonania. Nie rejestruje natomiast działań podejmowanych przez to polecenie. Dlatego jeden wiersz kończy ścieżkę audytu:
sudo -iDziennik zawiera pojedynczy wpis dla powłoki. Każde polecenie wpisane wewnątrz powłoki root jest niewidoczne dla sudo, ponieważ sudo nie znajduje się już w ścieżce wywołania. sudo su -, sudo bash oraz sudo vim /etc/shadow, po których następuje :!bash, mają taką samą strukturę. Reguła w sudoers, która zezwala na uruchomienie dowolnego programu z możliwością wyjścia do powłoki, takiego jak vim lub find, jest regułą przyznającą dostęp do root bez rejestrowania działań. Przed zaufaniem wpisom w dzienniku należy sprawdzić, do jakich zasobów konto faktycznie ma dostęp:
sudo -l -U aliceRejestrowanie pełnej sesji dla jednego konta
Najpierw należy ustalić, która wersja sudo jest zainstalowana, ponieważ ta funkcja nie istnieje w implementacji przepisanej w języku Rust:
sudo --version | head -1Jeśli wynik wskazuje na sudo-rs, należy pominąć tę sekcję i skorzystać z podsystemu audit. Dokumentacja Ubuntu dla wydań 25.10 oraz 26.04 wskazuje, że logowanie I/O oraz sudoreplay nie są wspierane, co pozostawało aktualne w sierpniu 2026 roku. Jest to istotne, ponieważ sudo-rs stanowi domyślny sudo w tych wydaniach, więc aktualizacja może usunąć kontrolę, która była wcześniej dostępna. Warto zapoznać się z pełną listą zmian w zachowaniu sudo-rs przed planowaniem jakiegokolwiek logowania opartego na sudo.
W przypadku oryginalnego sudo, które nadal jest dostarczane w Ubuntu 24.04 LTS, należy włączyć logowanie I/O dla wybranego konta:
sudo visudo -f /etc/sudoers.d/iologDefaults:deploy log_output
Defaults!/usr/bin/sudoreplay !log_outputNależy używać visudo zamiast edytora tekstu, ponieważ narzędzie to odmawia zapisu pliku, który zawiera błędy składniowe. Uszkodzony plik sudoers blokuje dostęp do sudo dla wszystkich użytkowników. Następnie można odtworzyć sesję:
sudo sudoreplay -l user=deploy
sudo sudoreplay 000001sudoreplay -l wyświetla listę sesji wraz z ich identyfikatorami; jeśli log_output nigdy nie zostało zastosowane dla danego użytkownika, polecenie nie zwróci żadnych danych. Koszty rozwiązania: każdy bajt przesyłany przez terminal jest zapisywany w /var/log/sudo-io, więc sesja o dużej ilości danych wyjściowych zajmuje dużo miejsca. Druga linia w pliku sudoers zapobiega rejestrowaniu samego procesu odtwarzania sesji. Rzeczywistym zagrożeniem są dane wrażliwe, ponieważ log I/O przechowuje wszystko, co zostało wpisane i wyświetlone, w tym hasła wpisane w monity wewnątrz sesji, dlatego pliki te wymagają takiej samej ochrony jak menedżery haseł. Zakres monitorowania jest również ograniczony. Rejestrowane są tylko polecenia uruchamiane przez sudo. Użytkownik, który loguje się i pracuje wyłącznie na własnym koncie, nie jest w ogóle rejestrowany.
Hooki powłoki i sposoby ich obejścia
Popularna recepta na „logowanie każdego polecenia” polega na umieszczeniu hooka PROMPT_COMMAND w pliku /etc/profile.d/:
# /etc/profile.d/00-cmdlog.sh
PROMPT_COMMAND='logger -p local6.info -t cmdlog "$(whoami) $$ $(history 1 | sed "s/^ *[0-9]* *//")"'bash uruchamia PROMPT_COMMAND przed wyświetleniem każdego znaku zachęty, dzięki czemu wiersz trafia do syslog w momencie wpisywania, a nie przy wyjściu, natomiast logger zapisuje dane za pośrednictwem demona logów systemowych, więc uprawnienia do plików użytkownika nie mają tu znaczenia. Należy otworzyć nową powłokę logowania i sprawdzić działanie za pomocą sudo tail -f /var/log/syslog lub journalctl -t cmdlog -f w obrazie bez rsyslog.
Mechanizm ten przestaje działać w pięciu przypadkach, z których każdy można odtworzyć w minutę.
- Powłoki nieinteraktywne nigdy nie wyświetlają znaku zachęty.
ssh you@server 'id'uruchamia polecenie i kończy działanie, a logi nie powstają, ponieważPROMPT_COMMANDnigdy nie zostało wywołane. - Jest to zmienna.
unset PROMPT_COMMANDwyłącza ją do końca sesji i nie wymaga uprawnień administratora. - Plik jest odczytywany przez powłoki logowania.
bash --noprofile --norcw ogóle nie wczytuje/etc/profile.d/. - Rozwiązanie jest specyficzne dla bash.
zsh,sh,python3 -c 'import os; os.system("id")'oraz:!idwewnątrzvimuruchamiają programy, których żaden hook znaku zachęty bash nie zarejestruje. - Logowany jest wiersz w postaci wpisanej, więc alias lub funkcja nadal ukrywają polecenie, które faktycznie zostało wykonane.
Hooki powłoki należy traktować jako udogodnienie. Odpowiadają one na pytanie „co uruchomiłem w zeszły wtorek” w przypadku współpracujących użytkowników. Nie należy uznawać ich za mechanizm kontroli w listach kontrolnych bezpieczeństwa.
Podsystem audytu jądra rejestruje każde wywołanie execve
Podsystem audytu systemu Linux, obsługiwany przez demona auditd, stanowi jedyną warstwę, której użytkownik nie może ominąć, ponieważ wpis jest tworzony wewnątrz jądra w momencie wykonywania wywołania systemowego. Jeśli proces uruchamia program, zdarzenie zostaje odnotowane. Powłoka, język programowania oraz obecność terminala nie mają znaczenia.
sudo apt update && sudo apt install -y auditd audispd-plugins
sudo systemctl enable --now auditd
sudo auditctl -sauditctl -s wyświetla stan demona. enabled 1 z wartością inną niż zero w polu pid oznacza, że demon działa, a lost 0 oznacza, że do tej pory nie odrzucono żadnych rekordów. Należy zapamiętać licznik lost, ponieważ powróci on w dalszej części.
auid to pole, które sprawia, że audyt jest użyteczny. PAM ustawia identyfikator logowania (login uid) w momencie rozpoczęcia sesji, a jądro przekazuje go do każdego procesu potomnego. Sprawdź swój identyfikator:
cat /proc/self/loginuidInteraktywna sesja SSH wyświetla twój uid, ponieważ /etc/pam.d/sshd zawiera pam_loginuid.so. Wartość 4294967295 oznacza, że loginuid nigdy nie został ustawiony, co jest typowe dla procesów uruchamianych przez demony systemowe podczas startu. Istotne jest to, że sudo -i nie zmienia tej wartości: powłoka root otwarta przez użytkownika alice nadal posiada auid 1000, więc każde polecenie w niej wykonane jest przypisane do alice. Jest to dokładnie ta luka, którą pozostawia sudo. Zmiana loginuid po jego ustawieniu wymaga uprawnień CAP_AUDIT_CONTROL, których zwykli użytkownicy nie posiadają, a sudo auditctl --loginuid-immutable blokuje tę możliwość nawet dla użytkownika root aż do następnego restartu.
Upewnij się, że /etc/pam.d/sshd, /etc/pam.d/login oraz /etc/pam.d/cron zawierają pam_loginuid.so, w przeciwnym razie zdarzenia będą rejestrowane bez przypisanego użytkownika. Jest to ten sam zestaw plików, który modyfikuje się podczas utwardzania dostępu SSH na VPS, dlatego warto wykonać obie te czynności jednocześnie.
Podstawowy zestaw reguł dla auditd
Reguły znajdują się w /etc/audit/rules.d/*.rules. augenrules łączy je w kolejności alfabetycznej nazw plików w jedną listę, a kolejność ta decyduje o działaniu, ponieważ jądro zatrzymuje się na pierwszej pasującej regule. Przed dodaniem własnych wpisów należy sprawdzić istniejącą konfigurację, ponieważ -D w późniejszym pliku usuwa wszystkie wcześniej załadowane reguły.
ls /etc/audit/rules.d/
cat /etc/audit/rules.d/audit.rulesNastępnie należy utworzyć /etc/audit/rules.d/50-exec.rules:
## Suppressions first: the kernel takes the first matching rule.
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-deb
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-query
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-split
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-trigger
## Every program started by a logged-in human.
-a always,exit -F arch=b64 -S execve,execveat -F auid>=1000 -F auid!=unset -k exec
-a always,exit -F arch=b32 -S execve,execveat -F auid>=1000 -F auid!=unset -k exec
## Changes to who may become root.
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
## Changes to the audit configuration itself.
-w /etc/audit/ -p wa -k auditconfigZaładuj reguły i potwierdź ich poprawność:
sudo augenrules --load
sudo auditctl -lauditctl -l wyświetlający reguły oznacza, że są one aktywne. No rules oznacza, że ładowanie nie powiodło się, a journalctl -u auditd -n 20 wskazuje plik oraz linię, której parser nie zaakceptował. Starsze wersje pakietu audit nie obsługują słowa kluczowego unset. Jeśli loader zgłasza błąd dotyczący tego pola, należy wpisać -F auid!=4294967295, co jest równoważnym zapisem tej samej wartości.
Teraz odczytaj zdarzenia:
sudo ausearch -k exec -ts recent -i | tail -40
sudo ausearch -ul 1000 -ts today -i
sudo aureport -k --summary -i-i zamienia identyfikatory UID i numery wywołań systemowych na nazwy i w praktyce jest niezbędny. -ts recent obejmuje ostatnie dziesięć minut. Każde wykonanie programu dociera jako grupa rekordów: rekord SYSCALL zawierający uid, auid, status wyjścia i klucz, rekord EXECVE z pełną listą argumentów oraz rekordy CWD i PATH dla kontekstu.
Należy pamiętać o jednym istotnym ograniczeniu. audit rejestruje wywołania systemowe, a wbudowane polecenia powłoki nie generują własnych wywołań. cd /root nie uruchamia żadnego programu. echo evil >> /etc/passwd wpisane w powłoce bash również nie uruchamia programu, ponieważ zarówno echo, jak i przekierowanie odbywają się wewnątrz procesu powłoki, który już działa. Zatem reguły execve widzą programy, a reguły -w widzą operacje zapisu. Żaden z tych typów reguł nie jest wystarczający w izolacji.
Na koniec zablokuj konfigurację:
## /etc/audit/rules.d/99-finalize.rules
-e 2-e 2 czyni zestaw reguł niezmiennym aż do następnego restartu. Po załadowaniu tej opcji auditctl -s zgłasza enabled 2, a każda próba dodania lub usunięcia reguły kończy się błędem Operation not permitted, nawet w przypadku użytkownika root. Ten plik należy dodać jako ostatni; każda zmiana reguł będzie wymagała restartu systemu. Jest to celowe działanie: zestaw reguł, który można po cichu wyłączyć, nie stanowi wiarygodnego dowodu.
Dziennik audytu, którego nikt nie czyta, jest jedynie artefaktem zgodności
Tryb awaryjny auditd nie polega na pomijaniu zdarzeń. Problem tkwi w tym, że rejestruje on tak dużą ilość danych, iż nikt ich nie analizuje, a dziennik istnieje jedynie w celu spełnienia wymogów listy kontrolnej, zamiast udzielać odpowiedzi na konkretne pytania.
Przed dokonaniem jakiejkolwiek optymalizacji należy wykonać obliczenia na własnym serwerze:
sudo aureport -k --summary -i
sudo du -sh /var/log/auditPojedynczy sudo apt upgrade uruchamia tysiące krótkotrwałych procesów, a każdy z nich przenosi identyfikator auid, dlatego jedna aktualizacja pakietów może wygenerować więcej danych niż tydzień pracy użytkownika. Z tego powodu powyższe wykluczenia wskazują dpkg oraz procesy pomocnicze. Wykluczenia należy stosować według pliku wykonywalnego, nigdy według użytkownika: wykluczenie dla /usr/bin/dpkg to luka, którą można opisać jednym zdaniem, podczas gdy wykluczenie dla konta tworzy lukę o kształcie dokładnie takim, jaki próbowano wykryć.
Klucz -k w każdej regule sprawia, że dziennik nadaje się do przeszukiwania po miesiącu. ausearch -k sudoers to pytanie, na które istnieje odpowiedź. ausearch bez filtra to ściana tekstu, która uczy ignorowania logów. Jeśli system zbierania logów wymaga formatu JSON zamiast formatu natywnego, laurel jest wtyczką do auditd, która zapisuje każde zdarzenie jako pojedynczy obiekt JSON z zdekodowanymi argumentami. Rejestruje się ją w /etc/audit/plugins.d/ jak każdą inną wtyczkę, a auditd uwzględnia zmiany wtyczek przy sudo pkill -HUP auditd.
Rzeczywiste koszty działania auditd
Każde dopasowane wywołanie systemowe (syscall) staje się rekordem, który jądro formatuje i przekazuje do przestrzeni użytkownika. Koszt tego procesu objawia się w dwóch obszarach i oba można zmierzyć dla własnego obciążenia, zamiast polegać na szacunkach z zewnętrznych źródeł.
- Procesor i opóźnienia. Maszyna intensywnie korzystająca z operacji fork, na przykład serwer kompilacji lub agent CI, generuje rekord przy każdym wywołaniu exec. Gdy kolejka zdarzeń jądra się zapełni,
--backlog_wait_timewymusza wstrzymanie procesu generującego zdarzenie do momentu zwolnienia miejsca, dlatego audit objawia się raczej jako spowolnienie kompilacji niż jako procentowe zużycie procesora. Monitorujbacklogorazlostwsudo auditctl -spod rzeczywistym obciążeniem. Wzrost wartościlostoznacza utratę rekordów, a dziennik z lukami jest gorszy niż brak dziennika, ponieważ użytkownik nadal będzie go traktował jako wiarygodny. - Dysk. Przeczytaj
/etc/audit/auditd.confi podejmij świadomą decyzję o zachowaniu systemu w przypadku zapełnienia dysku, ponieważ domyślne wartości są jedynie sugestiami.max_log_file,num_logsorazmax_log_file_actionsterują rotacją.space_left_action,admin_space_left_actionorazdisk_full_actionzarządzają sytuacją awaryjną, a niektóre z dostępnych akcji, w tymhaltorazsingle, powodują zatrzymanie maszyny zamiast utraty rekordu.
Linia -f w pliku /etc/audit/rules.d/audit.rules to ta sama decyzja na poziomie jądra: -f 1 zgłasza błąd audytu do syslog, a -f 2 wywołuje kernel panic. Wybierz 2 tylko wtedy, gdy rzeczywiście wolisz utratę serwera niż utratę rekordu. W przypadku VPS obsługującego krytyczne usługi, skonfiguruj rotację i przenieś problem przechowywania danych poza dany serwer.
Wysyłanie logów poza serwer w czasie zbliżonym do rzeczywistego
To jest element, który potwierdzają wszystkie analizy incydentów. Logi pozostawione na przejętym hoście mogą zostać zmodyfikowane przez osobę, która uzyskała do niego dostęp. Użytkownik root może nadpisać /var/log/auth.log, usunąć /var/log/audit/audit.log oraz zatrzymać demona. -e 2 zapobiega wyładowaniu reguł, ale nie chroni przed rm. Każda wyższa warstwa zabezpieczeń dostarczy dowodów tylko wtedy, gdy kopia danych opuści maszynę.
Własny mechanizm transportowy audytu to wtyczka audisp-remote z pakietu audispd-plugins. Należy ją włączyć w pliku /etc/audit/plugins.d/au-remote.conf:
active = yes
direction = out
path = /usr/sbin/audisp-remote
type = always
format = stringPrzed przeładowaniem sprawdź path względem command -v audisp-remote, ponieważ błędna ścieżka nie wygeneruje żadnego komunikatu poza jedną linią w dzienniku. Ustaw remote_server oraz port w /etc/audit/audisp-remote.conf, a na serwerze zbierającym (collector) ustaw tcp_listen_port = 60 w jego własnym pliku auditd.conf. Przeładuj za pomocą sudo pkill -HUP auditd. W wielu obrazach systemowych systemctl restart auditd jest odrzucane, ponieważ plik jednostki ustawia RefuseManualStop=yes, dlatego wysłanie sygnału jest niezawodną metodą.
Inna opcja polega na przekierowaniu audytu do strumienia syslog, który już jest przesyłany dalej. /etc/audit/plugins.d/syslog.conf jest dostarczane z active = no. Ustaw wartość na yes, przeładuj, a zdarzenia audytu dołączą do linii sudo i pozostałych logów. Następnie prześlij całość za pomocą rsyslog przez TLS (transport layer security), co wymaga pakietu rsyslog-gnutls:
# /etc/rsyslog.d/60-forward.conf
*.* action(type="omfwd"
target="logs.example.net" port="6514" protocol="tcp"
StreamDriver="gtls" StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeers="logs.example.net"
action.resumeRetryCount="-1"
queue.type="linkedList" queue.filename="fwd" queue.saveOnShutdown="on")Ustawienia kolejki są kluczowe. action.resumeRetryCount="-1" ponawia próby w nieskończoność, a kolejka wspomagana dyskiem z queue.saveOnShutdown="on" przechowuje rekordy, gdy serwer zbierający jest niedostępny, a następnie wysyła je po przywróceniu połączenia. Bez tych dwóch elementów restart serwera zbierającego pozostawi lukę w dowodach, o której istnieniu nie będzie żadnej informacji. Zastosuj zmiany za pomocą sudo systemctl restart rsyslog, a następnie potwierdź, że rekordy faktycznie docierają do serwera zbierającego, zanim uznasz system za wiarygodny.
Pozostaje jedna kwestia do zamknięcia: serwer zbierający musi być maszyną, do której audytowani użytkownicy nie mają dostępu. Jeśli ta sama grupa administratorów posiada uprawnienia root na serwerze logów, pliki zostały jedynie skopiowane, a nie zabezpieczone. Wymagane są oddzielne poświadczenia, oddzielne klucze i najlepiej oddzielne konto u dostawcy. To ta sama logika, która sprawia, że centralny sposób zarządzania wieloma serwerami Linux warto zbudować, zanim stanie się to niezbędne. Jest to również różnica między użyteczną a bezużyteczną pierwszą godziną pracy, gdy przeprowadzasz analizę po przejęciu VPS.
Sprawdzenie, czy użytkownik bez uprawnień może nadpisać rekord
Zamiast zakładać poprawność zabezpieczeń, należy je przetestować. Z poziomu zwykłego konta, bez użycia sudo:
echo test >> /var/log/auth.log
cat /var/log/audit/audit.log
auditctl -D
id -nGNależy oczekiwać, w podanej kolejności: Permission denied, ponieważ auth.log jest własnością syslog z grupą adm i uprawnieniami 640; ponownie Permission denied, ponieważ dziennik audytu ma uprawnienia 600 i jest własnością root; błąd odmowy wykonania operacji, ponieważ zmiana reguł audytu wymaga uprawnień CAP_AUDIT_CONTROL; oraz listę grup, która nie zawiera ani adm, ani systemd-journal.
Ostatni test jest najczęściej pomijany. Członkostwo w adm zapewnia dostęp do odczytu /var/log/auth.log, a członkostwo w systemd-journal zapewnia dostęp do odczytu całego dziennika. Żadne z nich nie zapewnia uprawnień do zapisu, więc żadne nie pozwala na manipulację danymi. Oba pozwalają użytkownikowi na odczyt każdej linii uwierzytelniania w systemie, co powinno być świadomą decyzją, a nie wynikiem bezmyślnego kopiowania linii usermod -aG z odpowiedzi na forum.
Na koniec należy potwierdzić dwa elementy, które muszą przetrwać restart systemu:
sudo auditctl -s
systemctl is-enabled auditdenabled 2 oznacza, że zestaw reguł jest zablokowany do czasu następnego uruchomienia systemu. enabled w wyniku drugiego polecenia oznacza, że auditd uruchomi się ponownie po tym restarcie. Zestaw reguł, który przestaje działać po aktualizacji jądra, nie stanowi wiarygodnego śladu audytu.
FAQ
Jak sprawdzić wszystkie polecenia wykonane przez konkretnego użytkownika?
Znajdź jego uid za pomocą id -u alice, a następnie przeszukaj dziennik audytu według login uid: sudo ausearch -ul 1000 -ts today -i. Dodaj -k exec, aby ograniczyć wyniki do reguły execve. Login uid jest ustawiany podczas logowania i przetrwa su oraz sudo -i, dzięki czemu metoda ta rejestruje polecenia uruchomione w powłoce root otwartej przez to konto. Działa to tylko dla poleceń wykonanych po załadowaniu reguł, ponieważ audit nie przechowuje historii zdarzeń, których nie skonfigurowano do rejestracji. sudo aureport -k --summary -i pozwala wyświetlić liczbę zdarzeń dla każdej reguły, jeśli chcesz najpierw sprawdzić strukturę danych.
Czy użytkownik może usunąć swoją historię bash, aby ukryć wykonane polecenia?
Tak, nie wymaga to żadnych uprawnień. Plik ~/.bash_history jest własnością użytkownika z uprawnieniami 600, więc może on go edytować, wyczyścić lub usunąć. Użytkownik może również wyłączyć zapisywanie historii za pomocą unset HISTFILE, przerwać rejestrowanie w trakcie sesji przez set +o history lub ukryć pojedyncze polecenia, wpisując je ze spacją na początku, gdy ustawiona jest zmienna HISTCONTROL=ignorespace. Bash zapisuje plik przy zamykaniu powłoki, więc sesja zakończona przez kill -9 $$ nie pozostawia żadnych śladów. Historię powłoki należy traktować jako wskazówkę, a nie jako dowód.
Czy sudo rejestruje to, co dzieje się wewnątrz sudo -i?
Nie. sudo rejestruje tylko polecenie, które miało zostać uruchomione, więc sudo -i generuje jedną linię dla powłoki i nic więcej. Każde polecenie wpisane w tej powłoce root jest niewidoczne dla sudo, ponieważ sudo nie bierze już udziału w procesie. sudo su -, sudo bash oraz każdy dozwolony program z funkcją shell escape zachowują się w ten sam sposób. Lukę tę można zamknąć na dwa sposoby: poprzez reguły audit dla execve, które rejestrują każdy program z przypisanym oryginalnym login uid, oraz poprzez reguły sudoers, które w ogóle nie przyznają dostępu do powłoki.
Czy auditd spowolni mój serwer?
Zależy to całkowicie od liczby procesów uruchamianych przez obciążenie, dlatego należy to zmierzyć, zamiast polegać na szacunkach. Serwer, który głównie odpowiada na żądania, wykonuje niewiele operacji exec i nie odczuje różnicy. Serwer budujący oprogramowanie lub CI runner wykonuje operacje exec nieustannie i może odczuć spowolnienie, ponieważ gdy kolejka audit w jądrze się zapełni, proces generujący zdarzenie jest wstrzymywany do czasu zwolnienia miejsca. Uruchom sudo auditctl -s pod rzeczywistym obciążeniem i obserwuj backlog oraz lost. Każda wartość lost powyżej zera oznacza, że rekordy zostały utracone, co jest najgorszym scenariuszem, ponieważ w dzienniku powstają niewidoczne luki.
Gdzie powinny być przechowywane dzienniki audytu?
Na innej maszynie, z opóźnieniem mierzonym w sekundach. Każdy, kto uzyska dostęp root na audytowanym hoście, może usunąć /var/log/audit/audit.log i nadpisać /var/log/auth.log, więc lokalne kopie odpowiadają na pytania tylko o incydenty, których nikt nie próbował ukryć. Przesyłaj dane za pomocą wtyczki audisp-remote do centralnego auditd lub włącz wtyczkę syslog dla audit i przesyłaj cały strumień syslog za pomocą rsyslog przez TLS. Nadaj kolektorowi własne poświadczenia i upewnij się, że audytowane konta nie mają do niego dostępu.