diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f36522a..1430528e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ This is a major release of Lynis and includes several big changes. Some of these changes may break your current usage of the tool, so test before deployment! -Breaking changes: +### Breaking changes - Some commands or switches are deprecated or removed - Format of all profile options converted (from key:value to key=value) - Non-interactive by default (use --wait option to pause between groups of tests) +### Security An important focus area for this release is on security. We added several measures to further tighten any possible misuse. @@ -30,6 +31,7 @@ measures to further tighten any possible misuse. - New test: CRYP-7930 - disk or file system encryption testing - New test: PROC-3802 - Check presence of prelink tooling - New report key: openssh_daemon_running +- New command: lynis generate systemd-units - Measure timing of tests and report slow tests (10+ seconds) ### Changed @@ -40,11 +42,15 @@ measures to further tighten any possible misuse. - Use only locations from PATH environment variable, unless it is not defined - Show 'lynis generate hostids' when they are missing - NAME-4408 - corrected Report function call +- NETW-3032 - small rewrite of test and extended with addrwatch - PROC-3602 - allow different root directory - PROC-3612 - show 'Not found' instead of 'OK' - PROC-3614 - show 'Not found' instead of 'OK' - SSH-7402 - detect other SSH daemons like dropbear +- SSH-7406 - strip OpenSSH patch version and remove characters (carriage return) +- Whow changelog works again for newer versions - systemd service file adjusted +- bash completion script extended --------------------------------------------------------------------------------- diff --git a/extras/bash_completion.d/lynis b/extras/bash_completion.d/lynis index 235a848a..8732ede3 100644 --- a/extras/bash_completion.d/lynis +++ b/extras/bash_completion.d/lynis @@ -1,6 +1,6 @@ # bash completion for lynis -# version 1.0.0 (22 September 2014) +# version 1.0.1 (2019-07-13) # Michael Boelen # lynis(8) completion @@ -10,7 +10,7 @@ _lynis() # opts nodig nosig COMPREPLY=() - _get_comp_words_by_ref cur prev + _get_comp_words_by_ref cur prev words if [ $COMP_CWORD -eq 1 ]; then # first parameter on line @@ -19,24 +19,134 @@ _lynis() COMPREPLY=( $( compgen -W '--help --info --version' -- "$cur" ) ) ;; *) - COMPREPLY=( $( compgen -W 'audit --help --info --version' -- "$cur" ) ) + COMPREPLY=( $( compgen -W 'audit generate show' -- "$cur" ) ) ;; esac - - return 0 + return 0 + elif [ $COMP_CWORD -eq 4 ]; then + # Stop after some specifics + if [ "${COMP_WORDS[1]}" = "show" -a "${COMP_WORDS[2]}" = "details" ]; then + return 0 + fi fi + # Check previous argument to share the available options case $prev in audit) COMPREPLY=( $( compgen -W 'dockerfile system ' -- "$cur" ) ) ;; + show) - COMPREPLY=( $( compgen -W 'help version ' -- "$cur" ) ) + COMPREPLY=( $( compgen -W 'categories changelog commands dbdir details environment eol groups help hostids includedir language license logfile man options os pidfile plugindir profiles release releasedate report settings tests version workdir ' -- "$cur" ) ) ;; + # Related items to show (lynis show XYZ) + categories) + return 0 + ;; + changelog) + return 0 + ;; + commands) + return 0 + ;; + dbdir) + return 0 + ;; + details) + local dbfile="" + local dirs="/data/development/lynis /usr/local/lynis /usr/share/lynis" + for d in ${dirs}; do + if [ -f "${d}/db/tests.db" ]; then + local dbfile="/data/development/lynis/db/tests.db" + fi + done + if [ -f "${dbfile}" ]; then + local suggestions=($(compgen -W "$(awk -F: '$1 ~ /^[A-Z]/ {print $1}' ${dbfile})" -- "${cur}")) + COMPREPLY=("${suggestions[@]}") + else + COMPREPLY=($(compgen -W "TEST-1234" -- "$cur")) + fi + ;; + environment) + return 0 + ;; + eol) + return 0 + ;; + groups) + return 0 + ;; + help) + return 0 + ;; + hostids) + if [ "${COMP_WORDS[1]}" = "generate" -a "${COMP_WORDS[2]}" = "hostids" ]; then + COMPREPLY=($(compgen -W "save" -- "$cur")) + else + return 0 + fi + ;; + includedir) + return 0 + ;; + language) + return 0 + ;; + license) + return 0 + ;; + logfile) + return 0 + ;; + man) + return 0 + ;; + options) + return 0 + ;; + os) + return 0 + ;; + pidfile) + return 0 + ;; + plugindir) + return 0 + ;; + profiles) + return 0 + ;; + release) + return 0 + ;; + releasedate) + return 0 + ;; + report) + return 0 + ;; + settiings) + return 0 + ;; + tests) + return 0 + ;; + version) + return 0 + ;; + workdir) + return 0 + ;; + + generate) + COMPREPLY=( $( compgen -W 'hostids ' -- "$cur" ) ) + ;; + + # Options --auditor) COMPREPLY=( '"Mr. Auditor"' ) - return 0 + #return 0 ;; --check-update|--help|--info|--version) # all other options are noop with this command diff --git a/extras/systemd/lynis.service b/extras/systemd/lynis.service index c49fdf12..21432c22 100644 --- a/extras/systemd/lynis.service +++ b/extras/systemd/lynis.service @@ -5,14 +5,17 @@ ################################################################################# # # - Adjust path to link to location where Lynis binary is installed -# - Place this file and the timer file together in the systemd directory -# (e.g. /etc/systemd/system/) -# - Run: systemctl enable lynis.service +# +# - Place this file together with the lynis.timer file in the related +# systemd directory (e.g. /etc/systemd/system/) +# +# - See details in lynis.timer file # ################################################################################# [Unit] -Description=Lynis security audit and vulnerability scan +Description=Security audit and vulnerability scanner +Documentation=https://cisofy.com/docs/ [Service] Nice=19 @@ -21,4 +24,7 @@ IOSchedulingPriority=7 Type=simple ExecStart=/path/to/lynis audit system --cronjob +[Install] +WantedBy=multi-user.target + #EOF diff --git a/extras/systemd/lynis.timer b/extras/systemd/lynis.timer index 169b3c17..83f5c144 100644 --- a/extras/systemd/lynis.timer +++ b/extras/systemd/lynis.timer @@ -4,17 +4,23 @@ # ################################################################################# # -# - Place this file together with the service file in systemd directory -# - Run: systemctl enable lynis.timer -# systemctl start lynis.service +# - Place this file together with the lynis.service file in the related +# systemd directory (e.g. /etc/systemd/system) +# +# - Tell systemd you made changes +# systemctl daemon-reload +# +# - Enable and start the timer (so no reboot is needed): +# systemctl enable --now lynis.timer # ################################################################################# [Unit] -Description=Daily run for Lynis security audit and vulnerability scan +Description=Daily timer for the Lynis security audit and vulnerability scanner [Timer] OnCalendar=daily +RandomizedDelaySec=1800 Persistent=false [Install] diff --git a/include/helper_generate b/include/helper_generate index bdcfb44d..31dba7ec 100644 --- a/include/helper_generate +++ b/include/helper_generate @@ -29,7 +29,7 @@ ###################################################################### SAVEFILE=0 -GENERATE_ARGS="hostids" +GENERATE_ARGS="hostids systemd-units" if [ $# -gt 0 ]; then case $1 in @@ -71,6 +71,97 @@ if [ $# -gt 0 ]; then ExitClean ;; + + "cronjob") + ${ECHOCMD} "Not implemented yet" + ;; + + "systemd-units") + + ${ECHOCMD} "" + + ${ECHOCMD} "${BG_BLUE}Step 1: create service unit (/etc/systemd/system/lynis.service)${NORMAL}" + + ${ECHOCMD} "" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "#" + ${ECHOCMD} "# Lynis service file for systemd" + ${ECHOCMD} "#" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "# Do not remove, so Lynis can provide a hint when a newer unit is available" + ${ECHOCMD} "# Generator=lynis" + ${ECHOCMD} "# Version=1" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "" + ${ECHOCMD} "[Unit]" + ${ECHOCMD} "Description=Security audit and vulnerability scanner" + ${ECHOCMD} "Documentation=https://cisofy.com/docs/" + ${ECHOCMD} "" + ${ECHOCMD} "[Service]" + ${ECHOCMD} "Nice=19" + ${ECHOCMD} "IOSchedulingClass=best-effort" + ${ECHOCMD} "IOSchedulingPriority=7" + ${ECHOCMD} "Type=simple" + MYBINARY=$(which lynis 2>/dev/null) + MOREOPTIONS="" + if [ -n "${LICENSE_KEY}" ]; then + MOREOPTIONS=" --upload" + fi + ${ECHOCMD} "ExecStart=${MYBINARY:-/path/to/lynis} audit system --cronjob${MOREOPTIONS}" + ${ECHOCMD} "" + ${ECHOCMD} "[Install]" + ${ECHOCMD} "WantedBy=multi-user.target" + ${ECHOCMD} "" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "" + ${ECHOCMD} "" + + ${ECHOCMD} "${BG_BLUE}Step 2: create timer unit (/etc/systemd/system/lynis.timer)${NORMAL}" + ${ECHOCMD} "" + + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "#" + ${ECHOCMD} "# Lynis timer file for systemd" + ${ECHOCMD} "#" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "# Do not remove, so Lynis can provide a hint when a newer unit is available" + ${ECHOCMD} "# Generator=lynis" + ${ECHOCMD} "# Version=1" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "" + ${ECHOCMD} "[Unit]" + ${ECHOCMD} "Description=Daily timer for the Lynis security audit and vulnerability scanner" + ${ECHOCMD} "" + ${ECHOCMD} "[Timer]" + ${ECHOCMD} "OnCalendar=daily" + ${ECHOCMD} "RandomizedDelaySec=1800" + ${ECHOCMD} "Persistent=false" + ${ECHOCMD} "" + ${ECHOCMD} "[Install]" + ${ECHOCMD} "WantedBy=timers.target" + ${ECHOCMD} "" + ${ECHOCMD} "#################################################################################" + ${ECHOCMD} "" + ${ECHOCMD} "" + + ${ECHOCMD} "${BG_BLUE}Step 3 - Enable the timer${NORMAL}" + + ${ECHOCMD} "" + ${ECHOCMD} "Tell systemd you made changes: systemctl daemon-reload" + ${ECHOCMD} "" + ${ECHOCMD} "Enable and start the timer (so no reboot is needed): systemctl enable --now lynis.timer" + ${ECHOCMD} "" + ${ECHOCMD} "" + ${ECHOCMD} "${BG_BLUE}Optional - Customize${NORMAL}" + ${ECHOCMD} "" + ${ECHOCMD} "Want to override the timer? Run: systemctl edit lynis.timer" + ${ECHOCMD} "Note: set the timer by first resetting it, then set the preferred value" + ${ECHOCMD} "" + ${ECHOCMD} "[Timer]" + ${ECHOCMD} "OnCalendar=" + ${ECHOCMD} "OnCalendar=*-*-* 03:00:00" + ${ECHOCMD} "" + ;; *) ${ECHOCMD} "Unknown argument '${RED}$1${NORMAL}' for lynis generate" ;; esac else diff --git a/include/helper_show b/include/helper_show index 874b3e1b..94d839be 100644 --- a/include/helper_show +++ b/include/helper_show @@ -102,6 +102,9 @@ GENERATE_HELP=" Generate and save values ${WHITE}lynis generate hostids --save${NORMAL} + Generate systemd units to run Lynis on a schedule (e.g. daily) + ${WHITE}lynis generate systemd-units${NORMAL} + " @@ -160,15 +163,15 @@ if [ $# -gt 0 ]; then if [ ! -z "${CHANGELOG}" ]; then LogText "Result: found changelog file: ${CHANGELOG}"; break; fi done if [ ! -z "${CHANGELOG}" ]; then - SEARCH=$(egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}" ${CHANGELOG}) + SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}") if [ $? -eq 0 ]; then while read -r LINE; do if [ ${STARTED} -eq 0 ]; then - SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}") + SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}") if [ $? -eq 0 ]; then STARTED=1; ${ECHOCMD} "${BOLD}${LINE}${NORMAL}"; fi else # Stop if we find the next Lynis version - SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]") + SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]") if [ $? -eq 0 ]; then break else @@ -183,7 +186,7 @@ if [ $# -gt 0 ]; then ${ECHOCMD} "$0 lynis show changelog [version]" ${ECHOCMD} "" ${ECHOCMD} "${HEADER}${PROGRAM_NAME} versions:${NORMAL}" - SEARCH=$(egrep "^Lynis [0-9]\.[0-9]\.[0-9] " ${CHANGELOG} | awk '{print $2}' | sort -n) + SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^Lynis [0-9]\.[0-9]\.[0-9] " | awk '{print $2}' | sort -n) ${ECHOCMD} ${SEARCH} ExitFatal fi diff --git a/include/tests_networking b/include/tests_networking index b43970ce..8c895c4e 100644 --- a/include/tests_networking +++ b/include/tests_networking @@ -610,24 +610,28 @@ if [ ${SKIPTEST} -eq 0 ]; then FOUND=0 + # addrwatch + if IsRunning "addrwatch"; then + FOUND=1 + fi + # arpwatch - IsRunning arpwatch - if [ ${RUNNING} -eq 1 ]; then + if IsRunning "arpwatch"; then FOUND=1 ARPWATCH_RUNNING=1 - Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN fi # arpon - IsRunning arpon - if [ ${RUNNING} -eq 1 ]; then + if IsRunning "arpon"; then FOUND=1 ARPON_RUNNING=1 - Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN fi - if [ ${FOUND} -eq 0 ]; then + + if [ ${FOUND} -eq 1 ]; then + Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN + else Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_NOT_FOUND}" --color YELLOW - ReportSuggestion ${TEST_NO} "Consider running ARP monitoring software (arpwatch,arpon)" + ReportSuggestion "${TEST_NO}" "Consider running ARP monitoring software (addrwatch,arpwatch,arpon)" fi fi # diff --git a/include/tests_ssh b/include/tests_ssh index 6e35e608..dde395e3 100644 --- a/include/tests_ssh +++ b/include/tests_ssh @@ -102,12 +102,12 @@ if [ ${OPENSSHD_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no SSH-7406 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Determine OpenSSH version" if [ ${SKIPTEST} -eq 0 ]; then - OPENSSHD_VERSION=$(sshd -t -d 2>&1 | ${GREPBINARY} 'sshd version' | ${AWKBINARY} '{if($4~OpenSSH_){print $4}}' | ${AWKBINARY} -F_ '{print $2}' | ${TRBINARY} -d ',') + OPENSSHD_VERSION=$(${SSHDBINARY} -t -d 2>&1 | ${GREPBINARY} 'sshd version' | ${AWKBINARY} '{if($4~OpenSSH_){print $4}}' | ${AWKBINARY} -F_ '{print $2}' | ${TRBINARY} -d '[:cntrl:],') LogText "Result: discovered OpenSSH version is ${OPENSSHD_VERSION}" if [ ! -z ${OPENSSHD_VERSION} ]; then - OPENSSHD_VERSION_MAJOR=$(echo ${OPENSSHD_VERSION} | ${AWKBINARY} -F. '{print $1}') + OPENSSHD_VERSION_MAJOR=$(echo ${OPENSSHD_VERSION%%p*} | ${AWKBINARY} -F. '{print $1}') LogText "Result: OpenSSH major version: ${OPENSSHD_VERSION_MAJOR}" - OPENSSHD_VERSION_MINOR=$(echo ${OPENSSHD_VERSION} | ${AWKBINARY} -F. '{print $2}') + OPENSSHD_VERSION_MINOR=$(echo ${OPENSSHD_VERSION%%p*} | ${AWKBINARY} -F. '{print $2}') LogText "Result: OpenSSH minor version: ${OPENSSHD_VERSION_MINOR}" fi fi @@ -117,7 +117,7 @@ # Test : SSH-7408 # Description : Check SSH specific defined options # Notes : Instead of parsing the configuration file, we query the SSH daemon itself - if [ ${OPENSSHD_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + if [ ${OPENSSHD_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" -a ${OPENSSHD_VERSION_MAJOR} -ge 5 -a ${OPENSSHD_VERSION_MINOR} -ge 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no SSH-7408 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check SSH specific defined options" if [ ${SKIPTEST} -eq 0 ]; then LogText "Test: Checking specific defined options in ${SSH_DAEMON_OPTIONS_FILE}"