#!/bin/bash # Linux security monitoring Plugin for Pandora FMS # (c) Sancho Lerena 2016 # (c) Pandora FMS Team # info@pandorafms.com # This plugin is intended to run ONLY on modern Linux boxes # It's ready to run on 64 & 32 bits. It contains a custom build # of John the ripper 1.8 + Contrib patches with 32&64 static binaries. # # This plugin will check: # # 1. Check SSH on default port. # 2. Check FTP on default port. # 3. Check SSH to allow root access. # 4. Check if we have MySQL running. # 5. Check MySQL without root password (skipped if no MySQL detected). # 6. Check MySQL bind address. # 7. Check MySQL on default port if linstening on 0.0.0.0. # 8. Check if SELinux is enabled. # 9. Check /etc/shadow file integrity. # 10. Check /etc/passwd file integrity. # 11. Check /etc/hosts file integrity. # 12. Check /etc/resolv file integrity. # 13. Check /etc/ssh/sshd_config file integrity. # 14. Check /etc/rsyslog.conf file integrity. # 15. Check ssh keys on /home directory. # 16. Check ssh keys on /root directory. # 17. User password audit check, using dictionary (provided) with the # 500 most common used passwords. # Future versions of this plugin will increase the number of checks # providing a more advanced hardening monitoring. # Tested on Centos 6, Centos 7, Suse 13.2 # Change to plugin directory PLUGIN_DIR=`dirname "$0"` cd $PLUGIN_DIR # Detect if SSH is running on port 22 CHECK_22=`netstat -an | grep tcp | grep ":22 "` if [ -z "$CHECK_22" ] then echo "" echo "generic_proc" echo "SEC[ssh_port]" echo "1" echo "SSH not running on 22" echo "" else echo "" echo "generic_proc" echo "SEC[ssh_port]" echo "0" echo "SSH listening on port 22" echo "" fi # Detect if FTP is running on port 21 CHECK_21=`netstat -an | grep tcp | grep ":21 "` if [ -z "$CHECK_21" ] then echo "" echo "generic_proc" echo "SEC[ftp_port]" echo "1" echo "FTP not running on 21" echo "" else echo "" echo "generic_proc" echo "SEC[ftp_port]" echo "0" echo "FTP listening on port 21" echo "" fi # Detect if SSH doesnt allow to Root to connect CHECK_SSH_ROOT=`cat /etc/ssh/sshd_config | grep -E "^\s*PermitRootLogin"` if [ -z "$CHECK_SSH_ROOT" ] then echo "" echo "generic_proc" echo "SEC[ssh_allow_root]" echo "1" echo "SSH doesn't allow root to connect" echo "" else echo "" echo "generic_proc" echo "SEC[ssh_allow_root]" echo "0" echo "SSH does allow root to connect" echo "" fi # Detect if local Mysql is without password # First, do we have a running MySQL? CHECK_MYSQL=`netstat -an | grep LISTEN | grep ":3306 "` if [ ! -z "$CHECK_MYSQL" ] then CHECK_MYSQL_PASS=`echo "select 1234" | mysql -u root 2> /dev/null | grep 1234` if [ -z "$CHECK_MYSQL_PASS" ] then echo "" echo "generic_proc" echo "SEC[mysql_without_pass]" echo "1" echo "MySQL have a password" echo "" else echo "" echo "generic_proc" echo "SEC[mysql_without_pass]" echo "0" echo "MySQL do not have a password" echo "" fi CHECK_BIND=`netstat -natp | grep mysql | gawk '{print $4}'` if [[ "$CHECK_BIND" != *"::1:"* ]] && [[ "$CHECK_BIND" != *"127.0.0.1:"* ]] then echo "" echo "generic_proc" echo "SEC[mysql_bind]" echo "0" echo "MySQL bind-address insecure" echo "" CHECK_3306=`netstat -anp | grep mysql | grep ":3306 "` if [ ! -z "$CHECK_3306" ] then echo "" echo "generic_proc" echo "SEC[mysql_port]" echo "0" echo "MySQL listening on 3306" echo "" else echo "" echo "generic_proc" echo "SEC[mysql_port]" echo "1" echo "MySQL not listening on port 3306" echo "" fi else echo "" echo "generic_proc" echo "SEC[mysql_bind]" echo "1" echo "MySQL bind-address on localhost" echo "" fi fi # Check if SELinux is enabled CHECK_SELINUX=`sestatus | grep 'SELinux.*enabled'` if [ ! -z "$CHECK_SELINUX" ] then echo "" echo "generic_proc" echo "SEC[SELinux_status]" echo "1" echo "SELinux is enabled" echo "" else echo "" echo "generic_proc" echo "SEC[SELinux_status]" echo "0" echo "SELinux is disabled" echo "" fi # Check if /etc/shadow has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5shadow.md5 ] then MD5shaprev=`cat /tmp/md5shadow.md5` MD5shanow=`md5sum /etc/shadow` if [ "$MD5shaprev" == "$MD5shanow" ] then echo "" echo "generic_proc" echo "SEC[shadow_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[shadow_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/shadow > /tmp/md5shadow.md5 else md5sum /etc/shadow > /tmp/md5shadow.md5 echo "" echo "generic_proc" echo "SEC[shadow_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check if /etc/passwd has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5passwd.md5 ] then MD5pasprev=`cat /tmp/md5passwd.md5` MD5pasnow=`md5sum /etc/passwd` if [ "$MD5pasprev" == "$MD5pasnow" ] then echo "" echo "generic_proc" echo "SEC[passwd_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[passwd_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/passwd > /tmp/md5passwd.md5 else md5sum /etc/passwd > /tmp/md5passwd.md5 echo "" echo "generic_proc" echo "SEC[passwd_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check if /etc/hosts has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5hosts.md5 ] then MD5pasprev=`cat /tmp/md5hosts.md5` MD5pasnow=`md5sum /etc/hosts` if [ "$MD5hosprev" == "$MD5hosnow" ] then echo "" echo "generic_proc" echo "SEC[hosts_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[hosts_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/hosts > /tmp/md5hosts.md5 else md5sum /etc/hosts > /tmp/md5hosts.md5 echo "" echo "generic_proc" echo "SEC[hosts_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check if /etc/resolv.conf has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5resolv.md5 ] then MD5resprev=`cat /tmp/md5resolv.md5` MD5resnow=`md5sum /etc/resolv.conf` if [ "$MD5resprev" == "$MD5resnow" ] then echo "" echo "generic_proc" echo "SEC[resolv_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[resolv_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/resolv.conf > /tmp/md5resolv.md5 else md5sum /etc/resolv.conf > /tmp/md5resolv.md5 echo "" echo "generic_proc" echo "SEC[resolv_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check if /etc/ssh/sshd_config has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5ssh.md5 ] then MD5sshprev=`cat /tmp/md5ssh.md5` MD5sshnow=`md5sum /etc/ssh/sshd_config` if [ "$MD5sshprev" == "$MD5sshnow" ] then echo "" echo "generic_proc" echo "SEC[ssh_config_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[ssh_config_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/ssh/sshd_config > /tmp/md5ssh.md5 else md5sum /etc/ssh/sshd_config > /tmp/md5ssh.md5 echo "" echo "generic_proc" echo "SEC[ssh_config_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check if /etc/rsyslog.conf has been modified since last execution # First, check if there was a previous execution if [ -f /tmp/md5sys.md5 ] then MD5sysprev=`cat /tmp/md5sys.md5` MD5sysnow=`md5sum /etc/rsyslog.conf` if [ "$MD5sysprev" == "$MD5sysnow" ] then echo "" echo "generic_proc" echo "SEC[rsyslog_integrity]" echo "1" echo "md5 unchanged" echo "" else echo "" echo "generic_proc" echo "SEC[rsyslog_integrity]" echo "0" echo "md5 modified" echo "" fi # Update the md5 register file md5sum /etc/rsyslog.conf > /tmp/md5sys.md5 else md5sum /etc/rsyslog.conf > /tmp/md5sys.md5 echo "" echo "generic_proc" echo "SEC[rsyslog_integrity]" echo "1" echo "Creating md5 for the first time" echo "" fi # Check SSH keys on /home directorie CHECK_AKEYS=`find /home/ -name authorized_keys | wc -l` if [ "$CHECK_AKEYS" == 0 ] then echo "" echo "generic_data" echo "SEC[authorized_keys_/home]" echo "1" echo "0" echo "No authorized_keys found in /home" echo "" else echo "" echo "generic_data" echo "SEC[authorized_keys_/home]" echo "1" echo "$CHECK_AKEYS" echo "authorized_keys found in /home" echo "" fi # Check SSH keys on /root directories CHECK_RAKEYS=`find /root/.ssh -name authorized_keys | wc -l` if [ "$CHECK_RAKEYS" == 0 ] then echo "" echo "generic_data" echo "SEC[authorized_keys_/root]" echo "1" echo "0" echo "No authorized_keys found in /root" echo "" else echo "" echo "generic_data" echo "SEC[authorized_keys_/root]" echo "1" echo "$CHECK_RAKEYS" echo "authorized_keys found in /root" echo "" fi # Password audit # Check if exist a local John setup ERROR_CODE=`which john 2> /dev/null` if [ $? == 0 ] then JOHN=`which john` else ARCH=`uname -r | grep x86_64 | wc -l` if [ $ARCH == 1 ] then JOHN=./john_64 else JOHN=./john_32 fi fi # Check if valid john kit, if not, skip audit pass ERROR_CODE=`$JOHN 2> /dev/null ` if [ $? != 0 ] then echo "" echo "generic_proc" echo "SEC[password_audit]" echo "1" echo "Cannot perform the test due missing John tool" echo "WARNING" echo "" else rm john.pot 2> /dev/null rm /root/.john/john.pot 2> /dev/null RESULT=`$JOHN --wordlist=password-list /etc/shadow 2> /dev/null | grep -v "hashes with" | awk '{ print $2 }'` if [ -z "$RESULT" ] then echo "" echo "generic_proc" echo "SEC[password_audit]" echo "1" echo "All users OK" echo "" else RESULT_USER=`echo $RESULT | tr -d "()"` echo "" echo "generic_proc" echo "SEC[password_audit]" echo "0" echo "Weak password on users: $RESULT_USER" echo "" fi rm john.pot 2> /dev/null rm john.log 2> /dev/null fi exit 0