#!/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. # ################################################################################# # # Read profile/template # ################################################################################# # # Set default values (should be equal to default.prf) SETTING_LOG_TESTS_INCORRECT_OS=1 SETTING_SHOW_REPORT_SOLUTION=0 DEPRECATED_OPTION="" # ################################################################################# # for PROFILE in ${PROFILES}; do LogText "Reading profile/configuration ${PROFILE}" # Show deprecation message for old config entries such as 'config:' and 'apache:' FOUND=0 DATA=$(grep -E "^[a-z-]{1,}:" ${PROFILE}) if ! IsEmpty "${DATA}"; then FOUND=1; fi if [ ${FOUND} -eq 1 ]; then Display --text " " Display --text "==================================================================================================" DisplayWarning "Your profile contains old-style configuration entries. See log file for more details and how to convert these entries" Display --indent 2 --text "* ${RED}ISSUE${NORMAL}" Display --indent 2 --text "Your profile has one or more lines that are in an old format (key:value). They need to be converted into the new format (key=value) or disabled." Display --text " " Display --indent 2 --text "* ${GREEN}HOW TO RESOLVE${NORMAL}" Display --indent 2 --text "Use grep to see the relevant matches (grep -E \"^[a-z-]{1,}:\" custom.prf)" Display --text " " Display --text "==================================================================================================" Display --text " " LogText "Insight: Profile '${PROFILE}' contains one or more old-style configuration entries" ReportWarning "GEN-0020" "Your profile contains one or more old-style configuration entries" sleep 10 fi # Security check for unexpected and possibly harmful escape characters (hyphen should be listed as first or last character) DATA=$(grep -Ev '^$|^ |^#|^config:' "${PROFILE}" | tr -d '[:alnum:]/\[\]\(\)_\|,\.:;= \n\r-') if ! IsEmpty "${DATA}"; then DisplayWarning "Your profile '${PROFILE}' contains unexpected characters. See the log file for more information." LogText "Found unexpected or possibly harmful characters in profile '${PROFILE}'. See which characters matched in the output below and compare them with your profile." for I in $(printf ${DATA} | od -An -ta); do LogText "Output: ${I}" done LogText "Suggestion: comment incorrect lines with a '#' and try again. Open a GitHub issue if valid characters are blocked" ExitFatal "unexpected characters in profile. Stopping execution (security measure)" fi # Now parse the profile and filter out unwanted characters DATA=$(grep -E "^config:|^[a-z-].*=" ${PROFILE} | tr -dc '[:alnum:]/\[\]\(\)_\|,\.:;= \n\r-' | sed 's/ /!space!/g') for CONFIGOPTION in ${DATA}; do if ContainsString "^config:" "${CONFIGOPTION}"; then # Old style configuration OPTION=$(echo ${CONFIGOPTION} | cut -d ':' -f2) VALUE=$(echo ${CONFIGOPTION} | cut -d ':' -f3 | sed 's/!space!/ /g') DEPRECATED_OPTION="${OPTION}" else OPTION=$(echo ${CONFIGOPTION} | cut -d '=' -f1) VALUE=$(echo ${CONFIGOPTION} | cut -d '=' -f2 | sed 's/!space!/ /g') fi Debug "Profile option set: ${OPTION} (with value ${VALUE})" case ${OPTION} in # Is Lynis Enterprise allowed to purge this system when it is becomes outdated? allow-auto-purge) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)$") if [ -n "${FIND}" ]; then Report "allow-auto-purge=1" else Report "allow-auto-purge=0" fi ;; # Define which compliance standards are enabled # For this to work, the Enterprise plugins are needed compliance_standards | compliance-standards | check-compliance) # deprecated: compliance_standards COMPLIANCE_STANDARDS_ENABLED=$(echo ${VALUE} | tr ',' ' ') for STANDARD in ${COMPLIANCE_STANDARDS_ENABLED}; do case ${STANDARD} in cis) COMPLIANCE_ENABLE_CIS=1 ; Debug "Compliance scanning for CIS Benchmarks is enabled" ;; hipaa) COMPLIANCE_ENABLE_HIPAA=1 ; Debug "Compliance scanning for HIPAA is enabled" ;; iso27001) COMPLIANCE_ENABLE_ISO27001=1 ; Debug "Compliance scanning for ISO27001 is enabled" ;; pci-dss) COMPLIANCE_ENABLE_PCI_DSS=1 ; Debug "Compliance scanning for PCI DSS is enabled" ;; *) LogText "Result: Unknown compliance standard configured" ;; esac done ;; # Check for a specific value check-value) STRING=$(echo ${VALUE} | tr -d "[" | tr -d "]" | sed "s/, /,/g") CHECK_VALUE_ARRAY="${CHECK_OPTION_ARRAY} ${STRING}" ;; # Colored output colors) # Quick mode (SKIP_PLUGINS) might already be set outside profile, so store in different variable SETTING_COLORS=1 # default is yes FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)$") && COLORS=0 if [ -n "${FIND}" ]; then SETTING_COLORS=0; RemoveColors; fi Debug "Colors set to ${SETTING_COLORS}" AddSetting "colors" "${SETTING_COLORS}" "Colored screen output" unset SETTING_COLORS ;; # Ignore configuration data config-data | permdir | permfile) Debug "Ignoring configuration option, as it will be used by a specific test" ;; # Maximum number of WAITing connections connections-max-wait-state | connections_max_wait_state) OPTIONS_CONN_MAX_WAIT_STATE="${VALUE}" AddSetting "connections-max-wait-state" "${OPTIONS_CONN_MAX_WAIT_STATE}" "Connections (max-wait-state)" ;; # Append something to URL for control information control-url-append | control_url_append) CONTROL_URL_APPEND="${VALUE}" AddSetting "control-url-append" "${CONTROL_URL_APPEND}" "Control URL (append)" ;; # Prepend an URL before control information link control-url-prepend | control_url_prepend) CONTROL_URL_PREPEND="${VALUE}" AddSetting "control-url-prepend" "${CONTROL_URL_PREPEND}" "Control URL (prepend)" ;; # Protocol to use for control information link control-url-protocol | control_url_protocol) CONTROL_URL_PROTOCOL="${VALUE}" AddSetting "control-url-protocol" "${CONTROL_URL_PREPEND}" "Control URL (protocol)" ;; # Append something to URL for control information (only applies to CUST-*) custom-url-append | custom_url_append) CUSTOM_URL_APPEND="${VALUE}" AddSetting "custom-url-append" "${CUSTOM_URL_APPEND}" "Custom URL (append)" ;; # Prepend an URL before control information link (only applies to CUST-*) custom-url-prepend | custom_url_prepend) CUSTOM_URL_PREPEND="${VALUE}" AddSetting "custom-url-prepend" "${CUSTOM_URL_PREPEND}" "Custom URL (prepend)" ;; # Protocol to use for control information link custom-url-protocol | custom_url_protocol) CUSTOM_URL_PROTOCOL="${VALUE}" AddSetting "custom-url-protocol" "${CUSTOM_URL_PREPEND}" "Custom URL (protocol)" ;; # Do not check security repository in sources.list (Debian/Ubuntu) debian-skip-security-repository | debian_skip_security_repository) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && OPTION_DEBIAN_SKIP_SECURITY_REPOSITORY=1 AddSetting "debian-skip-security-repository" "OPTION_DEBIAN_SKIP_SECURITY_REPOSITORY" "Skip checking for a security repository (Debian and others)" ;; # Debug status to show more details while running program debug) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && DEBUG=1 Debug "Debug mode set to '${DEBUG}'" AddSetting "debug" "${DEBUG}" "Debugging mode" ;; # Development mode (--developer) developer-mode) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && DEVELOPER_MODE=1 Debug "Developer mode set to ${DEVELOPER_MODE}" AddSetting "developer" "${DEVELOPER_MODE}" "Developer mode" ;; # Show non-zero exit code when errors are found error-on-warnings) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && ERROR_ON_WARNINGS=1 Debug "Exit with different code on warnings is set to ${ERROR_ON_WARNINGS}" AddSetting "error-on-warnings" "${ERROR_ON_WARNINGS}" "Use non-zero exit code if one or more warnings were found" ;; # Skip FreeBSD port audit freebsd-skip-portaudit | freebsd_skip_portaudit) LogText "Option set: Skip FreeBSD portaudit" OPTION_FREEBSD_SKIP_PORTAUDIT="${VALUE}" ;; # Lynis Enterprise: group name - deprecated option group) GROUP_NAME="${VALUE}" AddSetting "group" "${GROUP_NAME}" "Group" DEPRECATED_OPTION="group" ;; hostalias | host-alias) if [ -n "${VALUE}" ]; then Report "hostname_alias=${VALUE}"; fi ;; hostid) HOSTID="${VALUE}" ;; hostid2) HOSTID2="${VALUE}" ;; # Home directories to ignore during scans ignore-home-dir) Report "ignore-home-dir[]=${VALUE}" ;; # Language language | lang) LogText "Language set via profile to '${VALUE}'" if [ -n "${VALUE}" ]; then LANGUAGE="${VALUE}"; fi AddSetting "language" "${LANGUAGE}" "Language" ;; # Lynis Enterprise license key license-key | license_key) if [ -n "${VALUE}" ]; then LICENSE_KEY="${VALUE}" Report "license_key=${VALUE}" fi AddSetting "license-key" "${VALUE}" "License key" ;; # Do (not) log tests if they have an different operating system log-tests-incorrect-os | log_tests_incorrect_os) FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)") && SETTING_LOG_TESTS_INCORRECT_OS=0 Debug "Logging of tests with incorrect operating system set to ${SETTING_LOG_TESTS_INCORRECT_OS}" LOG_INCORRECT_OS=${SETTING_LOG_TESTS_INCORRECT_OS} ;; # What type of machine we are scanning (eg. personal, workstation or server) machine-role | machine_role) MACHINE_ROLE="${VALUE}" AddSetting "machine-role" "${MACHINE_ROLE}" "Machine role (personal, workstation or server)" ;; # Define if any found NTP daemon instance is configured as a server or client ntpd-role | ntpd_role) NTPD_ROLE="${VALUE}" AddSetting "ntpd-role" "${NTPD_ROLE}" "NTP role (server or client)" ;; # How much seconds to wait between tests pause_between_tests | pause-between-tests) TEST_PAUSE_TIME="${VALUE}" AddSetting "pause-between-tests" "${TEST_PAUSE_TIME}" "Pause between tests (in seconds)" ;; # Plugin plugin) LogText "Plugin '${VALUE}' enabled according profile (${PROFILE})" ;; disable-plugin) LogText "Plugin '${VALUE}' disabled according profile (${PROFILE})" DISABLED_PLUGINS="${DISABLED_PLUGINS} ${VALUE}" ;; # Plugin directory plugindir | plugin-dir) if IsEmpty "${PLUGINDIR}"; then PLUGINDIR="${VALUE}" else LogText "Plugin directory was already set to ${PLUGINDIR} before (most likely as a program argument), not overwriting" fi AddSetting "plugin-dir" "${PLUGINDIR}" "Plugin directory" ;; # Profile name profile-name | profile_name) PROFILE_NAME="${VALUE}" ;; # Quick (no waiting for keypresses) quick) # Quick mode might already be set outside profile, so store in different variable SETTING_QUICK_MODE=1 # default is yes FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)$") && QUICKMODE=0 if [ -n "${FIND}" ]; then SETTING_QUICK_MODE=1; fi Debug "Quickmode set to ${SETTING_QUICK_MODE}" AddSetting "quick" "${SETTING_QUICK_MODE}" "Quick mode (non-interactive)" ;; # Refresh software repositories refresh-repositories) SETTING_REFRESH_REPOSITORIES=1 # default is yes FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)$") && REFRESH_REPOSITORIES=0 if [ -n "${FIND}" ]; then SETTING_REFRESH_REPOSITORIES=0; fi Debug "Refreshing repositories set to ${SETTING_REFRESH_REPOSITORIES}" AddSetting "refresh-repositories" "${SETTING_REFRESH_REPOSITORIES}" "Refresh repositories (for vulnerable package detection)" ;; # Show more details in report show-report-solution) SETTING_SHOW_REPORT_SOLUTION=${SHOW_REPORT_SOLUTION} FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)$") && SHOW_REPORT_SOLUTION=0 if [ -n "${FIND}" ]; then SETTING_SHOW_REPORT_SOLUTION=0; fi Debug "Show report details (solution) set to ${SETTING_SHOW_REPORT_SOLUTION}" ;; # Inline tips about tool (default enabled) show_tool_tips | show-tool-tips) SETTING_SHOW_TOOL_TIPS=1 # default is yes FIND=$(echo "${VALUE}" | grep -E "^(0|false|no)$") && SHOW_TOOL_TIPS=0 if [ -n "${FIND}" ]; then SETTING_SHOW_TOOL_TIPS=0; fi Debug "Show tool tips set to ${SETTING_SHOW_TOOL_TIPS}" AddSetting "show-tool-tips" "${SETTING_SHOW_TOOL_TIPS}" "Show tool tips" ;; # Show warnings only show-warnings-only) QUIET=1 QUICKMODE=1 FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)$") && SHOW_WARNINGS_ONLY=1 Debug "Show warnings only set to ${SHOW_WARNINGS_ONLY}" AddSetting "show-warnings-only" "${SHOW_WARNINGS_ONLY}" "Show only warnings" ;; # Skip plugins skip-plugins) # Skip plugins (SKIP_PLUGINS) might already be set, so store in different variable SETTING_SKIP_PLUGINS=0 # default is no FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)$") && SKIP_PLUGINS=1 if [ -n "${FIND}" ]; then SETTING_SKIP_PLUGINS=1; fi Debug "Skip plugins is set to ${SETTING_SKIP_PLUGINS}" AddSetting "skip-plugins" "${SETTING_SKIP_PLUGINS}" "Skip plugins" ;; # Which tests to skip (skip-test=ABCD-1234 or skip-test=ABCD-1234:subtest) skip-test) STRING=$(echo ${VALUE} | tr '[:lower:]' '[:upper:]') SKIP_TESTS="${SKIP_TESTS} ${STRING}" ;; # Do not check the latest version on the internet skip_upgrade_test | skip-upgrade-test) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && SKIP_UPGRADE_TEST=1 Debug "Skip upgrade test set to ${SKIP_UPGRADE_TEST}" ;; # SSL paths ssl-certificate-paths) SSL_CERTIFICATE_PATHS="${VALUE}" Debug "SSL paths set to ${SSL_CERTIFICATE_PATHS}" AddSetting "ssl-certificate-paths" "${SSL_CERTIFICATE_PATHS}" "Paths for SSL certificates" ;; ssl-certificate-paths-to-ignore) # Retrieve paths to ignore when searching for certificates. Strip special characters, replace possible spaces SSL_CERTIFICATE_PATHS_TO_IGNORE=$(echo ${VALUE} | tr -d '[:cntrl:]' | sed 's/ /__space__/g' | tr ':' ' ') Debug "SSL paths to ignore: ${SSL_CERTIFICATE_PATHS_TO_IGNORE}" AddSetting "ssl-certificate-paths-to-ignore" "${SSL_CERTIFICATE_PATHS_TO_IGNORE}" "Paths that should be ignored for SSL certificates" ;; # Check also certificates provided by packages? ssl-certificate-include-packages) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && SSL_CERTIFICATE_INCLUDE_PACKAGES=1 Debug "Check also certificates provided by packages set to ${SSL_CERTIFICATE_INCLUDE_PACKAGES}" ;; # Set strict mode for development and quality purposes strict) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && SET_STRICT=1 ;; # The name of the customer/client that uses this system system-customer-name) if [ -n "${VALUE}" ]; then Report "system-customer-name=${VALUE}"; fi ;; # The groups linked to a system (system-groups=customers,webservers,production) system-groups) if [ -n "${VALUE}" ]; then Report "system-groups=${VALUE}"; fi ;; # Tags (tags=db,production,ssn-1304) tags) if [ -n "${VALUE}" ]; then Report "tags=${VALUE}"; fi ;; # Define what kind of scan we are performing test_scan_mode | test-scan-mode) if [ "${VALUE}" = "light" ]; then SCAN_TEST_LIGHT="YES"; SCAN_TEST_MEDIUM="NO"; SCAN_TEST_HEAVY="NO"; fi if [ "${VALUE}" = "normal" ]; then SCAN_TEST_LIGHT="YES"; SCAN_TEST_MEDIUM="YES"; SCAN_TEST_HEAVY="NO"; fi if [ "${VALUE}" = "full" ]; then SCAN_TEST_LIGHT="YES"; SCAN_TEST_MEDIUM="YES"; SCAN_TEST_HEAVY="YES"; fi AddSetting "test-scan-mode" "${VALUE}" "Scan mode" ;; # Perform upload upload) SETTING_UPLOAD=no # default FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)$") && UPLOAD_DATA=1 if [ -n "${FIND}" ]; then SETTING_UPLOAD=1; fi Debug "Upload set to ${SETTING_UPLOAD}" AddSetting "upload" "${SETTING_UPLOAD}" "Data upload after scanning" unset SETTING_UPLOAD ;; # Compression of uploads (enabled by default) upload_compressed | compressed-uploads) if [ "${VALUE}" = "0" ]; then COMPRESSED_UPLOADS=0; fi AddSetting "compressed-uploads" "${COMPRESSED_UPLOADS}" "Compressed uploads" ;; # Options during upload of data upload_options | upload-options) UPLOAD_OPTIONS="${VALUE}" AddSetting "upload-options" "${UPLOAD_OPTIONS}" "Upload options" ;; # Proxy settings upload_proxy_port | proxy-port | upload-proxy-port) UPLOAD_PROXY_PORT="${VALUE}" AddSetting "upload-proxy-port" "${UPLOAD_PROXY_PORT}" "Proxy port" ;; upload_proxy_protocol | proxy-protocol) UPLOAD_PROXY_PROTOCOL="${VALUE}" AddSetting "upload-proxy-protocol" "${UPLOAD_PROXY_PROTOCOL}" "Proxy protocol" ;; upload_proxy_server | proxy-server) UPLOAD_PROXY_SERVER="${VALUE}" AddSetting "upload-proxy-server" "${UPLOAD_PROXY_PORT}" "Proxy server" ;; # Receiving system (IP address or hostname) upload-server) UPLOAD_SERVER="${VALUE}" AddSetting "upload-server" "${UPLOAD_SERVER}" "Upload server (ip or hostname)" ;; # Specify an alternative upload tool upload-tool) if [ -f "${VALUE}" ]; then UPLOAD_TOOL="${VALUE}"; fi AddSetting "upload-tool" "${UPLOAD_TOOL}" "Upload tool" ;; # Specify arguments for an alternative upload tool upload-tool-arguments) UPLOAD_TOOL_ARGS="${VALUE}" AddSetting "upload-tool-arguments" "${UPLOAD_TOOL_ARGS}" "Upload tool (arguments)" ;; # Verbose output (--verbose) verbose) FIND=$(echo "${VALUE}" | grep -E "^(1|true|yes)") && VERBOSE=1 Debug "Verbose set to ${VERBOSE}" AddSetting "verbose" "${VERBOSE}" "Verbose output" ;; ######################################################################################################## ## DEPRECATED ITEMS ######################################################################################################## # Deprecated: skip tests test_skip_always) STRING=$(echo ${VALUE} | tr '[:lower:]' '[:upper:]') SKIP_TESTS="${SKIP_TESTS} ${STRING}" LogText "[deprecated option] Tests to be skipped: ${VALUE}" DisplayToolTip "Replace deprecated option 'test_skip_always' and replace with 'skip-test' (add to custom.prf)" ;; # Deprecated: receiving system (IP address or hostname) upload_server) UPLOAD_SERVER="${VALUE}" AddSetting "upload-server" "${UPLOAD_SERVER}" "Upload server (ip or hostname)" DisplayToolTip "Replace deprecated option 'upload_server' and replace with 'upload-server' (add to custom.prf)" ;; # Catch all bad options and bail out *) LogText "Unknown option ${OPTION} (with value: ${VALUE})" ${ECHOCMD:-echo} "" ${ECHOCMD:-echo} "${RED}Error${NORMAL}: found one or more errors in profile ${PROFILE}" ${ECHOCMD:-echo} "" ${ECHOCMD:-echo} "" ${ECHOCMD:-echo} "Full line: ${CONFIGOPTION}" ${ECHOCMD:-echo} "${WHITE}Details${NORMAL}: Unknown option '${YELLOW}${OPTION}${NORMAL}' found (with value: ${VALUE})" ${ECHOCMD:-echo} "" ExitFatal ;; esac done done # ################################################################################# # SKIP_TESTS=$(echo ${SKIP_TESTS} | sed "s/^ //") if [ -n "${SKIP_TESTS}" ]; then LogText "Skip tests: ${SKIP_TESTS}"; fi # ################################################################################# # # Add group name to report - deprecated if [ -n "${GROUP_NAME}" ]; then Report "group=${GROUP_NAME}"; fi # ################################################################################# # # Set default values (only if not configured in profile) if [ -z "${MACHINE_ROLE}" ]; then MACHINE_ROLE="server" LogText "Set option to default value: MACHINE_ROLE --> ${MACHINE_ROLE}" fi if [ -z "${NTPD_ROLE}" ]; then NTPD_ROLE="client" LogText "Set option to default value: NTPD_ROLE --> ${NTPD_ROLE}" fi # ################################################################################# # # Register the discovered settings AddSetting "log-tests-incorrect-os" "${SETTING_LOG_TESTS_INCORRECT_OS}" "Logging of tests that have a different OS" AddSetting "show-report-solution" "${SETTING_SHOW_REPORT_SOLUTION}" "Show more details in report (solution)" AddSetting "skip-upgrade-test" "${SKIP_UPGRADE_TEST}" "Skip upgrade test" AddSetting "strict" "${SET_STRICT}" "Perform strict code test of scripts" unset SETTING_LOG_TESTS_INCORRECT_OS SETTING_SHOW_REPORT_SOLUTION # ################################################################################# # if [ -n "${DEPRECATED_OPTION}" ]; then ReportWarning "GEN-0030" "One or more deprecated options used in profile" "${DEPRECATED_OPTION}" "Update your profile" fi # ################################################################################# # Display --indent 2 --text "- Checking profiles..." --result "DONE" --color GREEN #================================================================================ # Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com