lynis/include/tests_firewalls

471 lines
24 KiB
Bash

#!/bin/sh
#################################################################################
#
# Lynis
# ------------------
#
# Copyright 2007-2013, Michael Boelen
# Copyright 2013-2016, 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.
#
#################################################################################
#
# Firewalls
#
#################################################################################
#
InsertSection "Software: firewalls"
#
#################################################################################
#
IPTABLES_ACTIVE=0
IPTABLES_INKERNEL_ACTIVE=0
IPTABLES_MODULE_ACTIVE=0
FIREWALL_ACTIVE=0
FIREWALL_EMPTY_RULESET=0
FIREWALL_SOFTWARE=""
NFTABLES_ACTIVE=0
#
#################################################################################
#
# Test : FIRE-4502
# Description : Check iptables kernel module
Register --test-no FIRE-4502 --os Linux --weight L --network NO --category security --description "Check iptables kernel module"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${LSMODBINARY} | ${AWKBINARY} '{ print $1 }' | ${GREPBINARY} "^ip*_tables")
if [ ! -z "${FIND}" ]; then
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="iptables"
IPTABLES_ACTIVE=1
IPTABLES_MODULE_ACTIVE=1
Display --indent 2 --text "- Checking iptables kernel module" --result "${STATUS_FOUND}" --color GREEN
LogText "Result: Found iptables in loaded kernel modules"
for I in ${FIND}; do
LogText "Found module: ${I}"
done
else
Display --indent 2 --text "- Checking iptables kernel module" --result "${STATUS_NOT_FOUND}" --color WHITE
# If we can't find an active module, try to find the Linux configuration file and check that
if [ -f /proc/config.gz ]; then
LINUXCONFIGFILE="/proc/config.gz"; tCATCMD="zcat";
fi
sLINUXCONFIGFILE="/boot/config-$(uname -r)"
if [ -f ${sLINUXCONFIGFILE} ]; then
LINUXCONFIGFILE=${sLINUXCONFIGFILE}; tCATCMD="cat";
fi
# If we have a kernel configuration file, use it for testing
# Do not perform test if we already found it in kernel module list, to avoid triggered it in the upcoming
# tests, when using iptables --list
if [ ! "${LINUXCONFIGFILE}" = "" ]; then
if [ -f ${LINUXCONFIGFILE} -a ${IPTABLES_MODULE_ACTIVE} -eq 0 ]; then
LogText "Result: found kernel configuration file (${LINUXCONFIGFILE})"
FIND=$(${tCATCMD} ${LINUXCONFIGFILE} | ${GREPBINARY} -v '^#' | ${GREPBINARY} "CONFIG_IP_NF_IPTABLES" | head -n 1)
if [ ! -z "${FIND}" ]; then
HAVEMOD=$(echo ${FIND} | ${CUTBINARY} -d '=' -f2)
# Do not use iptables if it's compiled as a module (=m), since we already tested for it in the
# active list.
if [ "${HAVEMOD}" = "y" ]; then
LogText "Result: iptables available as a module in the configuration"
IPTABLES_ACTIVE=1
IPTABLES_INKERNEL_ACTIVE=1
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="iptables"
Display --indent 2 --text "- Checking iptables in config file" --result "${STATUS_FOUND}" --color GREEN
else
LogText "Result: no iptables found in Linux kernel config file"
fi
else
LogText "Result: no Linux configuration file found"
Display --indent 2 --text "- Checking iptables in config file" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
fi
fi
fi
if [ ${IPTABLES_ACTIVE} -eq 1 ]; then Report "firewall_software[]=iptables"; fi
fi
#
#################################################################################
#
# Test : FIRE-4508
# Description : Check iptables chain policies
# Notes : Suggestions are currently disabled, until related page and documentation is available
if [ ! "${IPTABLESBINARY}" = "" -a ${IPTABLES_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4508 --preqs-met ${PREQS_MET} --os Linux --weight L --network NO --root-only YES --category security --description "Check used policies of iptables chains"
if [ ${SKIPTEST} -eq 0 ]; then
Display --indent 4 --text "- Checking iptables policies of chains" --result "${STATUS_FOUND}" --color GREEN
TABLES="filter"
for TABLE in ${TABLES}; do
LogText "Test: gathering information from table ${TABLE}"
FIND="$FIND""\n"`${IPTABLESBINARY} -t ${TABLE} --numeric --list | ${EGREPBINARY} -z -o -w '[A-Z]+' | ${AWKBINARY} -v t=${TABLE} 'NR%2 {printf "%s %s ",t, $0 ; next;}1'`
done
echo "${FIND}" | while read line; do
table=$(echo ${line} | ${AWKBINARY} '{ print $1 }')
chainname=$(echo ${line} | ${AWKBINARY} '{ print $2 }')
policy=$(echo ${line} | ${AWKBINARY} '{ print $3 }')
LogText "Result: iptables ${table} -- ${chainname} policy is ${policy}."
LogText "Result: ${policy}"
if [ "${TABLE}" = "filter" ]; then
if [ "${chainname}" = "INPUT" ]; then
case ${policy} in
"ACCEPT")
LogText "Result: Found ACCEPT for ${chainname} (table: ${table})"
Display --indent 6 --text "- Checking chain ${chainname} (table: ${table}) policy" --result ${policy} --color YELLOW
#ReportSuggestion ${TEST_NO} "Consider settings default chain policy to DROP (iptables chain ${chainname}, table: ${table})"
AddHP 1 3
;;
"DROP")
LogText "Result: Found DROP for ${chainname} (table: ${table})"
Display --indent 6 --text "- Checking chain ${chainname} (table: ${table}) policy" --result ${policy} --color GREEN
AddHP 3 3
;;
*)
Display --indent 6 --text "- Checking chain ${chainname} (table: ${table}) policy" --result ${policy} --color YELLOW
LogText "Result: Unknown policy: ${policy}"
#ReportSuggestion ${TEST_NO} "Check iptables ${chainname} (table: ${table}) chain policy"
;;
esac
fi
fi
done
fi
#
#################################################################################
#
# Test : FIRE-4512
# Description : Check iptables for empty ruleset (should have at least 10 or more rules)
if [ ! "${IPTABLESBINARY}" = "" -a ${IPTABLES_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4512 --preqs-met ${PREQS_MET} --os Linux --weight L --network NO --root-only YES --category security --description "Check iptables for empty ruleset"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${IPTABLESBINARY} --list --numeric 2> /dev/null | ${EGREPBINARY} -v "^(Chain|target|$)" | ${WCBINARY} -l | ${TRBINARY} -d ' ')
if [ ! -z "${FIND}" ]; then
FIREWALL_ACTIVE=1
if [ ${FIND} -le 10 ]; then
# Firewall is active, but clearly needs configuration
FIREWALL_EMPTY_RULESET=1
LogText "Result: iptables ruleset seems to be empty (found ${FIND} rules)"
Display --indent 4 --text "- Checking for empty ruleset" --result "${STATUS_WARNING}" --color RED
ReportWarning ${TEST_NO} "iptables module(s) loaded, but no rules active"
else
LogText "Result: one or more rules are available (${FIND} rules)"
Display --indent 4 --text "- Checking for empty ruleset" --result "${STATUS_OK}" --color GREEN
fi
fi
fi
#
#################################################################################
#
# Test : FIRE-4513
# Description : Check iptables for unused rules
if [ ! -z "${IPTABLESBINARY}" -a ${IPTABLES_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4513 --preqs-met ${PREQS_MET} --os Linux --weight L --network NO --root-only YES --category security --description "Check iptables for unused rules"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${IPTABLESBINARY} --list --numeric --line-numbers --verbose | ${AWKBINARY} '{ if ($2=="0") print $1 }' | ${XARGSBINARY})
if [ -z "${FIND}" ]; then
Display --indent 4 --text "- Checking for unused rules" --result "${STATUS_OK}" --color GREEN
LogText "Result: There are no unused rules present"
else
Display --indent 4 --text "- Checking for unused rules" --result "${STATUS_FOUND}" --color YELLOW
LogText "Result: Found one or more possible unused rules"
LogText "Description: Unused rules can be a sign that the firewall rules aren't optimized or up-to-date"
LogText "Note: Sometimes rules aren't triggered but still in use. Keep this in mind before cleaning up rules."
LogText "Output: iptables rule numbers: ${FIND}"
ReportSuggestion ${TEST_NO} "Check iptables rules to see which rules are currently not used"
LogText "Tip: iptables --list --numeric --line-numbers --verbose"
fi
fi
#
#################################################################################
#
# Test : FIRE-4518
# Description : Checking status of pf firewall components
Register --test-no FIRE-4518 --weight L --network NO --category security --description "Check pf firewall components"
if [ ${SKIPTEST} -eq 0 ]; then
PFFOUND=0; PFLOGDFOUND=0
# Check status with pfctl
LogText "Test: checking pf status via pfctl"
if [ ! -z "${PFCTLBINARY}" ]; then
FIND=$(${PFCTLBINARY} -sa 2>&1 | ${GREPBINARY} "^Status" | ${HEADBINARY} -1 | ${AWKBINARY} '{ print $2 }')
if [ "${FIND}" = "Enabled" ]; then
Display --indent 2 --text "- Checking pf status (pfctl)" --result "${STATUS_ENABLED}" --color GREEN
LogText "Result: pf is enabled"
PFFOUND=1
AddHP 3 3
else
if [ "${FIND}" = "Disabled" ]; then
Display --indent 2 --text "- Checking pf status (pfctl)" --result "${STATUS_DISABLED}" --color RED
LogText "Result: pf is disabled"
AddHP 0 3
else
Display --indent 2 --text "- Checking pf status (pfctl)" --result "${STATUS_UNKNOWN}" --color YELLOW
ReportException ${TEST_NO} "Unknown status of pf firewall"
fi
fi
fi
# If we didn't find the status to be enabled, stop searching
if [ ${PFFOUND} -eq 0 ]; then
# Check for pf kernel module (FreeBSD and similar)
LogText "Test: searching for pf kernel module"
if [ ! -z "${KLDSTATBINARY}" ]; then
FIND=$(${KLDSTATBINARY} | ${GREPBINARY} 'pf.ko')
if [ -z "${FIND}" ]; then
LogText "Result: Can not find pf KLD"
else
LogText "Result: pf KLD loaded"
PFFOUND=1
fi
else
LogText "Result: no kldstat binary, skipping this part"
fi
IsRunning pflogd
if [ ${RUNNING} -eq 1 ]; then
LogText "Result: found pflog daemon in process list"
Display --indent 4 --text "- Checking pflogd status" --result "ACTIVE" --color GREEN
PFFOUND=1
PFLOGDFOUND=1
else
LogText "Result: pflog daemon not found in process list"
fi
fi
if [ ${PFFOUND} -eq 1 ]; then
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="pf"
Report "firewall_software[]=pf"
else
LogText "Result: pf not running on this system"
fi
fi
#
#################################################################################
#
# Test : FIRE-4520
# Description : Check pf configuration consistency
if [ ${PFFOUND} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4520 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check pf configuration consistency"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: check /etc/pf.conf"
# Test for warnings (-n don't load the rules)
if [ -f /etc/pf.conf ]; then
LogText "Result: /etc/pf.conf exists"
# Check results from pfctl
PFWARNINGS=$(${PFCTLBINARY} -n -f /etc/pf.conf -vvv 2>&1 | ${GREPBINARY} -i 'warning')
if [ -z "${PFWARNINGS}" ]; then
Display --indent 4 --text "- Checking pf configuration consistency" --result "${STATUS_OK}" --color GREEN
LogText "Result: no pf filter warnings found"
else
Display --indent 4 --text "- Checking pf configuration consistency" --result "${STATUS_WARNING}" --color RED
LogText "Result: found one or more warnings in the pf filter rules"
ReportWarning ${TEST_NO} "Found one or more warnings in pf configuration file" "/etc/pf.conf" "text:Run 'pfctl -n -f /etc/pf.conf -vvv' to see available pf warnings"
fi
else
LogText "Result: /etc/pf.conf does NOT exist"
fi
fi
#
#################################################################################
#
# Test : FIRE-4522
# Description : Check ipchains
#
#################################################################################
#
# Test : FIRE-4524
# Description : Check for CSF (ConfigServer Security & Firewall)
Register --test-no FIRE-4524 --weight L --network NO --category security --description "Check for CSF presence"
if [ ${SKIPTEST} -eq 0 ]; then
FILE="/etc/csf/csf.conf"
LogText "Test: check ${FILE}"
if [ -f ${FILE} ]; then
LogText "Result: ${FILE} exists"
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="csf"
Report "firewall_software[]=csf"
Display --indent 2 --text "- Checking CSF status (configuration file)" --result "${STATUS_FOUND}" --color GREEN
else
LogText "Result: ${FILE} does NOT exist"
fi
fi
#
#################################################################################
#
# Test : FIRE-4526
# Description : Check ipf (Solaris)
if [ ! "${IPFBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4526 --os Solaris --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check ipf status"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${IPFBINARY} -n -V | ${GREPBINARY} "^Running" | ${AWKBINARY} '{ print $2 }')
if [ "${FIND}" = "yes" ]; then
Display --indent 4 --text "- Checking ipf status" --result "${STATUS_RUNNING}" --color GREEN
LogText "Result: ipf is enabled and running"
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="ipf"
Report "firewall_software[]=ipf"
else
Display --indent 4 --text "- Checking ipf status" --result "${STATUS_NOT_RUNNING}" --color YELLOW
LogText "Result: ipf is not running"
fi
fi
#
#################################################################################
#
# Test : FIRE-4530
# Description : Check IPFW (FreeBSD)
Register --test-no FIRE-4530 --os FreeBSD --weight L --network NO --category security --description "Check IPFW status"
if [ ${SKIPTEST} -eq 0 ]; then
if [ ! -z "${SYSCTLBINARY}" ]; then
# For now, only check for IPv4.
FIND=$(${SYSCTLBINARY} net.inet.ip.fw.enable | ${AWKBINARY} '{ print $2 }')
if [ "${FIND}" = "1" ]; then
Display --indent 2 --text "- Checking IPFW status" --result "${STATUS_RUNNING}" --color GREEN
LogText "Result: IPFW is running for IPv4"
FIREWALL_ACTIVE=1
FIREWALL_SOFTWARE="ipfw"
Report "firewall_software[]=ipfw"
IPFW_ENABLED=`service -e | ${GREPBINARY} -o ipfw`
if [ "${IPFW_ENABLED}" = "ipfw" ]; then
Display --indent 4 --text "- IPFW enabled in /etc/rc.conf" --result "${STATUS_YES}" --color GREEN
LogText "Result: IPFW is enabled at start-up for IPv4"
else
Display --indent 4 --text "- ipfw enabled in /etc/rc.conf" --result "${STATUS_NO}" --color YELLOW
LogText "Result: IPFW is disabled at start-up for IPv4"
fi
else
Display --indent 2 --text "- Checking IPFW status" --result "${STATUS_NOT_RUNNING}" --color YELLOW
LogText "Result: IPFW is not running for IPv4"
fi
else
Display --indent 2 --text "- Checking IPFW" --result "${STATUS_SKIPPED}" --color YELLOW
ReportException "${TEST_NO}:1" "No IPFW test available (sysctl missing)"
fi
fi
#
#################################################################################
#
# Test : FIRE-4532
# Description : Check Application Firewall in Mac OS X
if [ -x /usr/libexec/ApplicationFirewall/socketfilterfw ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4532 --weight L --os "MacOS" --preqs-met ${PREQS_MET} --network NO --category security --description "Check Mac OS X application firewall"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2> /dev/null | ${GREPBINARY} "Firewall is enabled")
if [ ! -z "${FIND}" ]; then
Display --indent 2 --text "- Checking Mac OS X: Application Firewall" --result "${STATUS_ENABLED}" --color GREEN
AddHP 3 3
LogText "Result: application firewall of Mac OS X is enabled"
APPLICATION_FIREWALL_ACTIVE=1
Report "app_fw[]=macosx-app-fw"
else
Display --indent 2 --text "- Checking IPFW" --result "${STATUS_DISABLED}" --color YELLOW
AddHP 1 3
LogText "Result: application firewall of Mac OS X is disabled"
fi
fi
#
#################################################################################
#
# Test : FIRE-4536
# Description : Check nftables kernel module
if [ ! "${NFTBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4536 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check nftables status"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${LSMODBINARY} | ${AWKBINARY} '{ print $1 }' | ${GREPBINARY} "^nf*_tables")
if [ ! -z "${FIND}" ]; then
LogText "Result: found nftables kernel module"
FIREWALL_SOFTWARE="nftables"
FIREWALL_ACTIVE=1
NFTABLES_ACTIVE=1
Report "firewall_software[]=nftables"
else
LogText "Result: no nftables kernel module found"
fi
fi
#
#################################################################################
#
# Test : FIRE-4538
# Description : Check nftables configuration
if [ ! "${NFTBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4538 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check nftables basic configuration"
if [ ${SKIPTEST} -eq 0 ]; then
# Retrieve nft version
NFT_VERSION=$(${NFTBINARY} --version 2> /dev/null | ${AWKBINARY} '{ if ($1=="nftables") { print $2 }}' | ${TRBINARY} -d 'v')
Report "nft_version=${NFT_VERSION}"
LogText "Result: found version ${NFT_VERSION} of nft"
fi
#
#################################################################################
#
# Test : FIRE-4540
# Description : Check nftables configuration
if [ ! "${NFTBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no FIRE-4540 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for empty nftables configuration"
if [ ${SKIPTEST} -eq 0 ]; then
# Check for empty ruleset
NFT_RULES_LENGTH=$(${NFTBINARY} export json 2> /dev/null | wc -c)
if [ ${NFT_RULES_LENGTH} -le 16 ]; then
FIREWALL_EMPTY_RULESET=1
LogText "Result: this firewall set has 16 rules or less and is considered to be empty"
else
LogText "Result: found ${NFT_RULES_LENGTH} rules in nftables configuration"
fi
fi
#
#################################################################################
#
# Ideas:
# Suggestion to disable iptables if nftables is enabled
# Check for specific features in nftables releases
#
#################################################################################
#
# Test : FIRE-4590
# Description : Check if at least one firewall if active
Register --test-no FIRE-4590 --weight L --network NO --category security --description "Check firewall status"
if [ ${SKIPTEST} -eq 0 ]; then
if [ ${FIREWALL_ACTIVE} -eq 1 ]; then
Display --indent 2 --text "- Checking host based firewall" --result "ACTIVE" --color GREEN
LogText "Result: host based firewall or packet filter is active"
Report "manual[]=Verify if there is a formal process for testing and applying firewall rules"
Report "manual[]=Verify all traffic is filtered the right way between the different security zones"
Report "manual[]=Verify if a list is available with all required services"
# YYY Solaris ipf (determine default policy)
Report "manual[]=Make sure an explicit deny all is the default policy for all unmatched traffic"
AddHP 5 5
else
Display --indent 2 --text "- Checking host based firewall" --result "NOT ACTIVE" --color YELLOW
LogText "Result: no host based firewall/packet filter found or configured"
ReportSuggestion ${TEST_NO} "Configure a firewall/packet filter to filter incoming and outgoing traffic"
AddHP 0 5
fi
fi
#
#################################################################################
#
# Report firewall installed for now, if we found one active. Next step would be determining binaries first and apply additional checks.
Report "firewall_active=${FIREWALL_ACTIVE}"
Report "firewall_empty_ruleset=${FIREWALL_EMPTY_RULESET}"
Report "firewall_installed=${FIREWALL_ACTIVE}"
Report "firewall_software=${FIREWALL_SOFTWARE}"
WaitForKeyPress
#
#================================================================================
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com