pandorafms/pandora_plugins/basic_security/basic_security_v2

498 lines
17 KiB
Bash
Executable File

#!/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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_port]</name>"
echo "<data>1</data>"
echo "<description>SSH not running on 22</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_port]</name>"
echo "<data>0</data>"
echo "<description>SSH listening on port 22</description>"
echo "</module>"
fi
# Detect if FTP is running on port 21
CHECK_21=`netstat -an | grep tcp | grep ":21 "`
if [ -z "$CHECK_21" ]
then
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ftp_port]</name>"
echo "<data>1</data>"
echo "<description>FTP not running on 21</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ftp_port]</name>"
echo "<data>0</data>"
echo "<description>FTP listening on port 21</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_allow_root]</name>"
echo "<data>1</data>"
echo "<description>SSH doesn't allow root to connect</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_allow_root]</name>"
echo "<data>0</data>"
echo "<description>SSH does allow root to connect</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_without_pass]</name>"
echo "<data>1</data>"
echo "<description>MySQL have a password</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_without_pass]</name>"
echo "<data>0</data>"
echo "<description>MySQL do not have a password</description>"
echo "</module>"
fi
CHECK_BIND=`netstat -natp | grep mysql | gawk '{print $4}'`
if [[ "$CHECK_BIND" != *"::1:"* ]] && [[ "$CHECK_BIND" != *"127.0.0.1:"* ]]
then
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_bind]</name>"
echo "<data>0</data>"
echo "<description>MySQL bind-address insecure</description>"
echo "</module>"
CHECK_3306=`netstat -anp | grep mysql | grep ":3306 "`
if [ ! -z "$CHECK_3306" ]
then
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_port]</name>"
echo "<data>0</data>"
echo "<description>MySQL listening on 3306</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_port]</name>"
echo "<data>1</data>"
echo "<description>MySQL not listening on port 3306</description>"
echo "</module>"
fi
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[mysql_bind]</name>"
echo "<data>1</data>"
echo "<description>MySQL bind-address on localhost</description>"
echo "</module>"
fi
fi
# Check if SELinux is enabled
CHECK_SELINUX=`sestatus | grep 'SELinux.*enabled'`
if [ ! -z "$CHECK_SELINUX" ]
then
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[SELinux_status]</name>"
echo "<data>1</data>"
echo "<description>SELinux is enabled</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[SELinux_status]</name>"
echo "<data>0</data>"
echo "<description>SELinux is disabled</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[shadow_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[shadow_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/shadow > /tmp/md5shadow.md5
else
md5sum /etc/shadow > /tmp/md5shadow.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[shadow_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[passwd_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[passwd_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/passwd > /tmp/md5passwd.md5
else
md5sum /etc/passwd > /tmp/md5passwd.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[passwd_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[hosts_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[hosts_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/hosts > /tmp/md5hosts.md5
else
md5sum /etc/hosts > /tmp/md5hosts.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[hosts_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[resolv_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[resolv_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/resolv.conf > /tmp/md5resolv.md5
else
md5sum /etc/resolv.conf > /tmp/md5resolv.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[resolv_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_config_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_config_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/ssh/sshd_config > /tmp/md5ssh.md5
else
md5sum /etc/ssh/sshd_config > /tmp/md5ssh.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[ssh_config_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[rsyslog_integrity]</name>"
echo "<data>1</data>"
echo "<description>md5 unchanged</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[rsyslog_integrity]</name>"
echo "<data>0</data>"
echo "<description>md5 modified</description>"
echo "</module>"
fi
# Update the md5 register file
md5sum /etc/rsyslog.conf > /tmp/md5sys.md5
else
md5sum /etc/rsyslog.conf > /tmp/md5sys.md5
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[rsyslog_integrity]</name>"
echo "<data>1</data>"
echo "<description>Creating md5 for the first time</description>"
echo "</module>"
fi
# Check SSH keys on /home directorie
CHECK_AKEYS=`find /home/ -name authorized_keys | wc -l`
if [ "$CHECK_AKEYS" == 0 ]
then
echo "<module>"
echo "<type>generic_data</type>"
echo "<name>SEC[authorized_keys_/home]</name>"
echo "<min_critical>1</min_critical>"
echo "<data>0</data>"
echo "<description>No authorized_keys found in /home</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_data</type>"
echo "<name>SEC[authorized_keys_/home]</name>"
echo "<min_critical>1</min_critical>"
echo "<data>$CHECK_AKEYS</data>"
echo "<description>authorized_keys found in /home</description>"
echo "</module>"
fi
# Check SSH keys on /root directories
CHECK_RAKEYS=`find /root/.ssh -name authorized_keys | wc -l`
if [ "$CHECK_RAKEYS" == 0 ]
then
echo "<module>"
echo "<type>generic_data</type>"
echo "<name>SEC[authorized_keys_/root]</name>"
echo "<min_critical>1</min_critical>"
echo "<data>0</data>"
echo "<description>No authorized_keys found in /root</description>"
echo "</module>"
else
echo "<module>"
echo "<type>generic_data</type>"
echo "<name>SEC[authorized_keys_/root]</name>"
echo "<min_critical>1</min_critical>"
echo "<data>$CHECK_RAKEYS</data>"
echo "<description>authorized_keys found in /root</description>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[password_audit]</name>"
echo "<data>1</data>"
echo "<description>Cannot perform the test due missing John tool</description>"
echo "<status>WARNING</status>"
echo "</module>"
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 "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[password_audit]</name>"
echo "<data>1</data>"
echo "<description>All users OK</description>"
echo "</module>"
else
RESULT_USER=`echo $RESULT | tr -d "()"`
echo "<module>"
echo "<type>generic_proc</type>"
echo "<name>SEC[password_audit]</name>"
echo "<data>0</data>"
echo "<description>Weak password on users: $RESULT_USER</description>"
echo "</module>"
fi
rm john.pot 2> /dev/null
rm john.log 2> /dev/null
fi
exit 0