Logujemy logowania i nie tylko cz.I – moduły PAM
Napisał: Patryk Krawaczyński
27/01/2016 w Bezpieczeństwo Brak komentarzy. (artykuł nr 505, ilość słów: 532)
Z
ałóżmy, że posiadamy centralny system logowania, który gromadzi różne dane z wszystkich naszych serwerów. Może być on oparty o komercyjne usługi typu Loggly, Logentries, DataDog lub własne rozwiązania, których sercem jest Elasticsearch, czy RethinkDB. Zależy nam na tym, aby każde normalne logowanie i to na uprzywilejowane konto root, czy to bezpośrednio na maszynę, czy to za pomocą sudo było przesyłane do naszego centrum danych. Dane te mogą posłużyć nie tylko jako ewidencja i kontrola osób, które mają prawo do tego typu działań, ale również umożliwia nam ich analizę i wykrywanie potencjalnych naruszeń bezpieczeństwa.
Jednym z modułów PAM (ang. Pluggable Authentication Modules) jest pam_exec(8), który umożliwia wywołanie zewnętrznego polecenia oraz wykorzystanie w nim zmiennych środowiskowych typu PAM_RHOST, PAM_RUSER, PAM_SERVICE, PAM_TTY, PAM_USER
. Jak możemy się domyślić są to idealne zmienne, aby użyć je do uzyskania informacji o tym kto, gdzie i skąd zalogował się na maszynę oraz z jakiego użytkownika wykonywał polecenia administratora. Zacznijmy od stworzenia prostego skryptu w języku bash, który pozwoli nam w formacie json przesłać zdarzenie o logowaniu przez daemona SSH do naszej centrali logowań:
#!/bin/bash if [ "$PAM_TYPE" != "close_session" ]; then message="{\"EventReceivedTime\":\"`date +'%Y-%m-%d %R:%S'`\", \"User\":\"$PAM_USER\", \"Remotehost\":\"$PAM_RHOST\", \"LoginHost\":\"$(hostname -f) ($(hostname -i))\", \"Service\":\"$PAM_SERVICE\"}" echo $message | logger -t CarnivoreSSH fi
Skrypt zapisujemy w ścieżce /etc/ssh/carnivore.sh (z prawami chmod 650
). Zakładam tutaj, że dodaliśmy nasz system do Loggly. Jednak może to być inny dowolny endpoint akceptujący wiadomości w formacie json. Kolejnym krokiem jest wyzwolenie skryptu z poziomu PAM. Do /etc/pam.d/sshd dodajemy linijkę:
session optional pam_exec.so seteuid /etc/ssh/carnivore.sh
Od teraz po każdym logowaniu użytkownika w centrum logowania trafi wiadomość (możemy ją odfiltrować za pomocą: syslog.appName:CarnivoreSSH logtype:”json”):
syslog: severity: Notice appName: CarnivoreSSH timestamp: 2016-01-27T20:03:26.041619+01:00 facility: user-level messages priority: 13 host: darkstar json: Service: sshd Remotehost: 247.19.29.79.provider.isp.pl LoginHost: darkstar.nfsec.pl (2001:42d0:b:28d9::1 192.168.1.1) User: agresor EventReceivedTime: 2016-01-27 20:03:26
Analogicznie możemy wyzwolić zdarzenie logowania, gdy ktoś spróbuje wykonać polecenie “sudo” lub “su“. Wystarczy, że skrypt /usr/local/sbin/carnivore.sh:
#!/bin/bash if [ "$PAM_TYPE" != "close_session" ]; then message="{\"EventReceivedTime\":\"`date +'%Y-%m-%d %R:%S'`\", \"User\":\"$PAM_RUSER\", \"Host\":\"$(hostname -f) ($(hostname -i))\", \"Action\":\"$PAM_SERVICE\", \"TTY\":\"$PAM_TTY\"}" echo $message | logger -t CarnivoreSUDO fi
Dodamy do /etc/pam.d/sudo lub /etc/pam.d/su:
session optional pam_exec.so seteuid /usr/local/sbin/carnivore.sh
Zdarzenie będzie miało wówczas formę:
syslog: severity: Notice appName: CarnivoreSUDO timestamp: 2016-01-27T21:26:13.967908+01:00 facility: user-level messages priority: 13 host: darkstar json: Action: sudo TTY: /dev/pts/3 EventReceivedTime: 2016-01-27 21:26:13 Host: darkstar.nfsec.pl (2001:42d0:b:28d9::1 192.168.1.1) User: agresor
Za pomocą $PAM_TYPE
jesteśmy w stanie też sterować opuszczeniem stanu zalogowania lub uprzywilejowanego trybu. Tak zebrane wiadomości możemy poddawać dalszej analizie i ustawić odpowiednie alarmowanie w przypadku wystąpienia anomalii lub interesujących nas zdarzeń. Możemy też przechowywać je w zabezpieczonej i zarchiwizowanej formie w przypadku wystąpienia audytu, który wymagać będzie od nas tego typu informacji.
Więcej informacji: Login notifications, pam_exec scripting, Posting successful SSH logins to Slack