#!/bin/sh ################################################################################# # # Lynis # ------------------ # # Copyright 2007-2013, Michael Boelen # Copyright 2007-2021, CISOfy # # Website : https://cisofy.com # Blog : http://linux-audit.com # GitHub : https://github.com/CISOfy/lynis # # Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are # welcome to redistribute it under the terms of the GNU General Public License. # See LICENSE file for usage of this software. # ################################################################################# # ANSIBLE_ARTIFACT_FOUND=0 AUTOMATION_TOOL_FOUND=0 AUTOMATION_TOOL_RUNNING="" CFENGINE_AGENT_FOUND=0 CFENGINE_SERVER_RUNNING=0 BACKUP_AGENT_FOUND=0 PUPPET_MASTER_RUNNING=0 SALT_MASTER_RUNNING=0 SALT_MINION_RUNNING=0 IDS_IPS_TOOL_FOUND=0 FAIL2BAN_FOUND=0 FAIL2BAN_EMAIL=0 FAIL2BAN_SILENT=0 PERFORM_FAIL2BAN_TESTS=0 SNORT_FOUND=0 SNORT_RUNNING=0 # ################################################################################# # InsertSection "${SECTION_SYSTEM_TOOLING}" # ################################################################################# # # Automation # ################################################################################# # # Test : TOOL-5002 # Description : Check if automation tools are found Register --test-no TOOL-5002 --weight L --network NO --category security --description "Checking for automation tools" if [ ${SKIPTEST} -eq 0 ]; then Display --indent 2 --text "- Checking automation tooling" # Ansible FOUND=0 LIST="${HOME}/.ansible ${ROOTDIR}etc/ansible ${ROOTDIR}root/.ansible ${ROOTDIR}tmp/.ansible" for ITEM in ${LIST}; do if DirectoryExists ${ITEM}; then FOUND=1; break; fi; done # Test for files (only if no match was found) if [ ${FOUND} -eq 0 ]; then LIST="${ROOTDIR}var/log/ansible.log ~/.ansible-retry" for ITEM in ${LIST}; do if FileExists ${ITEM}; then FOUND=1; break; fi; done fi if [ ${FOUND} -eq 1 ]; then LogText "Result: found a possible trace of Ansible" AUTOMATION_TOOL_FOUND=1 ANSIBLE_ARTIFACT_FOUND=1 Report "automation_tool_running[]=ansible" Display --indent 4 --text "- Ansible artifact" --result "${STATUS_FOUND}" --color GREEN fi # Cfengine if [ -n "${CFAGENTBINARY}" ]; then LogText "Result: CFEngine (cfagent) is installed (${CFAGENTBINARY})" AUTOMATION_TOOL_FOUND=1 CFENGINE_AGENT_FOUND=1 Report "automation_tool_running[]=cf-agent" Display --indent 4 --text "- Cfengine (cfagent)" --result "${STATUS_FOUND}" --color GREEN fi OTHER_CFENGINE_LOCATIONS="/var/cfengine/bin /var/rudder/cfengine-community/bin" for I in ${OTHER_CFENGINE_LOCATIONS}; do if [ -d ${I} ]; then if [ -f ${I}/cf-agent ]; then LogText "Result: found CFEngine agent (cf-agent) in ${I}" AUTOMATION_TOOL_FOUND=1 CFENGINE_AGENT_FOUND=1 Report "automation_tool_running[]=cf-agent" Display --indent 4 --text "- CFEngine (cf-agent)" --result "${STATUS_FOUND}" --color GREEN fi if IsRunning "cf-server"; then LogText "Result: found CFEngine server" AUTOMATION_TOOL_FOUND=1 CFENGINE_SERVER_RUNNING=1 Report "automation_tool_running[]=cf-server" Display --indent 4 --text "- CFEngine (cf-server)" --result "${STATUS_FOUND}" --color GREEN fi fi done # Chef CHEF_LOCATIONS="/opt/chef/bin /opt/chef-server/sv /opt/chefdk/bin" for I in ${CHEF_LOCATIONS}; do if [ -d ${I} ]; then if [ -f ${I}/chef-client ]; then CHEFCLIENTBINARY="${I}/chef-client" AUTOMATION_TOOL_FOUND=1 Report "automation_tool_running[]=chef-client" Display --indent 4 --text "- Chef client (chef-client)" --result "${STATUS_FOUND}" --color GREEN LogText "Result: found chef-client (chef client daemon) in ${I}" fi if [ -f ${I}/erchef ]; then CHEFSERVERBINARY="${I}/erchef" LogText "Result: Chef Server (erchef) is installed (${CHEFSERVERBINARY})" AUTOMATION_TOOL_FOUND=1 Report "automation_tool_running[]=chef-server" Display --indent 4 --text "- Chef Server (erchef)" --result "${STATUS_FOUND}" --color GREEN LogText "Result: found erchef (chef server daemon) in ${I}" fi fi done # Puppet # Check for Puppet installation provided by Puppetlabs package if [ -z "${PUPPETBINARY}" ]; then if [ -f ${ROOTDIR}opt/puppetlabs/puppet/bin/puppet ]; then PUPPETBINARY="${ROOTDIR}opt/puppetlabs/puppet/bin/puppet" fi fi if [ -n "${PUPPETBINARY}" ]; then LogText "Result: Puppet is installed (${PUPPETBINARY})" AUTOMATION_TOOL_FOUND=1 Report "automation_tool_running[]=puppet-agent" Display --indent 4 --text "- Puppet (agent)" --result "${STATUS_FOUND}" --color GREEN fi if IsRunning --full "puppet master"; then LogText "Result: found puppet master" AUTOMATION_TOOL_FOUND=1 PUPPET_MASTER_RUNNING=1 Report "automation_tool_running[]=puppet-master" Display --indent 4 --text "- Puppet (master)" --result "${STATUS_FOUND}" --color GREEN fi # SaltStack if [ -n "${SALTMINIONBINARY}" ]; then Display --indent 4 --text "- SaltStack minion" --result "${STATUS_FOUND}" --color GREEN LogText "Result: SaltStack (salt-minion) is installed (${SALTMINIONBINARY})" AUTOMATION_TOOL_FOUND=1 Report "automation_tool_installed[]=saltstack-minion" if IsRunning "salt-minion" --user "root salt"; then Display --indent 6 --text "- Minion process" --result "${STATUS_RUNNING}" --color GREEN LogText "Result: found SaltStack (master)" SALT_MINION_RUNNING=1 Report "automation_tool_running[]=saltstack-minion" else Display --indent 6 --text "- Minion process" --result "${STATUS_NOT_RUNNING}" --color YELLOW fi fi if [ -n "${SALTMASTERBINARY}" ]; then Display --indent 4 --text "- SaltStack master (salt-master)" --result "${STATUS_FOUND}" --color GREEN LogText "Result: SaltStack (salt-master) is installed (${SALTMASTERBINARY})" AUTOMATION_TOOL_FOUND=1 Report "automation_tool_installed[]=saltstack-master" if IsRunning "salt-master" --user "root salt"; then Display --indent 6 --text "- Master process" --result "${STATUS_RUNNING}" --color GREEN LogText "Result: found SaltStack (master)" SALT_MASTER_RUNNING=1 Report "automation_tool_running[]=saltstack-master" else Display --indent 6 --text "- Master process" --result "${STATUS_NOT_RUNNING}" --color YELLOW fi fi if [ ${AUTOMATION_TOOL_FOUND} -eq 1 ]; then Display --indent 2 --text "- Automation tooling" --result "${STATUS_FOUND}" --color GREEN else Display --indent 2 --text "- Automation tooling" --result "${STATUS_NOT_FOUND}" --color YELLOW ReportSuggestion "${TEST_NO}" "Determine if automation tools are present for system management" fi fi # ################################################################################# # # Intrusion Detection and Prevention tools # ################################################################################# # # Test : TOOL-5102 # Description : Check for Fail2ban Register --test-no TOOL-5102 --weight L --network NO --category security --description "Check for presence of Fail2ban" if [ ${SKIPTEST} -eq 0 ]; then # Fail2ban presence if [ -n "${FAIL2BANBINARY}" ]; then FAIL2BAN_FOUND=1 IDS_IPS_TOOL_FOUND=1 LogText "Result: Fail2ban is installed (${FAIL2BANBINARY})" Report "ids_ips_tooling[]=fail2ban" Display --indent 2 --text "- Checking presence of Fail2ban" --result "${STATUS_FOUND}" --color GREEN else LogText "Result: Fail2ban not present (fail2ban-server not found)" fi # Fail2ban configuration LogText "Checking Fail2ban configuration file" if [ -f /etc/fail2ban/jail.local ]; then FAIL2BAN_CONFIG="/etc/fail2ban/jail.local" elif [ -f /etc/fail2ban/jail.conf ]; then FAIL2BAN_CONFIG="/etc/fail2ban/jail.conf" else FAIL2BAN_CONFIG="" fi # Continue if tooling is available and configuration file found if [ ${FAIL2BAN_FOUND} -eq 1 -a -n "${FAIL2BAN_CONFIG}" ]; then Report "fail2ban_config=${FAIL2BAN_CONFIG}" FAIL2BANCLIENT=$(which fail2ban-client 2> /dev/null | grep -v "no [^ ]* in ") if [ -n "${FAIL2BANCLIENT}" ]; then PERFORM_FAIL2BAN_TESTS=1; fi fi fi # ################################################################################# # # Test : TOOL-5104 # Description : Check for Fail2ban enabled tests if [ ${PERFORM_FAIL2BAN_TESTS} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no TOOL-5104 --weight L --network NO --preqs-met ${PREQS_MET} --category security --description "Enabled tests in Fail2ban" if [ ${SKIPTEST} -eq 0 ]; then FIND=$(${FAIL2BANCLIENT} -d | ${TRBINARY} -d '[]' | ${TRBINARY} -d "'" | ${AWKBINARY} -F, '{ if ($1=="add") { print $2 }}' | ${TRBINARY} -d ' ') if [ -n "${FIND}" ]; then for F2BSERVICE in ${FIND}; do LogText "Result: service '${F2BSERVICE}' enabled" Report "fail2ban_enabled_service[]=${F2BSERVICE}" done LogText "Result: found at least one enabled jail" Display --indent 4 --text "- Checking Fail2ban jails" --result "${STATUS_ENABLED}" --color GREEN AddHP 3 3 else LogText "Result: Fail2ban installed but completely disabled" Display --indent 4 --text "- Checking Fail2ban jails" --result "${STATUS_DISABLED}" --color RED AddHP 0 5 ReportWarning "${TEST_NO}" "All jails in Fail2ban are disabled" "${FAIL2BAN_CONFIG}" fi fi # ################################################################################# # # These tests are temporarily disabled to split them up in different areas to check # # LogText "Result: found configuration file (${FAIL2BAN_CONFIG})" # # # Check email alert configuration # LogText "Test: checking for email actions within ${FAIL2BAN_CONFIG}" # # FIND=$(${GREPBINARY} -E "^action = \%\(action_m.*\)s" ${FAIL2BAN_CONFIG}) # FIND2=$(${GREPBINARY} -E "^action = \%\(action_\)s" ${FAIL2BAN_CONFIG}) # # if [ -n "${FIND}" ]; then # FAIL2BAN_EMAIL=1 # LogText "Result: found at least one jail which sends an email alert" # fi # # if [ -n "${FIND2}" ]; then # FAIL2BAN_SILENT=1 # LogText "Result: found at least one jail which does NOT send an email alert" # fi # # if [ ${FAIL2BAN_SILENT} -eq 0 ] && [ ${FAIL2BAN_EMAIL} -eq 0 ]; then # LogText "No registered actions found in ${FAIL2BAN_CONFIG}" # Display --indent 4 --text "- Checking Fail2ban actions" --result "${STATUS_NONE}" --color RED # ReportWarning "${TEST_NO}" "${FAIL2BAN_CONFIG}" "There are no actions configured for Fail2ban." # AddHP 0 3 # fi # # if [ ${FAIL2BAN_SILENT} -eq 0 ] && [ ${FAIL2BAN_EMAIL} -eq 1 ]; then # LogText "All actions in ${FAIL2BAN_CONFIG} are configured to send email alerts" # Display --indent 4 --text "- Checking Fail2ban actions" --result "${STATUS_OK}" --color GREEN # AddHP 3 3 # fi # # if [ ${FAIL2BAN_SILENT} -eq 1 ] && [ ${FAIL2BAN_EMAIL} -eq 1 ]; then # LogText "Some actions found in ${FAIL2BAN_CONFIG} are configured to send email alerts" # Display --indent 4 --text "- Checking Fail2ban actions" --result PARTIAL --color YELLOW # ReportSuggestion "${TEST_NO}" "Some Fail2ban jails are configured with non-notified actions. Consider changing these to emailed alerts." # AddHP 2 3 # fi # # if [ ${FAIL2BAN_SILENT} -eq 1 ] && [ ${FAIL2BAN_EMAIL} -eq 0 ]; then # LogText "None of the actions found in ${FAIL2BAN_CONFIG} are configured to send email alerts" # Display --indent 4 --text "- Checking Fail2ban actions" --result "${STATUS_NONE}" --color YELLOW # ReportSuggestion "${TEST_NO}" "None of the Fail2ban jails are configured to send email notifications. Consider changing these to emailed alerts." # AddHP 1 3 # fi # # # Check at least one enabled jail # LogText "Checking for enabled jails within ${FAIL2BAN_CONFIG}" # # # # # Confirm at least one iptables chain for fail2ban # # LogText "Checking for fail2ban iptables chains" # # if [ -n "${IPTABLESBINARY}" ]; then # CHECK_CHAINS=$(${IPTABLESBINARY} -L 2>&1 | ${GREPBINARY} fail2ban) # if [ -n "${CHECK_CHAINS}" ]; then # LogText "Result: found at least one iptables chain for fail2ban" # Display --indent 4 --text "- Checking for Fail2ban iptables chain" --result "${STATUS_OK}" --color GREEN # else # LogText "Result: Fail2ban installed but iptables chain not present - fail2ban will not work" # Display --indent 4 --text "- Checking for Fail2ban iptables chain" --result "${STATUS_WARNING}" --color RED # AddHP 0 3 # ReportSuggestion "${TEST_NO}" "Check config to see why iptables does not have a fail2ban chain" "${FAIL2BAN_CONFIG}" # fi # else # Display --indent 4 --text "- Checking for Fail2ban iptables chain" --result "${STATUS_WARNING}" --color RED # ReportSuggestion "${TEST_NO}" "iptables doesn't seem to be installed; Fail2ban will not work. Remove Fail2ban or install iptables" "${FAIL2BAN_CONFIG}" # fi # fi # fi # ################################################################################# # # Test : TOOL-5120 # Description : Check for Snort Register --test-no TOOL-5120 --weight L --network NO --category security --description "Check for presence of Snort" if [ ${SKIPTEST} -eq 0 ]; then # Snort presence if [ -n "${SNORTBINARY}" ]; then SNORT_FOUND=1 IDS_IPS_TOOL_FOUND=1 LogText "Result: Snort is installed (${SNORTBINARY})" Report "ids_ips_tooling[]=snort" Display --indent 2 --text "- Checking presence of Snort" --result "${STATUS_FOUND}" --color GREEN fi if IsRunning "snort"; then SNORT_FOUND=1 SNORT_RUNNING=1 SNORT_LOG=$(${PSBINARY} | ${AWKBINARY} -F-.. '/snort/ {print $4}' | ${HEADBINARY} -1) else LogText "Result: Snort not present (Snort not running)" fi fi # ################################################################################# # # Test : TOOL-5122 # Description : Check for Snort configuration Register --test-no TOOL-5122 --weight L --network NO --category security --description "Check Snort configuration file" if [ ${SKIPTEST} -eq 0 ]; then # Continue if tooling is available and snort is running if [ -n "${SNORT_FOUND}" ] || [ -n "${SNORT_RUNNING}" ]; then if [ ${SNORT_FOUND} -eq 1 ] && [ ${SNORT_RUNNING} -eq 1 ]; then SNORT_CONFIG=$(${PSBINARY} | ${AWKBINARY} -F-.. '/snort/ {print $3}' | ${HEADBINARY} -1) if HasData "${SNORT_CONFIG}"; then LogText "Result: found Snort configuration file: ${SNORT_CONFIG}" Report "snort_config=${SNORT_CONFIG}" fi SNORT=$(which snort 2> /dev/null) fi fi fi # ################################################################################# # # Test : TOOL-5130 # Description : Check for Suricata Register --test-no TOOL-5130 --weight L --network NO --category security --description "Check for active Suricata daemon" if [ ${SKIPTEST} -eq 0 ]; then # Suricata presence if [ -n "${SURICATABINARY}" ]; then Report "ids_ips_tooling[]=suricata" LogText "Result: Suricata is installed (${SURICATABINARY})" # Suricata status # Suricata sets its process name to Suricata-Main on Linux, but this might differ on other platforms, # so fall back to checking the full commandline instead if the first test fails if IsRunning "Suricata-Main" || IsRunning --full "${SURICATABINARY} "; then # Only satisfy test TOOL-5190 if Suricata is actually running IDS_IPS_TOOL_FOUND=1 LogText "Result: Suricata daemon is active" Display --indent 2 --text "- Checking Suricata status" --result "${STATUS_RUNNING}" --color GREEN else LogText "Result: Suricata daemon not active" Display --indent 2 --text "- Checking Suricata status" --result "${STATUS_NOT_RUNNING}" --color YELLOW fi else LogText "Result: Suricata not installed (suricata not found)" fi fi # ################################################################################# # # Test : TOOL-5126 # Description : Check for OSSEC Register --test-no TOOL-5126 --weight L --network NO --category security --description "Check for active OSSEC daemon" if [ ${SKIPTEST} -eq 0 ]; then # Server side if IsRunning "ossec-analysisd"; then IDS_IPS_TOOL_FOUND=1 Report "ids_ips_tooling[]=ossec" Report "ids_ips_tooling[]=ossec-analysisd" LogText "Result: OSSEC analysis daemon is active" Display --indent 2 --text "- Checking presence of OSSEC (analysis)" --result "${STATUS_FOUND}" --color GREEN else LogText "Result: OSSEC analysis daemon not active" fi # Client side if IsRunning "ossec-agentd"; then IDS_IPS_TOOL_FOUND=1 Report "ids_ips_tooling[]=ossec" Report "ids_ips_tooling[]=ossec-agentd" LogText "Result: OSSEC agent daemon is active" Display --indent 2 --text "- Checking presence of OSSEC (agent)" --result "${STATUS_FOUND}" --color GREEN else LogText "Result: OSSEC agent daemon not active" fi fi # ################################################################################# # # Test : TOOL-5128 # Description : Check for Wazuh daemon Register --test-no TOOL-5128 --weight L --network NO --category security --description "Check for active Wazuh daemon" if [ ${SKIPTEST} -eq 0 ]; then # Server side if IsRunning "wazuh-analysisd"; then IDS_IPS_TOOL_FOUND=1 Report "ids_ips_tooling[]=wazuh" Report "ids_ips_tooling[]=wazuh-analysisd" LogText "Result: Wazuh analysis daemon is active" Display --indent 2 --text "- Checking presence of Wazuh (analysis)" --result "${STATUS_FOUND}" --color GREEN else LogText "Result: Wazuh analysis daemon not active" fi # Client side if IsRunning "wazuh-agentd"; then IDS_IPS_TOOL_FOUND=1 Report "ids_ips_tooling[]=wazuh" Report "ids_ips_tooling[]=wazuh-agentd" LogText "Result: Wazuh agent daemon is active" Display --indent 2 --text "- Checking presence of Wazuh (agent)" --result "${STATUS_FOUND}" --color GREEN else LogText "Result: Wazuh agent daemon not active" fi fi # ################################################################################# # # Test : TOOL-5190 # Description : Check for an IDS/IPS tool Register --test-no TOOL-5190 --weight L --network NO --category security --description "Check presence of IDS/IPS tool" if [ ${SKIPTEST} -eq 0 ]; then if [ ${IDS_IPS_TOOL_FOUND} -eq 1 ]; then Display --indent 2 --text "- Checking for IDS/IPS tooling" --result "${STATUS_FOUND}" --color GREEN AddHP 2 2 else Display --indent 2 --text "- Checking for IDS/IPS tooling" --result "${STATUS_NONE}" --color YELLOW #ReportSuggestion "${TEST_NO}" "Install and configure automated intrusion detection/prevention tools" AddHP 0 2 fi fi # ################################################################################# # # Backup tools # ################################################################################# # # Netvault # Rsync in cron # ################################################################################# # Report "automation_tool_present=${AUTOMATION_TOOL_FOUND}" WaitForKeyPress # #================================================================================ # Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com