diff options
-rw-r--r-- | CHANGELOG.md | 81 | ||||
-rw-r--r-- | db/languages/da | 41 | ||||
-rw-r--r-- | db/software-eol.db | 24 | ||||
-rw-r--r-- | db/tests.db | 13 | ||||
-rw-r--r-- | include/binaries | 67 | ||||
-rw-r--r-- | include/consts | 8 | ||||
-rw-r--r-- | include/functions | 218 | ||||
-rw-r--r-- | include/helper_audit_dockerfile | 38 | ||||
-rw-r--r-- | include/helper_generate | 89 | ||||
-rw-r--r-- | include/helper_show | 14 | ||||
-rw-r--r-- | include/osdetection | 2 | ||||
-rw-r--r-- | include/parameters | 38 | ||||
-rw-r--r-- | include/report | 114 | ||||
-rw-r--r-- | include/tests_authentication | 48 | ||||
-rw-r--r-- | include/tests_boot_services | 6 | ||||
-rw-r--r-- | include/tests_filesystems | 36 | ||||
-rw-r--r-- | include/tests_firewalls | 5 | ||||
-rw-r--r-- | include/tests_insecure_services | 332 | ||||
-rw-r--r-- | include/tests_networking | 41 | ||||
-rw-r--r-- | include/tests_php | 3 | ||||
-rw-r--r-- | include/tests_ports_packages | 95 | ||||
-rw-r--r-- | include/tests_shells | 11 | ||||
-rwxr-xr-x | lynis | 30 |
23 files changed, 1093 insertions, 261 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a3522551..0d9a969c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,86 @@ # Lynis Changelog +## Lynis 3.0.0 (not released yet) + +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: +- Some of the old and deprecated commands or switches are removed + +An important focus area for this release is on security. We added several +measures to further tighten any possible misuse. + +### Added +- Test PATH and warn or exit on discovery of dangerous location (security) +- Additional safeguard by testing if common system tools are available (security) +- Test parameters and arguments for presence of control characters (security) +- New function SafeInput (security) + +### Changed +- The 'nounset' (set -u) parameter is now activated by default (security) +- Use locations from PATH environment variable, unless it is empty + +--------------------------------------------------------------------------------- + +## Lynis 2.7.5 (2019-06-24) + +### Added +- Danish translation +- Slackware end-of-life information +- Detect BSD-style (rc.d) init in Linux systems +- Detection of Bro and Suricata (IDS) + +### Changed +- Corrected end-of-life entries for CentOS 5 and 6 +- AUTH-9204 - change name to check in /etc/passwd file for QNAP devices +- AUTH-9268 - AIX enhancement to use correct find statement +- FILE-6310 - Filter on correct field for AIX +- NETW-3012 - set ss command as preferred option for Linux and changed output format +- List of PHP ini file locations has been extended +- Removed several pieces of the code as part of cleanup and code health +- Extended help + +--------------------------------------------------------------------------------- + + +## Lynis 2.7.4 (2019-04-21) + +This is a bigger release than usual, including several new tests created by +Capashenn (GitHub). It is a coincidence that it is released exactly one month +after the previous version and on Easter. No easter eggs, only improvements! + +### Added +- FILE-6324 - Discover XFS mount points +- INSE-8000 - Installed inetd package +- INSE-8100 - Installed xinetd package +- INSE-8102 - Status of xinet daemon +- INSE-8104 - xinetd configuration file +- INSE-8106 - xinetd configuration for inactive daemon +- INSE-8200 - Usage of TCP wrappers +- INSE-8300 - Presence of rsh client +- INSE-8302 - Presence of rsh server +- Detect equery binary detection +- New 'generate' command + +### Changed +- AUTH-9278 - Test LDAP in all PAM components on Red Hat and other systems +- PKGS-7410 - Add support for DPKG-based systems to gather installed kernel packages +- PKGS-7420 - Detect toolkit to automatically download and apply upgrades +- PKGS-7328 - Added global Zypper option --non-interactive +- PKGS-7330 - Added global Zypper option --non-interactive +- PKGS-7386 - Only show warning when vulnerable packages were discovered +- PKGS-7392 - Skip test for Zypper-based systems +- Minor changes to improve text output, test descriptions, and logging +- Changed CentOS identifiers in end-of-life database +- AIX enhancement for IsRunning function +- Extended PackageIsInstalled function +- Improve text output on AIX systems +- Corrected lsvg binary detection + +--------------------------------------------------------------------------------- + ## Lynis 2.7.3 (2019-03-21) ### Added diff --git a/db/languages/da b/db/languages/da new file mode 100644 index 00000000..d26c1220 --- /dev/null +++ b/db/languages/da @@ -0,0 +1,41 @@ +ERROR_NO_LICENSE="Ingen licensnøgle konfigureret" +ERROR_NO_UPLOAD_SERVER="Ingen upload server konfigureret" +GEN_CHECKING="Tjekker" +GEN_CURRENT_VERSION="Nuværende version" +GEN_DEBUG_MODE="Fejlfindingstilstand" +GEN_INITIALIZE_PROGRAM="Initialiserer program" +GEN_LATEST_VERSION="Seneste version" +GEN_PHASE="Fase" +GEN_PLUGINS_ENABLED="Plugins aktiverede" +GEN_UPDATE_AVAILABLE="opdatering tilgængelig" +GEN_VERBOSE_MODE="Detaljeret tilstand" +GEN_WHAT_TO_DO="At gøre" +NOTE_EXCEPTIONS_FOUND="Undtagelser fundet" +NOTE_EXCEPTIONS_FOUND_DETAILED="Nogle usædvanlige hændelser eller information var fundet" +NOTE_PLUGINS_TAKE_TIME="Bemærk: plugins har mere omfattende tests og kan tage flere minutter at fuldføre" +NOTE_SKIPPED_TESTS_NON_PRIVILEGED="Sprang over tests på grund af ikke-privilegeret tilstand" +SECTION_CUSTOM_TESTS="Brugerdefinerede Tests" +SECTION_MALWARE="Malware" +SECTION_MEMORY_AND_PROCESSES="Hukommelse og Processer" +STATUS_DISABLED="DEAKTIVERET" +STATUS_DONE="FÆRDIG" +STATUS_ENABLED="AKTIVERET" +STATUS_NOT_ENABLED="IKKE AKTIVERET" +STATUS_ERROR="FEJL" +STATUS_FOUND="FUNDET" +STATUS_YES="JA" +STATUS_NO="NEJ" +STATUS_OFF="FRA" +STATUS_OK="OK" +STATUS_ON="TIL" +STATUS_NONE="INGEN" +STATUS_NOT_FOUND="IKKE FUNDET" +STATUS_NOT_RUNNING="KØRER IKKE" +STATUS_RUNNING="KØRER" +STATUS_SKIPPED="SPRUNGET OVER" +STATUS_SUGGESTION="FORSLAG" +STATUS_UNKNOWN="UKENDT" +STATUS_WARNING="ADVARSEL" +STATUS_WEAK="SVAG" +TEXT_YOU_CAN_HELP_LOGFILE="Du kan hjælpe ved at bidrage med din logfil" +TEXT_UPDATE_AVAILABLE="opdatering tilgængelig" diff --git a/db/software-eol.db b/db/software-eol.db index 39edb2da..084a5815 100644 --- a/db/software-eol.db +++ b/db/software-eol.db @@ -11,9 +11,9 @@ # # CentOS # -os:CentOS 5:2017-03-31:1490911200: -os:CentOS 6:2020-11-30:1606690800: -os:CentOS 7:2024-06-30:1719698400: +os:CentOS release 5:2017-03-31:1490911200: +os:CentOS release 6:2020-11-30:1606690800: +os:CentOS Linux release 7:2024-06-30:1719698400: # # FreeBSD - https://www.freebsd.org/security/unsupported.html # @@ -43,4 +43,20 @@ os:Ubuntu 17.04:2018-01-01:1514761200: os:Ubuntu 17.10:2018-07-01:1530396000: os:Ubuntu 18.04:2023-05-01:1682892000: os:Ubuntu 18.10:2019-07-01:1561932000: -os:Ubuntu 19.04:2020-01-01:1577833200:
\ No newline at end of file +os:Ubuntu 19.04:2020-01-01:1577833200: +# +# Slackware - https://en.wikipedia.org/wiki/Slackware#Releases +# +os:Slackware Linux 8.1:2012-08-01:1343768400: +os:Slackware Linux 9.0:2012-08-01:1343768400: +os:Slackware Linux 9.1:2012-08-01:1343768400: +os:Slackware Linux 10.0:2012-08-01:1343768400: +os:Slackware Linux 10.1:2012-08-01:1343768400: +os:Slackware Linux 10.2:2012-08-01:1343768400: +os:Slackware Linux 11.0:2012-08-01:1343768400: +os:Slackware Linux 12.0:2012-08-01:1343768400: +os:Slackware Linux 12.1:2013-12-09:1386540000: +os:Slackware Linux 12.2:2013-12-09:1386540000: +os:Slackware Linux 13.0:2018-07-05:1530738000: +os:Slackware Linux 13.1:2018-07-05:1530738000: +os:Slackware Linux 13.37:2018-07-05:1530738000: diff --git a/db/tests.db b/db/tests.db index 641ea927..215c3595 100644 --- a/db/tests.db +++ b/db/tests.db @@ -169,11 +169,17 @@ HTTP-6712:test:security:webservers::Check nginx access logging: HTTP-6714:test:security:webservers::Check for missing error logs in nginx: HTTP-6716:test:security:webservers::Check for debug mode on error log in nginx: HTTP-6720:test:security:webservers::Check Nginx log files: -INSE-8002:test:security:insecure_services::Check for enabled inet daemon: -INSE-8004:test:security:insecure_services::Check for enabled inet daemon: -INSE-8006:test:security:insecure_services::Check configuration of inetd when disabled: +INSE-8000:test:security:insecure_services::Installed inetd package: +INSE-8002:test:security:insecure_services::Status of inet daemon: +INSE-8004:test:security:insecure_services::Presence of inetd configuration file: +INSE-8006:test:security:insecure_services::Check configuration of inetd when it is disabled: INSE-8016:test:security:insecure_services::Check for telnet via inetd: INSE-8050:test:security:insecure_services:MacOS:Check for insecure services on macOS systems: +INSE-8100:test:security:insecure_services::Installed xinetd package: +INSE-8116:test:security:insecure_services::Insecure services enabled via xinetd: +INSE-8200:test:security:insecure_services::Usage of TCP wrappers: +INSE-8300:test:security:insecure_services::Presence of rsh client: +INSE-8302:test:security:insecure_services::Presence of rsh server: KRNL-5622:test:security:kernel:Linux:Determine Linux default run level: KRNL-5677:test:security:kernel:Linux:Check CPU options and support: KRNL-5695:test:security:kernel:Linux:Determine Linux kernel version and release number: @@ -319,6 +325,7 @@ PKGS-7393:test:security:ports_packages::Check for Gentoo vulnerable packages: PKGS-7394:test:security:ports_packages:Linux:Check for Ubuntu updates: PKGS-7398:test:security:ports_packages::Check for package audit tool: PKGS-7410:test:security:ports_packages::Count installed kernel packages: +PKGS-7420:test:security:ports_packages::Detect toolkit to automatically download and apply upgrades: PRNT-2302:test:security:printers_spools:FreeBSD:Check for printcap consistency: PRNT-2304:test:security:printers_spools::Check cupsd status: PRNT-2306:test:security:printers_spools::Check CUPSd configuration file: diff --git a/include/binaries b/include/binaries index 18b54b2a..c3e5dff9 100644 --- a/include/binaries +++ b/include/binaries @@ -42,18 +42,39 @@ Display --indent 2 --text "- Checking system binaries..." LogText "Status: Starting binary scan..." - # Test if our PATH variable provides a set of paths - # If so, reverse the order. If we discover the same binary multiple times, the one first in PATH - # should be used. - # If PATH is empty, we use the predefined list in include/consts. Common paths first, then followed - # by more specific paths. This helps on the slightly ancient UNIX derivatives. + # Notes: + # - If PATH is empty, we use the predefined list in include/consts + # - Common paths first, then followed by more specific paths. This helps on the slightly ancient UNIX derivatives. + # - Avoid sorting the path list, as this might result in incorrect order of finding binaries (e.g. awk binary) + + # Test if our PATH variable provides a set of paths. If so, reverse the order. If we discover the same binary + # multiple times, the one first in PATH should be used. if [ ! -z "${PATH}" ]; then PATH_REVERSED=$(echo ${PATH} | awk -F: '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }') - BIN_PATHS=$(echo "${PATH_REVERSED} ${BIN_PATHS}" | tr ':' ' ') + BIN_PATHS=$(echo "${PATH_REVERSED}" | tr ':' ' ') fi - # Avoid sorting, as this might result in incorrect order of finding binaries (e.g. awk binary) - #SORTED_BIN_PATHS=$(echo ${BIN_PATHS} | tr ' ' '\n' | sort | uniq | tr '\n' ' ') + # First test available locations that may be suspicious or dangerous + for SCANDIR in ${BIN_PATHS}; do + FOUND=0 + if [ "${SCANDIR}" = "." ]; then FOUND=1; MSG="Found single dot (.) in PATH" + elif [ "${SCANDIR}" = ".." ]; then FOUND=1; MSG="Found double dot (..) in PATH" + elif echo ${SCANDIR} | grep '^\.\.' > /dev/null; then FOUND=1; MSG="Found path starting with double dot (..) in PATH" + elif echo ${SCANDIR} | grep '^[a-zA-Z]' > /dev/null; then FOUND=1; MSG="Found relative path in PATH" + fi + if [ ${FOUND} -eq 1 ]; then + # Stop execution if privileged, otherwise continue but warn user + if [ ${PRIVILEGED} -eq 1 ]; then + ExitFatal "Possible riskful location (${SCANDIR}) in PATH discovered. Quitting..." + else + Display --indent 4 --text "Warning: suspicious location (${SCANDIR}) in PATH" + ReportWarning "${TEST_NO}" "Possible riskful location in PATH discovered" "text:${MSG}" + sleep 1 + fi + fi + done + + # Now perform binary detection for SCANDIR in ${BIN_PATHS}; do LogText "Test: Checking binaries in directory ${SCANDIR}" ORGPATH="" @@ -99,6 +120,7 @@ afick.pl) AFICKBINARY=${BINARY}; LogText " Found known binary: afick (file integrity checker) - ${BINARY}" ;; aide) AIDEBINARY=${BINARY}; LogText " Found known binary: aide (file integrity checker) - ${BINARY}" ;; apache2) HTTPDBINARY=${BINARY}; LogText " Found known binary: apache2 (web server) - ${BINARY}" ;; + apt) APTBINARY=${BINARY}; LogText " Found known binary: apt (package manager) - ${BINARY}" ;; arch-audit) ARCH_AUDIT_BINARY="${BINARY}"; LogText " Found known binary: arch-audit (auditing utility to test for vulnerable packages) - ${BINARY}" ;; auditd) AUDITDBINARY=${BINARY}; LogText " Found known binary: auditd (audit framework) - ${BINARY}" ;; awk) AWKBINARY=${BINARY}; LogText " Found known binary: awk (string tool) - ${BINARY}" ;; @@ -109,6 +131,7 @@ base64) BASE64BINARY="${BINARY}"; LogText " Found known binary: base64 (encoding tool) - ${BINARY}" ;; blkid) BLKIDBINARY="${BINARY}"; LogText " Found known binary: blkid (information about block devices) - ${BINARY}" ;; bootctl) BOOTCTLBINARY="${BINARY}"; LogText " Found known binary: bootctl (systemd-boot manager utility) - ${BINARY}" ;; + bro) BROBINARY="${BINARY}"; LogText " Found known binary: bro (IDS) - ${BINARY}" ;; cat) CAT_BINARY="${BINARY}"; LogText " Found known binary: cat (generic file handling) - ${BINARY}" ;; cc) CCBINARY="${BINARY}"; COMPILER_INSTALLED=1; LogText " Found known binary: cc (compiler) - ${BINARY}" ;; chkconfig) CHKCONFIGBINARY=${BINARY}; LogText " Found known binary: chkconfig (administration tool) - ${BINARY}" ;; @@ -131,7 +154,8 @@ domainname) DOMAINNAMEBINARY="${BINARY}"; LogText " Found known binary: domainname (NIS domain) - ${BINARY}" ;; dpkg) DPKGBINARY="${BINARY}"; LogText " Found known binary: dpkg (package management) - ${BINARY}" ;; egrep) EGREPBINARY=${BINARY}; LogText " Found known binary: egrep (text search) - ${BINARY}" ;; - exim) EXIMBINARY="${BINARY}"; EXIMVERSION=$(${BINARY} -bV | grep 'Exim version' | awk '{ print $3 }' | xargs); LogText "Found ${BINARY} (version ${EXIMVERSION})" ;; + equery) EQUERYBINARY="${BINARY}"; LogText " Found known binary: query (package manager) - ${BINARY}" ;; + exim) EXIMBINARY="${BINARY}"; EXIMVERSION=$(${BINARY} -bV | grep 'Exim version' | awk '{ print $3 }' | xargs); LogText " Found known binary ${BINARY} (version ${EXIMVERSION})" ;; fail2ban-server) FAIL2BANBINARY="${BINARY}"; LogText " Found known binary: fail2ban (IPS tool) - ${BINARY}" ;; file) FILEBINARY="${BINARY}"; LogText " Found known binary: file (file type detection) - ${BINARY}" ;; find) FINDBINARY="${BINARY}"; LogText " Found known binary: find (search tool) - ${BINARY}" ;; @@ -164,7 +188,7 @@ lsattr) LSATTRBINARY="${BINARY}"; LogText " Found known binary: lsattr (file attributes) - ${BINARY}" ;; lsmod) LSMODBINARY="${BINARY}"; LogText " Found known binary: lsmod (kernel modules) - ${BINARY}" ;; lsof) LSOFBINARY="${BINARY}"; LogText " Found known binary: lsof (open files) - ${BINARY}" ;; - lsvg) LVSGBINARY=${BINARY}; LogText " Found known binary: lsvg (volume manager) - ${BINARY}" ;; + lsvg) LSVGBINARY=${BINARY}; LogText " Found known binary: lsvg (volume manager) - ${BINARY}" ;; lvdisplay) LVDISPLAYBINARY="${BINARY}"; LogText " Found known binary: lvdisplay (LVM tool) - ${BINARY}" ;; lynx) LYNXBINARY="${BINARY}"; LYNXVERSION=$(${BINARY} -version | grep "^Lynx Version" | cut -d ' ' -f3); LogText "Found known binary: lynx (browser) - ${BINARY} (version ${LYNXVERSION})" ;; maldet) LMDBINARY="${BINARY}"; MALWARE_SCANNER_INSTALLED=1; LogText " Found known binary: maldet (Linux Malware Detect, malware scanner) - ${BINARY}" ;; @@ -225,6 +249,7 @@ sha1|sha1sum|shasum) SHA1SUMBINARY="${BINARY}"; LogText " Found known binary: sha1/sha1sum/shasum (crypto hashing) - ${BINARY}" ;; sha256|sha256sum) SHA256SUMBINARY="${BINARY}"; LogText " Found known binary: sha256/sha256sum (crypto hashing) - ${BINARY}" ;; ssh-keyscan) SSHKEYSCANBINARY="${BINARY}"; LogText " Found known binary: ssh-keyscan (scanner for SSH keys) - ${BINARY}" ;; + suricata) SURICATABINARY="${BINARY}"; LogText " Found known binary: suricata (IDS) - ${BINARY}" ;; sysctl) SYSCTLBINARY="${BINARY}"; LogText " Found known binary: sysctl (kernel parameters) - ${BINARY}" ;; syslog-ng) SYSLOGNGBINARY="${BINARY}"; SYSLOGNGVERSION=$(${BINARY} -V 2>&1 | grep "^syslog-ng" | awk '{ print $2 }'); LogText "Found ${BINARY} (version ${SYSLOGNGVERSION})" ;; systemctl) SYSTEMCTLBINARY="${BINARY}"; LogText " Found known binary: systemctl (client to systemd) - ${BINARY}" ;; @@ -265,6 +290,28 @@ LogText "Result: checking of binaries skipped in this mode" fi + # Test if the basic system tools are defined. These will be used during the audit. + [ "${AWKBINARY:-}" ] || ExitFatal "awk binary not found" + [ "${CUTBINARY:-}" ] || ExitFatal "cut binary not found" + [ "${EGREPBINARY:-}" ] || ExitFatal "grep binary not found" + [ "${FINDBINARY:-}" ] || ExitFatal "find binary not found" + [ "${GREPBINARY:-}" ] || ExitFatal "grep binary not found" + [ "${HEADBINARY:-}" ] || ExitFatal "head binary not found" + [ "${LSBINARY:-}" ] || ExitFatal "ls binary not found" + [ "${PSBINARY:-}" ] || ExitFatal "ps binary not found" + [ "${SEDBINARY:-}" ] || ExitFatal "sed binary not found" + [ "${SORTBINARY:-}" ] || ExitFatal "sort binary not found" + [ "${TRBINARY:-}" ] || ExitFatal "tr binary not found" + [ "${UNIQBINARY:-}" ] || ExitFatal "uniq binary not found" + [ "${WCBINARY:-}" ] || ExitFatal "wc binary not found" + + # Test a few other tools that we did not specifically define (yet) + TOOLS="xxd" + for T in ${TOOLS}; do + DATA=$(type ${T}) + if [ $? -gt 0 ]; then ExitFatal "${T} binary not found"; fi + done + # #================================================================================ # Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com diff --git a/include/consts b/include/consts index 671ed1ca..207cde8c 100644 --- a/include/consts +++ b/include/consts @@ -46,6 +46,7 @@ unset LANG # # == Variable initializing == # + APTBINARY="" ARCH_AUDIT_BINARY="" AUDITORNAME="" AUDITCTLBINARY="" @@ -70,6 +71,7 @@ unset LANG CHKCONFIGBINARY="" CLAMCONF_BINARY="" CLAMSCANBINARY="" + CLANGBINARY="" COLORS=1 COMPLIANCE_ENABLE_CIS=0 COMPLIANCE_ENABLE_HIPAA=0 @@ -99,8 +101,11 @@ unset LANG DNFBINARY="" DOCKERBINARY="" DOCKER_DAEMON_RUNNING=0 + DPKGBINARY="" ECHOCMD="" ERROR_ON_WARNINGS=0 + EQUERYBINARY="" + EXIMBINARY="" FAIL2BANBINARY="" FILEBINARY="" FILEVALUE="" @@ -248,8 +253,10 @@ unset LANG SHOW_REPORT_SOLUTION=1 SHOW_TOOL_TIPS=1 # Show inline tool tips (default true) SHOW_WARNINGS_ONLY=0 + SKIP_GETHOSTID=0 SKIP_PLUGINS=0 SKIP_TESTS="" + SKIP_VM_DETECTION=0 SKIPREASON="" SKIPPED_TESTS_ROOTONLY="" SMTPCTLBINARY="" @@ -270,6 +277,7 @@ unset LANG TESTS_EXECUTED="" TESTS_SKIPPED="" TMPFILE="" + TOMOYOINITBINARY="" TOOLTIP_SHOWED=0 TOTAL_SUGGESTIONS=0 TOTAL_WARNINGS=0 diff --git a/include/functions b/include/functions index 95083600..a0246d68 100644 --- a/include/functions +++ b/include/functions @@ -86,6 +86,7 @@ # ReportSuggestion Add a suggestion to report file # ReportWarning Add a warning and priority to report file # SafePerms Check if a file has safe permissions +# SafeInput Test provided string to see if it contains unwanted characters # SearchItem Search a string in a file # ShowComplianceFinding Display a particular finding regarding compliance or a security standard # ShowSymlinkPath Show a path behind a symlink @@ -659,9 +660,9 @@ RemoveTempFiles LogText "${PROGRAM_NAME} ended with exit code 1." if [ $# -eq 1 ]; then - ${ECHOCMD} "" - ${ECHOCMD} "${RED}Fatal error${NORMAL}: ${WHITE}$1${NORMAL}" - ${ECHOCMD} "" + ${ECHOCMD:-echo} "" + ${ECHOCMD:-echo} "${RED}Fatal error${NORMAL}: ${WHITE}$1${NORMAL}" + ${ECHOCMD:-echo} "" fi exit 1 } @@ -805,15 +806,26 @@ # Name : GetHostID() # Description : Create an unique id for the system # - # Returns : optional value + # Returns : 0 = fetched or created IDs, 1 = failed, 2 = skipped # Usage : GetHostID ################################################################################ GetHostID() { + if [ ${SKIP_GETHOSTID} -eq 1 ]; then + return 2 + fi + if [ ! -z "${HOSTID}" -a ! -z "${HOSTID2}" ]; then Debug "Skipping creation of host identifiers, as they are already configured (via profile)" - return 1 + return 2 + fi + + if [ -f "${ROOTDIR}etc/lynis/hostids" ]; then + Debug "Used hostids file to fetch values" + HOSTID=$(grep "^hostid=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}') + HOSTID2=$(grep "^hostid2=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}') + return 0 fi FIND="" @@ -1110,8 +1122,9 @@ fi # Show an exception if no HostID could be created, to ensure each system (and scan) has one - if [ "${HOSTID}" = "" ]; then + if [ -z "${HOSTID}" ]; then ReportException "GetHostID" "No unique host identifier could be created." + return 1 elif [ ! -z "${HOSTID2}" ]; then return 0 fi @@ -1284,7 +1297,8 @@ if [ -z "${search}" ]; then ExitFatal "Missing process to search for when using IsRunning function"; fi RUNNING=0 - if [ ! -z "${PGREPBINARY}" ]; then + # AIX does not fully support pgrep options, so using ps instead + if [ ! -z "${PGREPBINARY}" -a ! "${OS}" = "AIX" ]; then FIND=$(${PGREPBINARY} ${pgrep_options} "${search}" | ${TRBINARY} '\n' ' ') else if [ -z "${PSOPTIONS}" ]; then @@ -1392,6 +1406,10 @@ ISVIRTUALMACHINE=2; VMTYPE="unknown"; VMFULLTYPE="Unknown" SHORT="" + if [ ${SKIP_VM_DETECTION} -eq 1 ]; then + return 2 + fi + # lxc environ detection if [ -z "${SHORT}" ]; then if [ -f /proc/1/environ ]; then @@ -1699,7 +1717,7 @@ ################################################################################ # Name : PackageIsInstalled() - # Description : Add a separator to log file between sections, tests etc + # Description : Determines if a package is installed # Returns : exit code # Notes : this function is not used yet, but created in advance to allow # the addition of support for all operating systems @@ -1714,11 +1732,20 @@ Fatal "Incorrect usage of PackageIsInstalled function" fi - if [ ! -z "${RPMBINARY}" ]; then - output=$(${RPMBINARY} --quiet -q ${package} 2> /dev/null) + if [ ! -z "${DNFBINARY}" ]; then + output=$(${DNFBINARY} --quiet --cacheonly --noplugins --assumeno info --installed ${package} > /dev/null 2>&1) exit_code=$? - elif ! -z "${DPKGBINARY}" ]; then - output=$(${DPKGBINARY} -l ${package} 2> /dev/null) + elif [ ! -z "${DPKGBINARY}" ]; then + output=$(${DPKGBINARY} -l ${package} 2> /dev/null | ${GREPBINARY} "^ii") + exit_code=$? + elif [ ! -z "${EQUERYBINARY}" ]; then + output=$(${EQUERYBINARY} --quiet ${package} > /dev/null 2>&1) + exit_code=$? # 0=package installed, 3=package not installed + elif [ ! -z "${PKG_BINARY}" ]; then + output=$(${PKG_BINARY} -N info ${package} >/dev/null 2>&1) + exit_code=$? # 0=package installed, 70=invalid package + elif [ ! -z "${RPMBINARY}" ]; then + output=$(${RPMBINARY} --quiet -q ${package} > /dev/null 2>&1) exit_code=$? elif [ ! -z "${ZYPPERBINARY}" ]; then output=$(${ZYPPERBINARY} --quiet --non-interactive search --installed -i ${PACKAGE} 2> /dev/null | grep "^i") @@ -1983,7 +2010,7 @@ for ITEM in ${VALUE}; do LogText "Result: found protocol ${ITEM}" case ${ITEM} in - "sslv2" | "sslv3") + "sslv2" | "sslv3" | "tlsv1") NGINX_WEAK_SSL_PROTOCOL_FOUND=1 ;; esac @@ -2485,75 +2512,128 @@ ################################################################################ + # Name : SafeInput() + # Description : Test provided string to see if it contains unwanted characters + # + # Input : string + optional class (parameter 2) + # Returns : 0 (input considered to be safe) or 1 (validation failed) + ################################################################################ + + SafeInput() { + exitcode=1 + # By default remove only control characters + if [ $# -eq 1 ]; then + input="$1" + cleaned=$(echo ${input} | tr -d '[:cntrl:]') + # If know what to test against, then see if input matches the specified class + elif [ $# -eq 2 ]; then + input="$1" + testchars="$2" + cleaned=$(echo $1 | tr -cd "${testchars}") + else + ExitFatal "No argument or too many arguments provided to SafeInput()" + fi + + if [ "${cleaned}" = "${input}" ]; then + exitcode=0 + fi + return ${exitcode} + } + + + + ################################################################################ # Name : SafePerms() - # Return : 0 (file OK) or break + # Description : + # Returns : 0 (file permissions OK) or break ################################################################################ SafePerms() { - if [ ${WARN_ON_FILE_ISSUES} -eq 1 ]; then + exitcode=1 + IS_PARAMETERS=0 + IS_PROFILE=0 + + if [ ${IGNORE_FILE_PERMISSION_ISSUES} -eq 0 ]; then PERMS_OK=0 LogText "Checking permissions of $1" - if [ $# -eq 1 ]; then - IS_PARAMETERS_FILE=$(echo $1 | grep "/parameters") + + if [ $# -gt 0 ]; then + + if [ $# -eq 2 ]; then + case "$2" in + "parameters") + IS_PARAMETERS=1 + ;; + "profile") + IS_PROFILE=1 + ;; + esac + else + FIND=$(echo $1 | grep "/parameters") + if [ $? -eq 0 ]; then IS_PARAMETERS=1; fi + fi # Check file permissions - if [ ! -f "$1" ]; then - LogText "Fatal error: file $1 does not exist. Quitting." - echo "Fatal error: file $1 does not exist" - ExitFatal - else - PERMS=$(ls -l $1) - # Owner permissions - OWNER=$(echo ${PERMS} | awk -F" " '{ print $3 }') - OWNERID=$(ls -n $1 | awk -F" " '{ print $3 }') - if [ ${PENTESTINGMODE} -eq 0 -a "${IS_PARAMETERS_FILE}" = "" ]; then - if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then - echo "Fatal error: file $1 should be owned by user 'root' when running it as root (found: ${OWNER})." - ExitFatal - fi - fi - # Group permissions - GROUP=$(echo ${PERMS} | awk -F" " '{ print $4 }') - GROUPID=$(ls -n $1 | awk -F" " '{ print $4 }') - - if [ ${PENTESTINGMODE} -eq 0 -a "${IS_PARAMETERS_FILE}" = "" ]; then - if [ ! "${GROUP}" = "root" -a ! "${GROUP}" = "wheel" -a ! "${GROUPID}" = "0" ]; then - echo "Fatal error: group owner of directory $1 should be owned by root user, wheel or similar (found: ${GROUP})." - ExitFatal - fi - fi - - # Owner permissions - OWNER_PERMS=$(echo ${PERMS} | cut -c2-4) - if [ ! "${OWNER_PERMS}" = "rw-" -a ! "${OWNER_PERMS}" = "r--" ]; then - echo "Fatal error: permissions of file $1 are not strict enough. Access to 'owner' should be read-write, or read. Change with: chmod 600 $1" - ExitFatal - fi - - # Owner permissions - GROUP_PERMS=$(echo ${PERMS} | cut -c5-7) - if [ ! "${GROUP_PERMS}" = "rw-" -a ! "${GROUP_PERMS}" = "r--" -a ! "${GROUP_PERMS}" = "---" ]; then - echo "Fatal error: permissions of file $1 are not strict enough. Access to 'group' should be read-write, read, or none. Change with: chmod 600 $1" - ExitFatal - fi - - # Other permissions - OTHER_PERMS=$(echo ${PERMS} | cut -c8-10) - if [ ! "${OTHER_PERMS}" = "---" -a ! "${OTHER_PERMS}" = "r--" ]; then - echo "Fatal error: permissions of file $1 are not strict enough. Access to 'other' should be denied or read-only. Change with: chmod 600 $1" - ExitFatal - fi - # Set PERMS_OK to 1 if no fatal errors occurred - PERMS_OK=1 - LogText "File permissions are OK" - return 0 - fi + if [ ! -f "$1" ]; then + LogText "Fatal error: file $1 does not exist. Quitting." + echo "Fatal error: file $1 does not exist" + ExitFatal + else + PERMS=$(ls -l $1) + + # Owner permissions + OWNER=$(echo ${PERMS} | awk -F" " '{ print $3 }') + OWNERID=$(ls -n $1 | awk -F" " '{ print $3 }') + if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then + if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then + echo "Fatal error: file $1 should be owned by user 'root' when running it as root (found: ${OWNER})." + ExitFatal + fi + fi + # Group permissions + GROUP=$(echo ${PERMS} | awk -F" " '{ print $4 }') + GROUPID=$(ls -n $1 | awk -F" " '{ print $4 }') + + if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then + if [ ! "${GROUP}" = "root" -a ! "${GROUP}" = "wheel" -a ! "${GROUPID}" = "0" ]; then + echo "Fatal error: group owner of directory $1 should be owned by root user, wheel or similar (found: ${GROUP})." + ExitFatal + fi + fi + + # Owner permissions + OWNER_PERMS=$(echo ${PERMS} | cut -c2-4) + if [ ! "${OWNER_PERMS}" = "rw-" -a ! "${OWNER_PERMS}" = "r--" ]; then + echo "Fatal error: permissions of file $1 are not strict enough. Access to 'owner' should be read-write, or read. Change with: chmod 600 $1" + ExitFatal + fi + + # Owner permissions + GROUP_PERMS=$(echo ${PERMS} | cut -c5-7) + if [ ! "${GROUP_PERMS}" = "rw-" -a ! "${GROUP_PERMS}" = "r--" -a ! "${GROUP_PERMS}" = "---" ]; then + echo "Fatal error: permissions of file $1 are not strict enough. Access to 'group' should be read-write, read, or none. Change with: chmod 600 $1" + ExitFatal + fi + + # Other permissions + OTHER_PERMS=$(echo ${PERMS} | cut -c8-10) + if [ ! "${OTHER_PERMS}" = "---" -a ! "${OTHER_PERMS}" = "r--" ]; then + echo "Fatal error: permissions of file $1 are not strict enough. Access to 'other' should be denied or read-only. Change with: chmod 600 $1" + ExitFatal + fi + # Set PERMS_OK to 1 if no fatal errors occurred + PERMS_OK=1 + LogText "File permissions are OK" + exitcode=0 + fi else ReportException "SafePerms()" "Invalid number of arguments for function" fi else PERMS_OK=1 - return 0 + exitcode=0 fi + return ${exitcode} + } diff --git a/include/helper_audit_dockerfile b/include/helper_audit_dockerfile index efe73d28..3d18556f 100644 --- a/include/helper_audit_dockerfile +++ b/include/helper_audit_dockerfile @@ -19,25 +19,14 @@ ################################################################################# if [ $# -eq 0 ]; then - Display --indent 2 --text "${RED}Error: ${WHITE}Provide URL or file${NORMAL}" + Display --indent 2 --text "${RED}Error: ${WHITE}Provide a file${NORMAL}" Display --text " "; Display --text " " ExitFatal else FILE=$(echo $1 | egrep "^http|https") if HasData "${FILE}"; then - CreateTempFile - TMP_FILE="${TEMP_FILE}" - Display --indent 2 --text "Downloading URL ${FILE} with wget" - wget -o ${TMP_FILE} ${FILE} - if [ $? -gt 0 ]; then - AUDIT_FILE="${TMP_FILE}" - else - if [ -f ${TMP_FILE} ]; then - rm -f ${TMP_FILE} - fi - Display --indent 2 --text "${RED}Error: ${WHITE}can not download file${NORMAL}" - ExitFatal - fi + echo "Provide a file (not a URL)" + ExitFatal else if [ -f $1 ]; then AUDIT_FILE="$1" @@ -70,13 +59,12 @@ fi IS_ALPINE=$(echo ${IMAGE} | grep -i alpine) IS_LATEST=$(echo ${TAG} | grep -i latest) - if [ ! "${IS_DEBIAN}" = "" ]; then IMAGE="debian"; fi - if [ ! "${IS_FEDORA}" = "" ]; then IMAGE="fedora"; fi - if [ ! "${IS_UBUNTU}" = "" ]; then IMAGE="ubuntu"; fi - if [ ! "${IS_ALPINE}" = "" ]; then IMAGE="alpine"; fi - - if [ ! "${IS_LATEST}" = "" ]; then - ReportWarning "dockerfile" "latest TAG used. Specifying the version is better." + if [ ! -z "${IS_DEBIAN}" ]; then IMAGE="debian"; fi + if [ ! -z "${IS_FEDORA}" ]; then IMAGE="fedora"; fi + if [ ! -z "${IS_UBUNTU}" ]; then IMAGE="ubuntu"; fi + if [ ! -z "${IS_ALPINE}" ]; then IMAGE="alpine"; fi + if [ ! -z "${IS_LATEST}" ]; then + ReportWarning "dockerfile" "latest TAG used. Specifying a targeted OS image and version is better for reproducible results." fi case ${IMAGE} in @@ -110,14 +98,14 @@ InsertSection "Basics" #FIND=$(egrep "^MAINTAINER" ${AUDIT_FILE} | sed 's/ /:space:/g') FIND=$(egrep -i "*MAINTAINER" ${AUDIT_FILE} | sed 's/=/ /g' | cut -d'"' -f 2) - if [ "${FIND}" = "" ]; then + if [ -z "${FIND}" ]; then ReportWarning "dockerfile" "No maintainer found. Unclear who created this file." else #MAINTAINER=$(echo ${FIND} | sed 's/:space:/ /g' | awk '{ if($1=="MAINTAINER") { print }}') MAINTAINER=$(echo ${FIND}) Display --indent 2 --text "Maintainer" --result "${MAINTAINER}" fi - + FIND=$(grep "^ENTRYPOINT" ${AUDIT_FILE} | cut -d' ' -f2 ) if [ "${FIND}" = "" ]; then ReportWarning "dockerfile" "No ENTRYPOINT defined in Dockerfile." @@ -127,7 +115,7 @@ InsertSection "Basics" fi FIND=$(grep "^CMD" ${AUDIT_FILE} | cut -d' ' -f2 ) - if [ "${FIND}" = "" ]; then + if [ -z "${FIND}" ]; then ReportWarning "dockerfile" "No CMD defines in Dockerfile." else CMD=$(echo ${FIND}) @@ -135,7 +123,7 @@ InsertSection "Basics" fi FIND=$(grep "^USER" ${AUDIT_FILE} | cut -d' ' -f2 ) - if [ "${FIND}" = "" ]; then + if [ -z "${FIND}" ]; then ReportWarning "dockerfile" "No user declared in Dockerfile. Container will execute command as root" else USER=$(echo ${FIND}) diff --git a/include/helper_generate b/include/helper_generate new file mode 100644 index 00000000..bdcfb44d --- /dev/null +++ b/include/helper_generate @@ -0,0 +1,89 @@ +#!/bin/sh + +################################################################################# +# +# Lynis +# ------------------ +# +# Copyright 2007-2013, Michael Boelen +# Copyright 2007-2019, 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. +# +###################################################################### +# +# Helper program to generate specific details such as host IDs +# +###################################################################### +# +# How to use: +# ------------ +# Run: lynis generate <option> +# +###################################################################### + +SAVEFILE=0 +GENERATE_ARGS="hostids" + +if [ $# -gt 0 ]; then + case $1 in + "hostids") + + if [ $# -gt 1 ]; then + shift + if [ $1 = "--save" ]; then + SAVEFILE=1 + fi + fi + + # Generate random host IDs + HOSTID=$(head -c20 < /dev/urandom | xxd -c 20 -p) + HOSTID2=$(head -c32 < /dev/urandom | xxd -c 32 -p) + + ${ECHOCMD} "Generated host identifiers" + ${ECHOCMD} "- hostid: ${HOSTID}" + ${ECHOCMD} "- hostid2: ${HOSTID2}" + + if [ ${SAVEFILE} -eq 1 ]; then + FILE="${ROOTDIR}etc/lynis/hostids" + if [ -f ${FILE} ]; then + ${ECHOCMD} "Error: hostids file already exists (${FILE})" + ${ECHOCMD} "Remove the file first and rerun command" + ExitFatal + else + OUTPUT=$(touch ${FILE} 2> /dev/null) + if [ $? -eq 0 ]; then + ${ECHOCMD} "Created hostids file (${FILE})" + echo "# generated using 'lynis generate hostids --save'" > ${FILE} + echo "hostid=${HOSTID}" >> ${FILE} + echo "hostid2=${HOSTID2}" >> ${FILE} + else + ExitFatal "Error: could not created hostids file (${FILE}). Issue with permissions?" + fi + fi + fi + + ExitClean + ;; + *) ${ECHOCMD} "Unknown argument '${RED}$1${NORMAL}' for lynis generate" ;; + esac +else + ${ECHOCMD} "\n ${WHITE}Provide an additional argument${NORMAL}\n\n" + for ITEM in ${GENERATE_ARGS}; do + ${ECHOCMD} " lynis generate ${BROWN}${ITEM}${NORMAL}" + done + ${ECHOCMD} "\n" + ${ECHOCMD} "" + ${ECHOCMD} "Extended help about the generate command can be provided with: $0 show commands generate" +fi + + +ExitClean + +# The End diff --git a/include/helper_show b/include/helper_show index 6e0738e6..874b3e1b 100644 --- a/include/helper_show +++ b/include/helper_show @@ -28,7 +28,7 @@ # ###################################################################### -COMMANDS="audit configure show update upload-only" +COMMANDS="audit configure generate show update upload-only" HELPERS="audit configure show update" OPTIONS="--auditor\n--cronjob (--cron)\n--debug\n--developer\n--help (-h)\n--license-key\n--log-file\n--manpage (--man)\n--no-colors\n--no-log\n--pentest\n--profile\n--plugin-dir\n--quick (-Q)\n--quiet (-q)\n--report-file\n--reverse-colors\n--skip-plugins\n--tests\n--tests-from-category\n--tests-from-group\n--upload\n--verbose\n--version (-V)\n--wait\n--warnings-only" @@ -94,6 +94,17 @@ AUDIT_HELP=" " +GENERATE_ARGS="( --save )" +GENERATE_HELP=" + Generate random value for hostid and hostid2 + ${WHITE}lynis generate hostids${NORMAL} + + Generate and save values + ${WHITE}lynis generate hostids --save${NORMAL} + +" + + UPDATE_ARGS="check info" UPDATE_HELP=" ${CYAN}update info${NORMAL} @@ -274,6 +285,7 @@ if [ $# -gt 0 ]; then shift case $1 in "audit") ${ECHOCMD} "${AUDIT_HELP}" ;; + "generate") ${ECHOCMD} "${GENERATE_HELP}" ;; "show") ${ECHOCMD} "${SHOW_HELP}" ;; "update") ${ECHOCMD} "${UPDATE_HELP}" ;; "upload-only") ${ECHOCMD} "${UPLOAD_ONLY_HELP}" ;; diff --git a/include/osdetection b/include/osdetection index 5ab80293..a6c18bb5 100644 --- a/include/osdetection +++ b/include/osdetection @@ -477,7 +477,7 @@ ECHONB="" case ${OS} in - "AIX") ECHOCMD="echo" ;; + "AIX") ECHOCMD="echo"; ECHONB="printf" ;; "DragonFly"|"FreeBSD"|"NetBSD") ECHOCMD="echo -e"; ECHONB="echo -n" ;; "macOS" | "Mac OS X") ECHOCMD="echo"; ECHONB="/bin/echo -n" ;; "Solaris") ECHOCMD="echo" ; test -f /usr/ucb/echo && ECHONB="/usr/ucb/echo -n" ;; diff --git a/include/parameters b/include/parameters index 96d63524..0798224e 100644 --- a/include/parameters +++ b/include/parameters @@ -22,8 +22,21 @@ # ################################################################################# # - # Check number of parameters submitted (at least one is needed) PARAMCOUNT=$# + + + # Input validation on provided parameters and their arguments + COUNT=0 + for I in "$@"; do + COUNT=$((COUNT + 1)) + if ! SafeInput "${I}"; then + echo "Execution of ${PROGRAM_NAME} stopped as we found unexpected input or invalid characters in argument ${COUNT}" + echo "Do you believe this is in error? Let us know: ${PROGRAM_AUTHOR_CONTACT}" + ExitFatal "Program execution stopped due to security measure" + fi + done + + # Parse arguments while [ $# -ge 1 ]; do case $1 in # Helpers first @@ -36,12 +49,13 @@ if [ $# -gt 1 ]; then case $2 in "dockerfile") - if [ "$3" = "" ]; then + if [ $# = 2 ]; then echo "${RED}Error: ${WHITE}Missing file name or URL${NORMAL}" - echo "Example: $0 audit dockerfile /root/Dockerfile" + echo "Example: $0 audit dockerfile /path/to/Dockerfile" ExitFatal else shift; shift + CHECK_BINARIES=1 HELPER_PARAMS="$1" HELPER="audit_dockerfile" break @@ -111,6 +125,24 @@ break ;; + # Generate data + generate) + CHECK_BINARIES=0 + HELPER="generate" + LOGTEXT=0 + QUIET=1 + RUN_HELPERS=1 + RUN_TESTS=0 + RUN_UPDATE_CHECK=0 + SKIP_GETHOSTID=1 + SKIP_PLUGINS=1 + SKIP_VM_DETECTION=1 + SHOW_PROGRAM_DETAILS=0 + SHOW_TOOL_TIPS=0 + shift; HELPER_PARAMS="$@" + break + ;; + # Show Lynis details show) CHECK_BINARIES=0 diff --git a/include/report b/include/report index b200f6be..2df666e4 100644 --- a/include/report +++ b/include/report @@ -22,55 +22,79 @@ # ################################################################################# # + + # Add data fields to report file + Report "dhcp_client_running=${DHCP_CLIENT_RUNNING}" + Report "arpwatch_running=${ARPWATCH_RUNNING}" + + # 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}" + + if [ ! -z "${INSTALLED_PACKAGES}" ]; then Report "installed_packages_array=${INSTALLED_PACKAGES}"; fi + + Report "package_audit_tool=${PACKAGE_AUDIT_TOOL}" + Report "package_audit_tool_found=${PACKAGE_AUDIT_TOOL_FOUND}" + Report "vulnerable_packages_found=${VULNERABLE_PACKAGES_FOUND}" + + # Hardening Index - # Define approximately how strong a machine has been hardened - # If no hardening has been found, set value to 1 - if [ ${HPPOINTS} -eq 0 ]; then HPPOINTS=1; HPTOTAL=100; fi - HPINDEX=$((HPPOINTS * 100 / HPTOTAL)) - HPAOBLOCKS=$((HPPOINTS * 20 / HPTOTAL)) - # Set color related to rating - if [ ${HPINDEX} -lt 50 ]; then - HPCOLOR="${RED}" - HIDESCRIPTION="System has not or a low amount been hardened" - elif [ ${HPINDEX} -gt 49 -a ${HPINDEX} -lt 80 ]; then - HPCOLOR="${YELLOW}" - HIDESCRIPTION="System has been hardened, but could use additional hardening" - elif [ ${HPINDEX} -gt 79 -a ${HPINDEX} -lt 90 ]; then - HPCOLOR="${GREEN}" - HIDESCRIPTION="System seem to be decent hardened" - elif [ ${HPINDEX} -gt 89 ]; then - HPCOLOR="${GREEN}" - HIDESCRIPTION="System seem to be well hardened" - fi + # Goal: + # Provide a visual way to show how much the system is hardened + # + # Important: + # The index gives a simplified version of the measures taken on the system. + # It should be used to get a first impression about the state of the system or to compare similar systems. + # Getting the maximum score (100 or full bar) does not indicate that the system is fully secured. + + # If no hardening has been found, set value to 1 + if [ ${HPPOINTS} -eq 0 ]; then HPPOINTS=1; HPTOTAL=100; fi + HPINDEX=$((HPPOINTS * 100 / HPTOTAL)) + HPAOBLOCKS=$((HPPOINTS * 20 / HPTOTAL)) + # Set color related to rating + if [ ${HPINDEX} -lt 50 ]; then + HPCOLOR="${RED}" + HIDESCRIPTION="System has not or a low amount been hardened" + elif [ ${HPINDEX} -gt 49 -a ${HPINDEX} -lt 80 ]; then + HPCOLOR="${YELLOW}" + HIDESCRIPTION="System has been hardened, but could use additional hardening" + elif [ ${HPINDEX} -gt 79 -a ${HPINDEX} -lt 90 ]; then + HPCOLOR="${GREEN}" + HIDESCRIPTION="System seem to be decent hardened" + elif [ ${HPINDEX} -gt 89 ]; then + HPCOLOR="${GREEN}" + HIDESCRIPTION="System seem to be well hardened" + fi - case ${HPAOBLOCKS} in - 0) HPBLOCKS="#"; HPEMPTY=" " ;; - 1) HPBLOCKS="#"; HPEMPTY=" " ;; - 2) HPBLOCKS="##"; HPEMPTY=" " ;; - 3) HPBLOCKS="###"; HPEMPTY=" " ;; - 4) HPBLOCKS="####"; HPEMPTY=" " ;; - 5) HPBLOCKS="#####"; HPEMPTY=" " ;; - 6) HPBLOCKS="######"; HPEMPTY=" " ;; - 7) HPBLOCKS="#######"; HPEMPTY=" " ;; - 8) HPBLOCKS="########"; HPEMPTY=" " ;; - 9) HPBLOCKS="#########"; HPEMPTY=" " ;; - 10) HPBLOCKS="##########"; HPEMPTY=" " ;; - 11) HPBLOCKS="###########"; HPEMPTY=" " ;; - 12) HPBLOCKS="############"; HPEMPTY=" " ;; - 13) HPBLOCKS="#############"; HPEMPTY=" " ;; - 14) HPBLOCKS="##############"; HPEMPTY=" " ;; - 15) HPBLOCKS="###############"; HPEMPTY=" " ;; - 16) HPBLOCKS="################"; HPEMPTY=" " ;; - 17) HPBLOCKS="#################"; HPEMPTY=" " ;; - 18) HPBLOCKS="##################"; HPEMPTY=" " ;; - 19) HPBLOCKS="###################"; HPEMPTY=" " ;; - 20) HPBLOCKS="####################"; HPEMPTY="" ;; - esac + case ${HPAOBLOCKS} in + 0) HPBLOCKS="#"; HPEMPTY=" " ;; + 1) HPBLOCKS="#"; HPEMPTY=" " ;; + 2) HPBLOCKS="##"; HPEMPTY=" " ;; + 3) HPBLOCKS="###"; HPEMPTY=" " ;; + 4) HPBLOCKS="####"; HPEMPTY=" " ;; + 5) HPBLOCKS="#####"; HPEMPTY=" " ;; + 6) HPBLOCKS="######"; HPEMPTY=" " ;; + 7) HPBLOCKS="#######"; HPEMPTY=" " ;; + 8) HPBLOCKS="########"; HPEMPTY=" " ;; + 9) HPBLOCKS="#########"; HPEMPTY=" " ;; + 10) HPBLOCKS="##########"; HPEMPTY=" " ;; + 11) HPBLOCKS="###########"; HPEMPTY=" " ;; + 12) HPBLOCKS="############"; HPEMPTY=" " ;; + 13) HPBLOCKS="#############"; HPEMPTY=" " ;; + 14) HPBLOCKS="##############"; HPEMPTY=" " ;; + 15) HPBLOCKS="###############"; HPEMPTY=" " ;; + 16) HPBLOCKS="################"; HPEMPTY=" " ;; + 17) HPBLOCKS="#################"; HPEMPTY=" " ;; + 18) HPBLOCKS="##################"; HPEMPTY=" " ;; + 19) HPBLOCKS="###################"; HPEMPTY=" " ;; + 20) HPBLOCKS="####################"; HPEMPTY="" ;; + esac - HPGRAPH="[${HPCOLOR}${HPBLOCKS}${NORMAL}${HPEMPTY}]" - LogText "Hardening index : [${HPINDEX}] [${HPBLOCKS}${HPEMPTY}]" - LogText "Hardening strength: ${HIDESCRIPTION}" + HPGRAPH="[${HPCOLOR}${HPBLOCKS}${NORMAL}${HPEMPTY}]" + LogText "Hardening index : [${HPINDEX}] [${HPBLOCKS}${HPEMPTY}]" + LogText "Hardening strength: ${HIDESCRIPTION}" # Only show overview if not running in quiet mode diff --git a/include/tests_authentication b/include/tests_authentication index fe8ece41..6c867da6 100644 --- a/include/tests_authentication +++ b/include/tests_authentication @@ -40,7 +40,12 @@ if [ ${SKIPTEST} -eq 0 ]; then # Search accounts with UID 0 LogText "Test: Searching accounts with UID 0" - FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^root:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0') + # Check if device is a QNAP, as the root user is called admin, and not root + if [ ${QNAP_DEVICE} -eq 1 ]; then + FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^admin:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0') + else + FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^root:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0') + fi if [ ! -z "${FIND}" ]; then Display --indent 2 --text "- Administrator accounts" --result "${STATUS_WARNING}" --color RED LogText "Result: Found more than one administrator accounts" @@ -669,8 +674,8 @@ if [ -d ${DIR} -a ! -L ${DIR} ]; then LogText "Result: directory ${DIR} exists" # Search in the specified directory - if [ "${OS}" = "Solaris" ]; then - # Solaris does not support -maxdepth + if [ "${OS}" = "AIX" -o "${OS}" = "Solaris" ]; then + # AIX/Solaris does not support -maxdepth FIND=$(find ${DIR} -type f -name "pam_*.so" -print | sort) else FIND=$(find ${DIR} -maxdepth 1 -type f -name "pam_*.so" -print | sort) @@ -698,25 +703,32 @@ # # Test : AUTH-9278 # Description : Search LDAP support in PAM files - Register --test-no AUTH-9278 --weight L --network NO --category security --description "Checking LDAP pam status" + Register --test-no AUTH-9278 --weight L --network NO --category security --description "Determine LDAP support in PAM files" if [ ${SKIPTEST} -eq 0 ]; then - LogText "Test: checking presence /etc/pam.d/common-auth" - if [ -f /etc/pam.d/common-auth ]; then - LogText "Result: file /etc/pam.d/common-auth exists" - LogText "Test: checking presence LDAP module" - FIND=$(${GREPBINARY} "^auth.*ldap" /etc/pam.d/common-auth) - if [ ! "${FIND}" = "" ]; then - LogText "Result: LDAP module present" - LogText "Output: ${FIND}" - Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_FOUND}" --color GREEN - LDAP_AUTH_ENABLED=1 - LDAP_PAM_ENABLED=1 + AUTH_FILES="${ROOTDIR}etc/pam.d/common-auth ${ROOTDIR}etc/pam.d/system-auth" + for FILE in ${AUTH_FILES}; do + LogText "Test: checking presence ${FILE}" + if [ -f ${FILE} ]; then + LogText "Result: file ${FILE} exists" + LogText "Test: checking presence LDAP module" + FIND=$(${GREPBINARY} "^auth.*ldap" ${FILE}) + if [ ! -z "${FIND}" ]; then + LogText "Result: LDAP module present" + LogText "Output: ${FIND}" + LDAP_AUTH_ENABLED=1 + LDAP_PAM_ENABLED=1 + else + LogText "Result: LDAP module not found" + fi else - LogText "Result: LDAP module not found" - Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_NOT_FOUND}" --color WHITE + LogText "Result: file ${FILE} not found, skipping test" fi + done + + if [ ${LDAP_PAM_ENABLED} -eq 1 ]; then + Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_FOUND}" --color GREEN else - LogText "Result: file /etc/pam.d/common-auth not found, skipping test" + Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_NOT_FOUND}" --color WHITE fi fi # diff --git a/include/tests_boot_services b/include/tests_boot_services index 5495938c..42b8dab1 100644 --- a/include/tests_boot_services +++ b/include/tests_boot_services @@ -96,7 +96,11 @@ ;; "init" | "initsplash") - SERVICE_MANAGER="SysV Init" + if [ -d ${ROOTDIR}etc/rc.d ]; then + SERVICE_MANAGER="bsdrc.d" + else + SERVICE_MANAGER="SysV Init" + fi ;; systemd) SERVICE_MANAGER="systemd" diff --git a/include/tests_filesystems b/include/tests_filesystems index a52bb66b..4e52ea5e 100644 --- a/include/tests_filesystems +++ b/include/tests_filesystems @@ -48,7 +48,11 @@ Display --indent 4 --text "- Checking ${I} mount point" --result SYMLINK --color WHITE elif [ -d ${I} ]; then LogText "Result: directory ${I} exists" - FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($3==MP) { print $3 }}') + case "${OS}" in + "AIX") FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($2==MP) { print $2 }}') ;; + *) FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($3==MP) { print $3 }}') ;; + esac + if IsEmpty "${FIND}"; then LogText "Result: ${I} not found in mount list. Directory most likely stored on / file system" Display --indent 4 --text "- Checking ${I} mount point" --result "${STATUS_SUGGESTION}" --color YELLOW @@ -158,7 +162,27 @@ done else LogText "Result: no EXT file systems found" - Report "file_systems_ext[]=none" + fi + fi +# +################################################################################# +# + # Test : FILE-6324 + # Description : Checking Linux XFS file systems + Register --test-no FILE-6324 --os Linux --weight L --network NO --category security --description "Checking XFS file systems" + if [ ${SKIPTEST} -eq 0 ]; then + LogText "Test: Checking for Linux XFS file systems" + FIND=$(${MOUNTBINARY} -t xfs | ${AWKBINARY} '{ print $3","$5 }') + if [ ! -z "${FIND}" ]; then + LogText "Result: found one or more XFS file systems" + for I in ${FIND}; do + FILESYSTEM=$(echo ${I} | ${CUTBINARY} -d ',' -f1) + FILETYPE=$(echo ${I} | ${CUTBINARY} -d ',' -f2) + LogText "File system: ${FILESYSTEM} (type: ${FILETYPE})" + Report "file_systems_xfs[]=${FILESYSTEM}|${FILETYPE}|" + done + else + LogText "Result: no XFS file systems found" fi fi # @@ -540,13 +564,13 @@ # --------------------------------------------------------- FILESYSTEMS_TO_CHECK="/boot:nodev,noexec,nosuid /dev/shm:nosuid,nodev,noexec /home:nodev,nosuid /tmp:nodev,noexec,nosuid /var:nosuid /var/log:nodev,noexec,nosuid /var/log/audit:nodev,noexec,nosuid /var/tmp:nodev,noexec,nosuid" - Register --test-no FILE-6374 --os Linux --weight L --network NO --category security --description "Checking /boot mount options" + Register --test-no FILE-6374 --os Linux --weight L --network NO --category security --description "Checking partitions mount options" if [ ${SKIPTEST} -eq 0 ]; then if [ -f /etc/fstab ]; then for I in ${FILESYSTEMS_TO_CHECK}; do FILESYSTEM=$(echo ${I} | ${CUTBINARY} -d: -f1) EXPECTED_FLAGS=$(echo ${I} | ${CUTBINARY} -d: -f2 | ${SEDBINARY} 's/,/ /g') - FS_FSTAB=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $3 } }' /etc/fstab) + FS_FSTAB=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $3 } }' ${ROOTDIR}etc/fstab) if [ "${FS_FSTAB}" = "glusterfs" ]; then EXPECTED_FLAGS=$(echo ${EXPECTED_FLAGS} | ${SEDBINARY} 's/\<\(nodev\|nosuid\)\> *//g') if [ -z "${EXPECTED_FLAGS}" ]; then @@ -554,7 +578,7 @@ fi fi if [ ! -z "${FS_FSTAB}" ]; then - FOUND_FLAGS=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $4 } }' /etc/fstab | ${SEDBINARY} 's/,/ /g' | ${TRBINARY} '\n' ' ') + FOUND_FLAGS=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $4 } }' ${ROOTDIR}etc/fstab | ${SEDBINARY} 's/,/ /g' | ${TRBINARY} '\n' ' ') LogText "File system: ${FILESYSTEM}" LogText "Expected flags: ${EXPECTED_FLAGS}" LogText "Found flags: ${FOUND_FLAGS}" @@ -562,7 +586,7 @@ FULLY_HARDENED=1 for FLAG in ${EXPECTED_FLAGS}; do FLAG_AVAILABLE=$(echo ${FOUND_FLAGS} | ${GREPBINARY} ${FLAG}) - if [ "${FLAG_AVAILABLE}" = "" ]; then + if [ -z "${FLAG_AVAILABLE}" ]; then LogText "Result: Could not find mount option ${FLAG} on file system ${FILESYSTEM}" FULLY_HARDENED=0 else diff --git a/include/tests_firewalls b/include/tests_firewalls index 85f2b150..735059fe 100644 --- a/include/tests_firewalls +++ b/include/tests_firewalls @@ -596,11 +596,6 @@ ################################################################################# # -# 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}" - WaitForKeyPress # diff --git a/include/tests_insecure_services b/include/tests_insecure_services index 277791d9..841189d8 100644 --- a/include/tests_insecure_services +++ b/include/tests_insecure_services @@ -18,7 +18,7 @@ # ################################################################################# # -# Unsecure services +# Insecure services # ################################################################################# # @@ -28,32 +28,55 @@ # INETD_ACTIVE=0 INETD_CONFIG_FILE="${ROOTDIR}etc/inetd.conf" + INETD_PACKAGE_INSTALLED=0 + XINETD_ACTIVE=0 + XINETD_CONFIG_FILE="${ROOTDIR}etc/xinetd.conf" + XINETD_CONFIG_DIR="${ROOTDIR}etc/xinetd.d" +# +################################################################################# +# + # Test : INSE-8000 + # Description : Check for installed inetd package + Register --test-no INSE-8000 --weight L --network NO --category security --description "Installed inetd package" + if [ ${SKIPTEST} -eq 0 ]; then + # Check for installed inetd daemon + LogText "Test: Checking if inetd is installed" + if PackageIsInstalled "inetd"; then + INETD_PACKAGE_INSTALLED=1 + LogText "Result: inetd is installed" + Display --indent 2 --text "- Installed inetd package" --result "${STATUS_FOUND}" --color YELLOW + #ReportSuggestion ${TEST_NO} "If there are no inetd services required, it is recommended that the daemon be removed" + else + LogText "Result: inetd is NOT installed" + Display --indent 2 --text "- Installed inetd package" --result "${STATUS_NOT_FOUND}" --color GREEN + fi + fi # ################################################################################# # # Test : INSE-8002 # Description : Check for inetd status - Register --test-no INSE-8002 --weight L --network NO --category security --description "Check for enabled inet daemon" + if [ ${INETD_PACKAGE_INSTALLED} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + Register --test-no INSE-8002 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled inet daemon" if [ ${SKIPTEST} -eq 0 ]; then # Check running processes LogText "Test: Searching for active inet daemon" - IsRunning inetd - if [ ${RUNNING} -eq 1 ]; then + if IsRunning "inetd"; then LogText "Result: inetd is running" - Display --indent 2 --text "- Checking inetd status" --result "ACTIVE" --color GREEN + Display --indent 4 --text "- inetd status" --result "ACTIVE" --color GREEN INETD_ACTIVE=1 else LogText "Result: inetd is NOT running" - Display --indent 2 --text "- Checking inetd status" --result "NOT ACTIVE" --color GREEN + Display --indent 4 --text "- inetd status" --result "NOT ACTIVE" --color GREEN fi fi # ################################################################################# # # Test : INSE-8004 - # Description : Check for inetd configuration file + # Description : Check for inetd configuration file (inetd) if [ ${INETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi - Register --test-no INSE-8004 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled inet daemon" + Register --test-no INSE-8004 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Presence of inetd configuration file" if [ ${SKIPTEST} -eq 0 ]; then # Check configuration file LogText "Test: Searching for file ${INETD_CONFIG_FILE}" @@ -73,15 +96,15 @@ if [ ${INETD_ACTIVE} -eq 0 -a -f ${INETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no INSE-8006 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check configuration of inetd when disabled" if [ ${SKIPTEST} -eq 0 ]; then - # Check if any service is enabled in /etc/inetd.conf (inetd is not active, see test 8002) - LogText "Test: check if all services are disabled if inetd is disabled" + # Check if any service is enabled in /etc/inetd.conf (inetd is not active, see test INSE-8002) + LogText "Test: check if all services are disabled when inetd is disabled" FIND=$(${GREPBINARY} -v "^#" ${INETD_CONFIG_FILE} | ${GREPBINARY} -v "^$") if [ -z "${FIND}" ]; then LogText "Result: no services found in ${INETD_CONFIG_FILE}" - Display --indent 4 --text "- Checking inetd.conf services" --result "${STATUS_OK}" --color GREEN + Display --indent 4 --text "- Checking enabled inetd services" --result "${STATUS_OK}" --color GREEN else LogText "Result: found services in inetd, even though inetd is not running" - Display --indent 4 --text "- Checking inetd.conf services" --result "${STATUS_SUGGESTION}" --color YELLOW + Display --indent 4 --text "- Checking enabled inetd services" --result "${STATUS_SUGGESTION}" --color YELLOW ReportSuggestion ${TEST_NO} "Although inetd is not running, make sure no services are enabled in ${INETD_CONFIG_FILE}, or remove inetd service" fi fi @@ -95,7 +118,7 @@ if [ ${SKIPTEST} -eq 0 ]; then LogText "Test: checking telnet presence in inetd configuration" FIND=$(${GREPBINARY} "^telnet" ${INETD_CONFIG_FILE}) - if [ "${FIND}" = "" ]; then + if [ -z "${FIND}" ]; then LogText "Result: telnet not enabled in ${INETD_CONFIG_FILE}" Display --indent 2 --text "- Checking inetd (telnet)" --result "${STATUS_NOT_FOUND}" --color GREEN AddHP 3 3 @@ -109,6 +132,289 @@ # ################################################################################# # + # Test : INSE-8100 + # Description : Check for installed xinetd daemon + Register --test-no INSE-8100 --weight L --network NO --category security --description "Check for installed xinetd daemon" + if [ ${SKIPTEST} -eq 0 ]; then + # Check for installed xinetd daemon + LogText "Test: Checking for installed xinetd daemon" + if PackageIsInstalled "xinetd"; then + LogText "Result: xinetd is installed" + Display --indent 2 --text "- Installed xinetd package" --result "${STATUS_FOUND}" --color YELLOW + ReportSuggestion ${TEST_NO} "If there are no xinetd services required, it is recommended that the daemon be removed" + else + LogText "Result: xinetd is NOT installed" + Display --indent 2 --text "- Installed xinetd package" --result "${STATUS_OK}" --color GREEN + fi + fi +# +################################################################################# +# + # Test : INSE-8102 + # Description : Check for xinetd status + Register --test-no INSE-8102 --weight L --network NO --category security --description "Check for active xinet daemon" + if [ ${SKIPTEST} -eq 0 ]; then + # Check running processes + LogText "Test: Searching for active extended internet services daemon (xinetd)" + if IsRunning "xinetd"; then + LogText "Result: xinetd is running" + Display --indent 4 --text "- xinetd status" --result "ACTIVE" --color GREEN + XINETD_ACTIVE=1 + else + LogText "Result: xinetd is NOT running" + Display --indent 4 --text "- xinetd status" --result "NOT ACTIVE" --color GREEN + fi + fi +# +################################################################################# +# + # Test : INSE-8104 + # Description : Check for xinetd configuration file + if [ ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + Register --test-no INSE-8104 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled xinet daemon" + if [ ${SKIPTEST} -eq 0 ]; then + # Check configuration file + LogText "Test: Searching for file ${XINETD_CONFIG_FILE}" + if [ -f "${XINETD_CONFIG_FILE}" ]; then + LogText "Result: ${XINETD_CONFIG_FILE} exists" + Display --indent 6 --text "- Configuration file (xinetd.conf)" --result "${STATUS_FOUND}" --color WHITE + else + LogText "Result: ${XINETD_CONFIG_FILE} does not exist" + Display --indent 6 --text "- Configuration file (xinetd.conf)" --result "${STATUS_NOT_FOUND}" --color WHITE + fi + fi +# +################################################################################# +# + # Test : INSE-8106 + # Description : Check for xinetd configuration file contents if xinetd is NOT active + if [ ${XINETD_ACTIVE} -eq 0 -a -f ${XINETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + Register --test-no INSE-8106 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check configuration of xinetd when disabled" + if [ ${SKIPTEST} -eq 0 ]; then + # Check if any service is enabled in /etc/xinetd.d (xinetd is not active, see test INSE-8102) + LogText "Test: check if all services are disabled if xinetd is disabled" + FIND=$(${GREPBINARY} -r "disable\s*=\s*no" ${XINETD_CONFIG_DIR}) + if [ -z "${FIND}" ]; then + LogText "Result: no services found in ${XINETD_CONFIG_DIR}" + Display --indent 6 --text "- Enabled xinetd.d services" --result "${STATUS_NOT_FOUND}" --color GREEN + else + LogText "Result: found services in ${XINETD_CONFIG_DIR}, even though xinetd is not running" + Display --indent 6 --text "- Enabled xinetd.d services" --result "${STATUS_FOUND}" --color YELLOW + ReportSuggestion ${TEST_NO} "Although xinetd is not running, make sure no services are enabled in ${XINETD_CONFIG_DIR}, or remove xinetd service" + fi + fi +# +################################################################################# +# + # Test : INSE-8116 + # Description : Check for insecure services enabled via xinetd + if [ ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + Register --test-no INSE-8116 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Insecure services enabled via xinetd" + if [ ${SKIPTEST} -eq 0 ]; then + XINETD_INSECURE_SERVICE_FOUND=0 + + ITEMS="chargen chargen-dgram chargen-stream daytime daytime-dgram daytime-stream discard discard-dgram discard-stream echo echo-dgram echo-stream time time-dgram time-stream ntalk rexec rlogin rsh talk telnet tftp" + + for SERVICE in ${ITEMS}; do + LogText "Test: checking service ${SERVICE}" + if ! SkipAtomicTest "${TEST_NO}:${SERVICE}"; then + FILE="${XINETD_CONFIG_DIR}/${SERVICE}" + if [ -f "${FILE}" ]; then + LogText "Test: checking status in xinetd configuration file (${FILE})" + FIND=$(${GREPBINARY} "disable\s*=\s*no" ${FILE}) + if [ ! -z "${FIND}" ]; then + LogText "Result: found insecure service enabled: ${SERVICE}" + XINETD_INSECURE_SERVICE_FOUND=1 + ReportSuggestion "${TEST_NO}" "Disable or remove any insecure services in the xinetd configuration" "${SERVICE}" "text:See log file for more details" + Report "insecure_service[]=${SERVICE}" + fi + fi + else + LogText "Result: skipped, as this item is excluded using the profile" + fi + done + + if [ ${XINETD_INSECURE_SERVICE_FOUND} -eq 0 ]; then + LogText "Result: no insecure services found in xinetd configuration" + Display --indent 6 --text "- Checking xinetd (insecure services)" --result "${STATUS_OK}" --color GREEN + AddHP 3 3 + else + LogText "Result: one ore more insecure services discovered in xinetd configuration" + Display --indent 6 --text "- Checking xinetd (insecure services)" --result "${STATUS_WARNING}" --color RED + AddHP 0 3 + fi + fi +# +################################################################################# +# + # Test : INSE-8150 + # Description : Check for rsync enabled via xinetd + #RSYNC_XINETD_CONFIG_FILE="${XINETD_CONFIG_DIR}/rsync" + #if [ ${XINETD_ACTIVE} -eq 1 -a -f ${RSYNC_XINETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + #Register --test-no INSE-8150 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for rsync via xinetd" + #if [ ${SKIPTEST} -eq 0 ]; then + # LogText "Test: checking rsync presence in xinetd configuration" + # FIND=$(${GREPBINARY} "disable\s*=\s*no" ${RSYNC_XINETD_CONFIG_FILE}) + # if [ "${FIND}" = "" ]; then + # LogText "Result: rsync not enabled in ${RSYNC_XINETD_CONFIG_FILE}" + # Display --indent 6 --text "- Checking xinetd (rsync)" --result "${STATUS_DISABLED}" --color GREEN + # else + # LogText "Result: rsync enabled in ${RSYNC_XINETD_CONFIG_FILE}" + # Display --indent 6 --text "- Checking xinetd (rsync)" --result "${STATUS_ENABLED}" --color RED + # ReportSuggestion "${TEST_NO}" "Disable rsync in xinetd configuration" + # fi + #fi +# +################################################################################# +# + # Test : INSE-8200 + # Description : Check if tcp_wrappers is installed when inetd/xinetd is active + if [ ${INETD_ACTIVE} -eq 1 -o ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + Register --test-no INSE-8200 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check if tcp_wrappers is installed when inetd/xinetd is active" + if [ ${SKIPTEST} -eq 0 ]; then + LogText "Test: Checking if tcp_wrappers is installed" + FOUND=0 + PACKAGES="tcp_wrappers tcpd" + for PACKAGE in ${PACKAGES}; do + if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi + done + if [ ${FOUND} -eq 1 ]; then + LogText "Result: tcp_wrappers is installed" + Display --indent 2 --text "- Checking tcp_wrappers installation" --result "${STATUS_OK}" --color GREEN + else + LogText "Result: tcp_wrappers is NOT installed" + Display --indent 2 --text "- Checking tcp_wrappers installation" --result "${STATUS_SUGGESTION}" --color YELLOW + #ReportSuggestion ${TEST_NO} "When network services are using the inetd/xinetd service, the tcp_wrappers package should be installed" + fi + fi +# +################################################################################# +# + # Test : INSE-8300 + # Description : Check if rsh client is installed + Register --test-no INSE-8300 --weight L --network NO --category security --description "Check if rsh client is installed" + if [ ${SKIPTEST} -eq 0 ]; then + LogText "Test: Checking if rsh client is installed" + FOUND=0 + PACKAGES="rsh rsh-client rsh-redone-client" + for PACKAGE in ${PACKAGES}; do + if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi + done + if [ ${FOUND} -eq 1 ]; then + LogText "Result: rsh client is installed" + Display --indent 2 --text "- Installed rsh client package" --result "${STATUS_SUGGESTION}" --color YELLOW + ReportSuggestion ${TEST_NO} "Remove rsh client when it is not in use or replace with the more secure SSH package" + else + LogText "Result: rsh client is NOT installed" + Display --indent 2 --text "- Installed rsh client package" --result "${STATUS_OK}" --color GREEN + fi + fi +# +################################################################################# +# + # Test : INSE-8302 + # Description : Check presence of rsh Trust Files + #Register --test-no INSE-8302 --weight L --network NO --category security --description "Check presence of rsh Trust Files" + #if [ ${SKIPTEST} -eq 0 ]; then + # # Check presence of Rsh Trust Files + # FOUND=0 + # for LINE in $(${CAT_BINARY} /etc/passwd | ${EGREPBINARY} -v '^(root|halt|sync|shutdown)' | ${AWKBINARY} -F: '($7 !="/sbin/nologin" && $7 != "/bin/false") { print }'); do + # USER=$(echo ${LINE} | ${CUTBINARY} -d: -f1) + # DIR=$(echo ${LINE} | ${CUTBINARY} -d: -f6) + # if [ -d ${DIR} ]; then + # for RHOSTS in ${DIR}/.rhosts; do + # if [ ! -h ${RHOSTS} -a -f ${RHOSTS} ]; then + # LogText "FOUND .rhosts file in home directory ${DIR} of ${USER}" + # FOUND=1 + # fi + # done + # fi + # done + # if [ -f /etc/hosts.equiv ];then + # LogText "FOUND /etc/hosts.equiv" + # FOUND=1 + # fi + # if [ ${FOUND} -eq 1 ]; then + # LogText "Result: found one or more Rsh Trust Files" + # Display --indent 4 --text "- Checking presence of Rsh Trust Files" --result "${STATUS_SUGGESTION}" --color YELLOW + # ReportSuggestion ${TEST_NO} "Remove every Rsh Trust Files as they can allow unauthenticated access to a system" + # else + # LogText "Result: no Rsh Trust Files found" + # Display --indent 4 --text "- Checking presence of Rsh Trust Files" --result "${STATUS_OK}" --color GREEN + # fi + #fi +# +################################################################################# +# + # Test : INSE-8304 + # Description : Check if rsh server is installed + Register --test-no INSE-8342 --weight L --network NO --category security --description "Check if rsh server is installed" + if [ ${SKIPTEST} -eq 0 ]; then + # Check if rsh server is installed + LogText "Test: Checking if rsh server is installed" + FOUND=0 + PACKAGES="rsh-server rsh-redone-server" + for PACKAGE in ${PACKAGES}; do + if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi + done + if [ ${FOUND} -eq 1 ]; then + LogText "Result: rsh server is installed" + Display --indent 2 --text "- Installed rsh server package" --result "${STATUS_SUGGESTION}" --color YELLOW + ReportSuggestion ${TEST_NO} "Remove the rsh-server package and replace with a more secure alternative like SSH" + Report "insecure_service[]=rsh-server" + else + LogText "Result: rsh server is NOT installed" + Display --indent 2 --text "- Installed rsh server package" --result "${STATUS_OK}" --color GREEN + fi + fi +# +################################################################################# +# + # Test : INSE-8310 + # Description : Check if telnet client is installed + Register --test-no INSE-8310 --weight L --network NO --category security --description "Check if telnet client is installed" + if [ ${SKIPTEST} -eq 0 ]; then + # Check if telnet client is installed + LogText "Test: Checking if telnet client is installed" + if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi + + if [ ${FOUND} -eq 1 ]; then + LogText "Result: telnet client is installed" + Display --indent 2 --text "- Installed telnet client package" --result "${STATUS_FOUND}" --color YELLOW + # Telnet client usage might be used for troubleshooting instead of system administration + #ReportSuggestion ${TEST_NO} "telnet client contain numerous security exposures and have been replaced with the more secure SSH package" + else + LogText "Result: telnet client is NOT installed" + Display --indent 2 --text "- Installed telnet client package" --result "${STATUS_OK}" --color GREEN + fi + fi +# +################################################################################# +# + # Test : INSE-8312 + # Description : Check if telnet server is installed + Register --test-no INSE-8322 --weight L --network NO --category security --description "Check if telnet server is installed" + if [ ${SKIPTEST} -eq 0 ]; then + # Check if TFTP server is installed + LogText "Test: Checking if telnet server is installed" + FOUND=0 + PACKAGES="telnetd telnet-server" + for PACKAGE in ${PACKAGES}; do + if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi + done + if [ ${FOUND} -eq 1 ]; then + LogText "Result: telnet server is installed" + Display --indent 2 --text "- Installed telnet server package" --result "${STATUS_FOUND}" --color YELLOW + ReportSuggestion ${TEST_NO} "Removing the ${FOUND} package and replace with SSH when possible" + Report "insecure_service[]=telnet-server" + else + LogText "Result: telnet server is NOT installed" + Display --indent 2 --text "- Installed telnet server package" --result "${STATUS_NOT_FOUND}" --color GREEN + fi + fi +# +################################################################################# +# if [ ! -z "${LAUNCHCTL_BINARY}" ]; then PREQS_MET="YES"; SKIPREASON=""; else PREQS_MET="NO"; SKIPREASON="No launchctl binary on this system"; fi Register --test-no INSE-8050 --os "macOS" --preqs-met ${PREQS_MET} --skip-reason "${SKIPREASON}" --weight M --network NO --category security --description "Check for insecure services on macOS" if [ ${SKIPTEST} -eq 0 ]; then diff --git a/include/tests_networking b/include/tests_networking index 3986220b..b43970ce 100644 --- a/include/tests_networking +++ b/include/tests_networking @@ -370,6 +370,7 @@ # Description : Check listening ports Register --test-no NETW-3012 --weight L --network NO --category security --description "Check listening ports" if [ ${SKIPTEST} -eq 0 ]; then + DATA="" FIND=""; FIND2="" COUNT=0 case ${OS} in @@ -381,24 +382,19 @@ FIND="" fi FIND2="" - ;; + ;; Linux) - if [ ! -z "${NETSTATBINARY}" ]; then + if [ -n "${SSBINARY}" ]; then + DATA=$(${SSBINARY} --query=udp,tcp -plnt | awk '{ if ($1!="Netid") { print "raw,ss,v1|"$1"|"$5"|"$7"|" }}' | sed 's/pid=[0-9]\{1,\},fd=[0-9]\{1,\}//g' | sed 's/users://' | sed 's/,)//g' | tr -d '()"') + elif [ -n "${NETSTATBINARY}" ]; then # UDP FIND=$(${NETSTATBINARY} -nlp 2> /dev/null | ${GREPBINARY} "^udp" | ${AWKBINARY} '{ print $4"|"$1"|"$6"|" }' | ${SEDBINARY} 's:|[0-9]*/:|:') # TCP FIND2=$(${NETSTATBINARY} -nlp 2> /dev/null | ${GREPBINARY} "^tcp" | ${AWKBINARY} '{ if($6=="LISTEN") { print $4"|"$1"|"$7"|" }}' | ${SEDBINARY} 's:|[0-9]*/:|:') else - if [ ! "${SSBINARY}" = "" ]; then - # UDP - FIND=$(${SSBINARY} -u -a -n 2> /dev/null | ${AWKBINARY} '{ print $4 }' | ${GREPBINARY} -v Local) - # TCP - FIND2=$(${SSBINARY} -t -a -n 2> /dev/null | ${AWKBINARY} '{ print $4 }' | ${GREPBINARY} -v Local) - else - ReportException "${TEST_NO}:1" "netstat and ss binary missing to gather listening ports" - fi + ReportException "${TEST_NO}:1" "netstat and ss binary missing to gather listening ports" fi - ;; + ;; macOS) if [ ! "${LSOFBINARY}" = "" ]; then @@ -409,9 +405,7 @@ fi # Not needed as we have a combined test FIND2="" - ;; - - + ;; NetBSD) if [ ! "${SOCKSTATBINARY}" = "" ]; then FIND=$(${SOCKSTATBINARY} 2> /dev/null | ${AWKBINARY} '{ if ($7 ~ /\*.\*/) print $5"|"$6"|"$2"|" }' | ${SORTBINARY} -u) @@ -419,7 +413,7 @@ FIND="" fi FIND2="" - ;; + ;; OpenBSD) if [ ! "${NETSTATBINARY}" = "" ]; then # UDP @@ -429,13 +423,20 @@ else ReportException "${TEST_NO}:3" "netstat missing to gather listening ports" fi - ;; + ;; *) # Got this exception? Provide your details and output of netstat or any other tool to determine this information. ReportException "${TEST_NO}:2" "Unclear what method to use, to determine listening port information" - ;; + ;; esac + if HasData "${DATA}"; then + for ITEM in ${DATA}; do + COUNT=$((COUNT + 1)) + Report "network_listen[]=${ITEM}" + done + fi + # Retrieve information from sockstat, when available LogText "Test: Retrieving sockstat information to find listening ports" if HasData "${FIND}"; then @@ -453,11 +454,10 @@ Report "network_listen_port[]=${ITEM}" done fi - if [ "${FIND}" = "" -a "${FIND2}" = "" ]; then + if [ -z "${DATA}" -a -z "${FIND}" ]; then Display --indent 2 --text "- Getting listening ports (TCP/UDP)" --result "${STATUS_SKIPPED}" --color YELLOW else Display --indent 2 --text "- Getting listening ports (TCP/UDP)" --result "${STATUS_DONE}" --color GREEN - Display --indent 6 --text "* Found ${COUNT} ports" fi fi # @@ -634,9 +634,6 @@ ################################################################################# # -Report "dhcp_client_running=${DHCP_CLIENT_RUNNING}" -Report "arpwatch_running=${ARPWATCH_RUNNING}" - WaitForKeyPress # diff --git a/include/tests_php b/include/tests_php index 363321cf..76606c64 100644 --- a/include/tests_php +++ b/include/tests_php @@ -42,6 +42,9 @@ ${ROOTDIR}etc/php5/apache2/php.ini \ ${ROOTDIR}etc/php5/fpm/php.ini \ ${ROOTDIR}private/etc/php.ini \ + ${ROOTDIR}etc/php/7.2/apache2/php.ini \ + ${ROOTDIR}etc/php/7.1/apache2/php.ini \ + ${ROOTDIR}etc/php/7.0/apache2/php.ini \ ${ROOTDIR}etc/php/7.2/cli/php.ini ${ROOTDIR}etc/php/7.2/fpm/php.ini \ ${ROOTDIR}etc/php/7.1/cli/php.ini ${ROOTDIR}etc/php/7.1/fpm/php.ini \ ${ROOTDIR}etc/php/7.0/cli/php.ini ${ROOTDIR}etc/php/7.0/fpm/php.ini \ diff --git a/include/tests_ports_packages b/include/tests_ports_packages index 1426a068..2d8b997e 100644 --- a/include/tests_ports_packages +++ b/include/tests_ports_packages @@ -344,7 +344,7 @@ COUNT=0 PACKAGE_AUDIT_TOOL_FOUND=1 PACKAGE_AUDIT_TOOL="zypper" - FIND=$(${ZYPPERBINARY} -n se -t package -i | ${AWKBINARY} '{ if ($1=="i") { print $3 } }') + FIND=$(${ZYPPERBINARY} --non-interactive -n se -t package -i | ${AWKBINARY} '{ if ($1=="i") { print $3 } }') if [ ! -z "${FIND}" ]; then for PKG in ${FIND}; do COUNT=$((COUNT + 1)) @@ -365,7 +365,7 @@ if [ ! -z "${ZYPPERBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no PKGS-7330 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Querying Zypper for vulnerable packages" if [ ${SKIPTEST} -eq 0 ]; then - FIND=$(${ZYPPERBINARY} -n pchk | ${GREPBINARY} "(0 security patches)") + FIND=$(${ZYPPERBINARY} --non-interactive pchk | ${GREPBINARY} "(0 security patches)") if [ ! -z "${FIND}" ]; then LogText "Result: No security updates found with Zypper" Display --indent 2 --text "- Using Zypper to find vulnerable packages" --result "${STATUS_NONE}" --color GREEN @@ -374,7 +374,7 @@ LogText "Result: Zypper found one or more installed packages which are vulnerable." ReportWarning ${TEST_NO} "Found one or more vulnerable packages installed" # Unfortunately zypper does not properly give back which package it is. Usually best guess is last word on the line - FIND=$(${ZYPPERBINARY} -n lp | ${AWKBINARY} '{ if ($5=="security" || $7=="security") { print $NF }}' | ${SEDBINARY} 's/:$//' | ${GREPBINARY} -v "^$" | ${SORTBINARY} -u) + FIND=$(${ZYPPERBINARY} --non-interactive lp | ${AWKBINARY} '{ if ($5=="security" || $7=="security") { print $NF }}' | ${SEDBINARY} 's/:$//' | ${GREPBINARY} -v "^$" | ${SORTBINARY} -u) LogText "List of vulnerable packages/version:" for PKG in ${FIND}; do VULNERABLE_PACKAGES_FOUND=1 @@ -930,7 +930,6 @@ AddHP 1 2 done ReportWarning ${TEST_NO} "Found one or more vulnerable packages." - ReportSuggestion ${TEST_NO} "Use 'yum --security update' to update your system" fi else LogText "Result: yum-security package not found" @@ -1055,7 +1054,8 @@ # # Test : PKGS-7392 # Description : Check Debian/Ubuntu vulnerable packages - if [ -x ${ROOTDIR}usr/bin/apt-get ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi + # Note : Skip for zypper-based systems + if [ -x ${ROOTDIR}usr/bin/apt-get -a -z "${ZYPPERBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no PKGS-7392 --os Linux --preqs-met ${PREQS_MET} --root-only YES --weight L --network YES --category security --description "Check for Debian/Ubuntu security updates" if [ ${SKIPTEST} -eq 0 ]; then VULNERABLE_PACKAGES_FOUND=0 @@ -1247,8 +1247,20 @@ Register --test-no PKGS-7410 --weight L --network NO --category security --description "Count installed kernel packages" if [ ${SKIPTEST} -eq 0 ]; then KERNELS=0 - if [ ! -z "${RPMBINARY}" ]; then - LogText "Test: Checking how many kernel packages are installed" + LogText "Test: Checking how many kernel packages are installed" + + if [ ! -z "${DPKGBINARY}" ]; then + KERNELS=$(${DPKGBINARY} -l 2> /dev/null | ${GREPBINARY} "linux-image-[0-9]" | ${WCBINARY} -l) + if [ ${KERNELS} -eq 0 ]; then + LogText "Result: found no kernels from dpkg -l output, which is unexpected" + ReportException "KRNL-5840:2" "Could not find any kernel packages from DPKG output" + elif [ ${KERNELS} -gt 5 ]; then + LogText "Result: found more than 5 kernel packages on the system, which might indicate lack of regular cleanups" + ReportSuggestion "${TEST_NO}" "Remove any unneeded kernel packages" "${KERNELS} kernels" "text:validate dpkg -l output and perform cleanup with apt autoremove" + else + LogText "Result: found ${KERNELS} kernel packages on the system, which is fine" + fi + elif [ ! -z "${RPMBINARY}" ]; then KERNELS=$(${RPMBINARY} -q kernel 2> /dev/null | ${WCBINARY} -l) if [ ${KERNELS} -eq 0 ]; then LogText "Result: found no kernels from rpm -q kernel output, which is unexpected" @@ -1256,22 +1268,77 @@ elif [ ${KERNELS} -gt 5 ]; then LogText "Result: found more than 5 kernel packages on the system, which might indicate lack of regular cleanups" ReportSuggestion "${TEST_NO}" "Remove any unneeded kernel packages with package-cleanup utility (--old-kernels)" - AddHP 4 5 else - LogText "Result: found ${KERNELS} on the system, which is fine" - AddHP 1 1 + LogText "Result: found ${KERNELS} kernel packages on the system, which is fine" fi fi + + Report "installed_kernel_packages=${KERNELS}" fi # ################################################################################# # + # Test : PKGS-7420 + # Description : Detect toolkit to automatically download and apply upgrades + Register --test-no PKGS-7420 --weight L --network NO --category security --description "Detect toolkit to automatically download and apply upgrades" + if [ ${SKIPTEST} -eq 0 ]; then + UNATTENDED_UPGRADES_TOOLKIT=0 + UNATTENDED_UPGRADES_TOOL="" + UNATTENDED_UPGRADES_OPTION_AVAILABLE=0 + + case "${OS}" in + "Linux") + case "${LINUX_VERSION}" in + "CentOS" | "Debian" | "Fedora" | "RHEL" | "Ubuntu") -if [ ! -z "${INSTALLED_PACKAGES}" ]; then Report "installed_packages_array=${INSTALLED_PACKAGES}"; fi + UNATTENDED_UPGRADES_OPTION_AVAILABLE=1 + # Test available tools for Linux + if [ -f "${ROOTDIR}bin/auter" ]; then + UNATTENDED_UPGRADES_TOOL="auter" + UNATTENDED_UPGRADES_TOOLKIT=1 + LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}" + Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}" + fi + if [ -f "${ROOTDIR}sbin/yum-cron" ]; then + UNATTENDED_UPGRADES_TOOL="yum-cron" + UNATTENDED_UPGRADES_TOOLKIT=1 + LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}" + Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}" + fi + if [ -f "${ROOTDIR}usr/bin/dnf-automatic" ]; then + UNATTENDED_UPGRADES_TOOL="dnf-automatic" + UNATTENDED_UPGRADES_TOOLKIT=1 + LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}" + Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}" + fi + if [ -f "${ROOTDIR}usr/bin/unattended-upgrade" ]; then + UNATTENDED_UPGRADES_TOOL="unattended-upgrade" + UNATTENDED_UPGRADES_TOOLKIT=1 + LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}" + Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}" + fi + ;; + esac + ;; + esac -Report "package_audit_tool=${PACKAGE_AUDIT_TOOL}" -Report "package_audit_tool_found=${PACKAGE_AUDIT_TOOL_FOUND}" -Report "vulnerable_packages_found=${VULNERABLE_PACKAGES_FOUND}" + if [ ${UNATTENDED_UPGRADES_OPTION_AVAILABLE} -eq 1 ]; then + if [ ${UNATTENDED_UPGRADES_TOOLKIT} -eq 1 ]; then + AddHP 5 5 + Display --indent 2 --text "- Toolkit for automatic upgrades (${UNATTENDED_UPGRADES_TOOL})" --result "${STATUS_FOUND}" --color GREEN + else + AddHP 1 5 + Display --indent 2 --text "- Toolkit for automatic upgrades" --result "${STATUS_NOTFOUND}" --color YELLOW + LogText "Result: no toolkit for automatic updates discovered" + ReportSuggestion "${TEST_NO}" "Consider using a tool to automatically apply upgrades" + fi + fi + + Report "unattended_upgrade_option_available=${UNATTENDED_UPGRADES_OPTION_AVAILABLE}" + fi +# +################################################################################# +# WaitForKeyPress diff --git a/include/tests_shells b/include/tests_shells index 8f9763b4..3a094ad8 100644 --- a/include/tests_shells +++ b/include/tests_shells @@ -31,9 +31,10 @@ # Files (interactive login shells): /etc/profile $HOME/.bash_profile # $HOME/.bash_login $HOME/.profile # Files (interactive non-login shells): $HOME/.bash_rc - + # # csh/tcsh # Files: /etc/csh.cshrc /etc/csh.login + # # zsh # Files: /etc/zshenv /etc/zsh/zshenv $HOME/.zshenv /etc/zprofile # /etc/zsh/zprofile $HOME/.zprofile /etc/zshrc /etc/zsh/zshrc @@ -68,8 +69,8 @@ ################################################################################# # # Test : SHLL-6211 - # Description : which shells are available according /etc/shells - Register --test-no SHLL-6211 --weight L --network NO --category security --description "Checking available and valid shells" + # Description : Determine available shell according /etc/shells + Register --test-no SHLL-6211 --weight L --network NO --category security --description "Available and valid shells" if [ ${SKIPTEST} -eq 0 ]; then LogText "Test: Searching for ${ROOTDIR}etc/shells" if [ -f ${ROOTDIR}etc/shells ]; then @@ -98,8 +99,8 @@ ################################################################################# # # Test : SHLL-6220 - # Description : check for idle session killing tools or settings - Register --test-no SHLL-6220 --weight L --network NO --category security --description "Checking available and valid shells" + # Description : Check for idle session killing tools or settings + Register --test-no SHLL-6220 --weight L --network NO --category security --description "Idle session killing tools or settings" if [ ${SKIPTEST} -eq 0 ]; then IDLE_TIMEOUT_METHOD="" @@ -22,6 +22,11 @@ # ################################################################################# # + # Code quality: don't allow using undefined variables + set -o nounset +# +################################################################################# +# # In Solaris /bin/sh is not POSIX, but /usr/xpg4/bin/sh is. # Switch to /usr/xpg4/bin/sh if it exists and we are not already running it. test "$_" != "/usr/xpg4/bin/sh" && test -f /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh "$0" "$@" @@ -35,10 +40,10 @@ PROGRAM_AUTHOR_CONTACT="lynis-dev@cisofy.com" # Version details - PROGRAM_RELEASE_DATE="2019-03-21" - PROGRAM_RELEASE_TIMESTAMP=1553157295 - PROGRAM_RELEASE_TYPE="final" # dev or final - PROGRAM_VERSION="2.7.3" + PROGRAM_RELEASE_DATE="2019-06-29" + PROGRAM_RELEASE_TIMESTAMP=1561383761 + PROGRAM_RELEASE_TYPE="dev" # dev or final + PROGRAM_VERSION="3.0.0" # Source, documentation and license PROGRAM_SOURCE="https://github.com/CISOfy/lynis" @@ -55,11 +60,6 @@ DISPLAY_LANG="${LANG}" # required by function Display to deal with multi-bytes characters. - # Code quality: - # Set strict checking for development version for first part of code. After - # initialization this is checked with strict profile option. - if [ ${PROGRAM_RELEASE_TYPE} = "dev" ]; then set -u; fi - # ################################################################################# # @@ -139,8 +139,7 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta ################################################################################# # # Perform a basic check for permissions. After including functions, using SafePerms() - WARN_ON_FILE_ISSUES=1 - WARN_ON_FILE_ISSUES_ASKED=0 + IGNORE_FILE_PERMISSION_ISSUES=0 FILES_TO_CHECK="consts functions" @@ -192,14 +191,10 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta printf "\n Option 2) Change ownership of the related files (or full directory).\n\n Commands (full directory):\n # cd ..\n # chown -R 0:0 lynis\n # cd lynis\n # ./lynis audit system" fi printf "\n\n[ Press ENTER to continue, or CTRL+C to cancel ]" - WARN_ON_FILE_ISSUES_ASKED=1 + IGNORE_FILE_PERMISSION_ISSUES=1 read DUMMY fi - if [ ${WARN_ON_FILE_ISSUES_ASKED} -eq 1 ]; then - WARN_ON_FILE_ISSUES=0 - fi - # Now include files if permissions are correct, or user decided to continue . ${INCLUDEDIR}/consts . ${INCLUDEDIR}/functions @@ -613,6 +608,9 @@ ${NORMAL} if [ ${EOL} -eq 1 ]; then echo " End-of-life: ${WARNING}YES${NORMAL}" ReportWarning "GEN-0010" "This version ${OS_VERSION} is marked end-of-life as of ${EOL_DATE}" + elif [ ${EOL} -eq 255 ]; then + # TODO - mark as item where community can provide help + LogText "Note: the end-of-life of '${OS_FULLNAME}' could not be checked. Entry missing in software-eol.db?" fi if [ ! -z "${OS_MODE}" ]; then echo " Operating system mode: ${OS_MODE}"; fi |