Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/CISOfy/lynis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lynis
diff options
context:
space:
mode:
Diffstat (limited to 'lynis')
-rwxr-xr-xlynis236
1 files changed, 152 insertions, 84 deletions
diff --git a/lynis b/lynis
index 5956290b..2d79fa4f 100755
--- a/lynis
+++ b/lynis
@@ -6,7 +6,7 @@
# ------------------
#
# Copyright 2007-2013, Michael Boelen
-# 2013-2016, CISOfy
+# 2013-now, CISOfy
#
# Web site: https://cisofy.com
#
@@ -24,26 +24,35 @@
#
# 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" "$@"
+ if [ "$(uname)" = "SunOS" ]; then
+ test "$_" != "/usr/xpg4/bin/sh" && test -f /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh "$0" "$@"
+ fi
+#
+#################################################################################
+#
+ # Code quality: don't allow using undefined variables
+ # Notes: $_ may be empty on FreeBSD
+ set -o nounset
#
#################################################################################
#
-
# Program information
PROGRAM_NAME="Lynis"
PROGRAM_AUTHOR="CISOfy"
PROGRAM_AUTHOR_CONTACT="lynis-dev@cisofy.com"
+ PROGRAM_WEBSITE="https://cisofy.com/lynis/"
# Version details
- PROGRAM_RELEASE_DATE="2018-10-26"
- PROGRAM_RELEASE_TIMESTAMP=1540556675
- PROGRAM_RELEASE_TYPE="final" # dev or final
- PROGRAM_VERSION="2.7.0"
+ PROGRAM_RELEASE_DATE="2020-03-20"
+ PROGRAM_RELEASE_TIMESTAMP=1584711965
+ PROGRAM_RELEASE_TYPE="pre-release" # pre-release or release
+ PROGRAM_VERSION="3.0.0"
# Source, documentation and license
PROGRAM_SOURCE="https://github.com/CISOfy/lynis"
- PROGRAM_WEBSITE="https://cisofy.com/lynis/"
- PROGRAM_COPYRIGHT="2007-2018, ${PROGRAM_AUTHOR} - ${PROGRAM_WEBSITE}"
+ PROGRAM_PACKAGE="https://packages.cisofy.com/"
+ PROGRAM_DOCUMENTATION="https://cisofy.com/docs/"
+ PROGRAM_COPYRIGHT="2007-2020, ${PROGRAM_AUTHOR} - ${PROGRAM_WEBSITE}"
PROGRAM_LICENSE="${PROGRAM_NAME} 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 the LICENSE file for details about using this software."
@@ -53,12 +62,6 @@
REPORT_version_major="1"; REPORT_version_minor="0"
REPORT_version="${REPORT_version_major}.${REPORT_version_minor}"
- 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
#
#################################################################################
@@ -67,57 +70,48 @@
#
#################################################################################
#
+ # Check setuid bit
+ if [ -u "$0" ]; then echo "The called binary has the set-user-id bit - As this is unusual, execution will be stopped."; exit 1; fi
+
# Work directory
WORKDIR=$(pwd)
# Test from which directories we can use all functions and tests
-
- INCLUDEDIR="" # Set default include directory to none
+ USE_CWD=0
+ if case "$@" in *--usecwd*) true;; *) false;; esac; then
+ USE_CWD=1
+ INCLUDEDIR="./include"
+ else
+ INCLUDEDIR=""
tINCLUDE_TARGETS="/usr/local/include/lynis /usr/local/lynis/include /usr/share/lynis/include ./include" # Default paths to check (CWD as last option, in case we run from standalone)
for I in ${tINCLUDE_TARGETS}; do
if [ "${I}" = "./include" ]; then
- if [ -d ${WORKDIR}/include ]; then INCLUDEDIR="${WORKDIR}/include"; fi
+ if [ -d "${WORKDIR}/include" ]; then INCLUDEDIR="${WORKDIR}/include"; fi
elif [ -d ${I} -a -z "${INCLUDEDIR}" ]; then
INCLUDEDIR=${I}
fi
done
+ fi
# Drop out if our include directory can't be found
- if [ -z "${INCLUDEDIR}" ]; then
- printf "%s" "
-Fatal error: can't find include directory
-Make sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
- exit 1
- fi
+ if [ -z "${INCLUDEDIR}" ]; then
+ printf "%s" "\nFatal error: can't find include directory\nMake sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
+ exit 1
+ fi
# Test for database directory
-
+ if [ ${USE_CWD} -eq 1 ]; then
+ DBDIR="./db"
+ else
DBDIR=""; tDB_TARGETS="/usr/local/share/lynis/db /usr/local/lynis/db /usr/share/lynis/db ./db"
for I in ${tDB_TARGETS}; do
if [ "${I}" = "./db" ]; then
- if [ -d ${WORKDIR}/db ]; then DBDIR="${WORKDIR}/db"; fi
+ if [ -d "${WORKDIR}/db" ]; then DBDIR="${WORKDIR}/db"; fi
elif [ -d ${I} -a -z "${DBDIR}" ]; then
DBDIR="${I}"
fi
done
-
- # Import translations. First import English to prefill all texts
- if [ ! -f ${DBDIR}/languages/en ]; then
- echo "Could not find languages directory (file: ${DBDIR}/languages/en)"
- exit 1
- else
- . ${DBDIR}/languages/en
- fi
-
- # Auto detection of language based on locale (first two characters). Set to English when nothing found.
- if [ -x "$(command -v locale)" ]; then
- LANGUAGE=$(locale | egrep "^LANG=" | cut -d= -f2 | cut -d_ -f1 | egrep "^[a-z]{2}$")
fi
- if [ -z "${LANGUAGE}" ]; then
- #Debug "Result: no (valid) language found, setting to default language (en)"
- LANGUAGE="en"
- fi
-
#
#################################################################################
#
@@ -125,7 +119,7 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
# Check user to determine file permissions later on. If we encounter Solaris, use related id binary instead
if [ -x /usr/xpg4/bin/id ]; then
MYID=$(/usr/xpg4/bin/id -u 2> /dev/null)
- elif [ $(uname) = "SunOS" ]; then
+ elif [ "$(uname)" = "SunOS" ]; then
MYID=$(id | tr '=' ' ' | tr '(' ' ' | awk '{ print $2 }' 2> /dev/null)
else
MYID=$(id -u 2> /dev/null)
@@ -134,13 +128,24 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
#
#################################################################################
#
-# Consts (bin paths, text strings, colors)
+# Set basic values and test permissions of the files to include, such as:
+# - consts: bin paths, text strings, colors
+# - functions: function library
#
#################################################################################
#
+ # Determine if we are root (UID = 0)
+ if [ ${MYID} -eq 0 ]; then
+ PRIVILEGED=1
+ PENTESTINGMODE=0
+ else
+ PRIVILEGED=0
+ # Set to pentesting mode if scan is without root privileges
+ PENTESTINGMODE=1
+ fi
+
# 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,12 +197,8 @@ 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
- read DUMMY
- fi
-
- if [ ${WARN_ON_FILE_ISSUES_ASKED} -eq 1 ]; then
- WARN_ON_FILE_ISSUES=0
+ IGNORE_FILE_PERMISSION_ISSUES=1
+ read -r void
fi
# Now include files if permissions are correct, or user decided to continue
@@ -206,11 +207,49 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
#
#################################################################################
#
+# Language settings
+#
+#################################################################################
+#
+ # Auto detection of language based on shell LANG variable. This is required by the Display() function to deal with multi-bytes characters.
+ DISPLAY_LANG="${LANG:-}"
+
+ # Extract the short notation of the language (first two characters).
+ if [ -x "$(command -v locale 2> /dev/null)" ]; then
+ LANGUAGE=$(locale | egrep "^LANG=" | cut -d= -f2 | cut -d_ -f1 | egrep "^[a-z]{2}$")
+ # Try locale command if shell variable had no value
+ if [ -z "${DISPLAY_LANG}" ]; then
+ DISPLAY_LANG=$(locale | egrep "^LANG=" | cut -d= -f2)
+ fi
+ else
+ LANGUAGE="en"
+ fi
+
+ # Set default language: 'en' (English) if no value is set
+ if [ -z "${LANGUAGE}" ]; then
+ LANGUAGE="en"
+ fi
+
+ # Import translations. First import English to prefill all texts
+ if [ -f ${DBDIR}/languages/en ]; then
+ if SafeFile "${DBDIR}/languages/en"; then
+ . ${DBDIR}/languages/en
+ else
+ ExitFatal "Incorrect ownership or permissions of language file (${DBDIR}/languages/en)"
+ fi
+ else
+ echo "Could not find languages directory (file: ${DBDIR}/languages/en)"
+ exit 1
+ fi
+#
+#################################################################################
+#
# Traps
#
#################################################################################
#
- trap CleanUp INT
+ trap CleanUp INT TERM
+ trap Status USR1
# Use safe umask for the files we create
umask 027
@@ -224,14 +263,6 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
SafePerms ${INCLUDEDIR}/parameters
. ${INCLUDEDIR}/parameters
- # Now determine if we are root (UID = 0)
- if [ ${MYID} -eq 0 ]; then
- PRIVILEGED=1
- else
- Debug "Starting Lynis non-privileged"
- # Implied pentesting mode if not performed by root user
- PENTESTINGMODE=1
- fi
# Disable logging if no alternative was provided
if [ ${PRIVILEGED} -eq 0 ]; then
@@ -399,21 +430,24 @@ ${YELLOW}Note: ${WHITE}Cancelling the program can leave temporary files behind${
${WHITE}Options:${NORMAL}
- ${GRAY}--no-log${NORMAL} : Don't create a log file
- ${GRAY}--pentest${NORMAL} : Non-privileged scan (useful for pentest)
- ${GRAY}--profile ${BROWN}<profile>${NORMAL} : Scan the system with the given profile file
- ${GRAY}--quick (-Q)${NORMAL} : Quick mode, don't wait for user input
+ ${WHITE}Alternative system audit modes${NORMAL}
+ ${GRAY}--forensics${NORMAL} : Perform forensics on a running or mounted system
+ ${GRAY}--pentest${NORMAL} : Non-privileged, show points of interest for pentesting
${WHITE}Layout options${NORMAL}
${GRAY}--no-colors${NORMAL} : Don't use colors in output
${GRAY}--quiet (-q)${NORMAL} : No output
${GRAY}--reverse-colors${NORMAL} : Optimize color display for light backgrounds
+ ${GRAY}--reverse-colours${NORMAL} : Optimize colour display for light backgrounds
${WHITE}Misc options${NORMAL}
${GRAY}--debug${NORMAL} : Debug logging to screen
+ ${GRAY}--no-log${NORMAL} : Don't create a log file
+ ${GRAY}--profile ${BROWN}<profile>${NORMAL} : Scan the system with the given profile file
${GRAY}--view-manpage (--man)${NORMAL} : View man page
${GRAY}--verbose${NORMAL} : Show more details on screen
${GRAY}--version (-V)${NORMAL} : Display version number and quit
+ ${GRAY}--wait${NORMAL} : Wait between a set of tests
${WHITE}Enterprise options${NORMAL}
${GRAY}--plugindir ${BROWN}<path>${NORMAL} : Define path of available plugins
@@ -421,6 +455,7 @@ ${YELLOW}Note: ${WHITE}Cancelling the program can leave temporary files behind${
More options available. Run '$0 show options', or use the man page.
+
"
if [ ${WRONGOPTION} -eq 1 ]; then
@@ -489,6 +524,7 @@ ${NORMAL}
if [ "${OS}" = "Linux" -a "${HOSTNAME}" = "${FQDN}" ]; then
FQDN=$(hostname -f 2> /dev/null)
fi
+
#
#################################################################################
#
@@ -521,8 +557,8 @@ ${NORMAL}
Report "os_fullname=${OS_FULLNAME}"
Report "os_version=${OS_VERSION}"
if [ "${OS}" = "Linux" ]; then Report "linux_version=${LINUX_VERSION}"; fi
- if [ ! -z "${OS_KERNELVERSION}" ]; then Report "os_kernel_version=${OS_KERNELVERSION}"; fi
- if [ ! -z "${OS_KERNELVERSION_FULL}" ]; then Report "os_kernel_version_full=${OS_KERNELVERSION_FULL}"; fi
+ if [ -n "${OS_KERNELVERSION}" ]; then Report "os_kernel_version=${OS_KERNELVERSION}"; fi
+ if [ -n "${OS_KERNELVERSION_FULL}" ]; then Report "os_kernel_version_full=${OS_KERNELVERSION_FULL}"; fi
Report "hostname=${HOSTNAME}"
@@ -533,6 +569,7 @@ ${NORMAL}
fi
Report "test_category=${TEST_CATEGORY_TO_CHECK}"
Report "test_group=${TEST_GROUP_TO_CHECK}"
+
#
#################################################################################
#
@@ -595,6 +632,7 @@ ${NORMAL}
echo "Make sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
exit 1
fi
+
#
#################################################################################
#
@@ -609,7 +647,16 @@ ${NORMAL}
echo " Operating system: ${OS}"
echo " Operating system name: ${OS_NAME}"
echo " Operating system version: ${OS_VERSION}"
- if [ ! -z "${OS_MODE}" ]; then echo " Operating system mode: ${OS_MODE}"; fi
+ LogText "EOL check: ${EOL}"
+ 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 [ -n "${OS_MODE}" ]; then echo " Operating system mode: ${OS_MODE}"; fi
echo " Kernel version: ${OS_KERNELVERSION}"
echo " Hardware platform: ${HARDWARE}"
echo " Hostname: ${HOSTNAME}"
@@ -632,9 +679,9 @@ ${NORMAL}
LogText "Operating system: ${OS}"
LogText "Operating system name: ${OS_NAME}"
LogText "Operating system version: ${OS_VERSION}"
- if [ ! -z "${OS_MODE}" ]; then LogText "Operating system mode: ${OS_MODE}"; fi
+ if [ -n "${OS_MODE}" ]; then LogText "Operating system mode: ${OS_MODE}"; fi
LogText "Kernel version: ${OS_KERNELVERSION}"
- if [ ! -z "${OS_KERNELVERSION_FULL}" ]; then
+ if [ -n "${OS_KERNELVERSION_FULL}" ]; then
LogText "Kernel version (full): ${OS_KERNELVERSION_FULL}"
fi
LogText "Hardware platform: ${HARDWARE}"
@@ -685,7 +732,7 @@ ${NORMAL}
LogText "Latest stable version : ${PROGRAM_LV}"
if [ ${PROGRAM_LV} -gt ${PROGRAM_AC} ]; then
# Check if current version is REALLY outdated (10 versions ago)
- PROGRAM_MINVERSION=$((${PROGRAM_LV} - 10))
+ PROGRAM_MINVERSION=$((PROGRAM_LV - 10))
LogText "Minimum required version : ${PROGRAM_MINVERSION}"
if [ ${PROGRAM_MINVERSION} -gt ${PROGRAM_AC} ]; then
Display --indent 2 --text "- Program update status... " --result "WARNING" --color RED
@@ -722,13 +769,12 @@ ${NORMAL}
OLD_RELEASE=0
TIME_DIFFERENCE_CHECK=10368000 # 4 months
- RELEASE_PLUS_TIMEDIFF=$((${PROGRAM_RELEASE_TIMESTAMP} + ${TIME_DIFFERENCE_CHECK}))
+ RELEASE_PLUS_TIMEDIFF=$((PROGRAM_RELEASE_TIMESTAMP + TIME_DIFFERENCE_CHECK))
if [ ${NOW} -gt ${RELEASE_PLUS_TIMEDIFF} ]; then
# Show if release is old, only if we didn't show it with normal update check
if [ ${UPDATE_AVAILABLE} -eq 0 ]; then
ReportSuggestion "LYNIS" "This release is more than 4 months old. Consider upgrading"
fi
- UPDATE_AVAILABLE=1
OLD_RELEASE=1
fi
@@ -774,6 +820,14 @@ ${NORMAL}
#
#################################################################################
#
+ # Test if we have a package manager available by testing for a dummy package (should not exist)
+ if PackageIsInstalled "__dummy__"; then
+ HAS_PACKAGE_MANAGER=1
+ LogText "Informational: package manager is used"
+ else
+ LogText "Informational: no known package manager for this system"
+ fi
+
# Use hardware detection capabilities
IsVirtualMachine
if IsContainer; then
@@ -840,15 +894,24 @@ ${NORMAL}
if [ -f ${PLUGIN_FILE} ]; then
FIND2=$(grep "^# PLUGIN_NAME=" ${PLUGIN_FILE} | awk -F= '{ print $2 }')
if [ ! "${FIND2}" = "" -a ! "${FIND2}" = "[plugin_name]" ]; then
- if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN=$((${N_PLUGIN} + 1)); fi
+ if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN=$((N_PLUGIN + 1)); fi
# Check if the plugin is enabled in any of the profiles
PLUGIN_ENABLED_STATE=0
for PROFILE in ${PROFILES}; do
LogText "Action: checking plugin status in profile: ${PROFILE}"
FIND3=$(grep "^plugin=${FIND2}" ${PROFILE})
- if [ ! -z "${FIND3}" ]; then
- LogText "Result: plugin enabled in profile (${PROFILE})"
- PLUGIN_ENABLED_STATE=1
+ if [ -n "${FIND3}" ]; then
+ FOUND=0
+ for I in ${DISABLED_PLUGINS}; do
+ if [ "${I}" = "${FIND2}" ]; then
+ FOUND=1
+ LogText "Result: plugin ${FIND2} is specifically disabled"
+ fi
+ done
+ if [ ${FOUND} -eq 0 ]; then
+ LogText "Result: plugin enabled in profile (${PROFILE})"
+ PLUGIN_ENABLED_STATE=1
+ fi
fi
done
if [ ${PLUGIN_ENABLED_STATE} -eq 1 ]; then
@@ -860,7 +923,7 @@ ${NORMAL}
if SafePerms ${PLUGINFILE}; then
LogText "Including plugin file: ${PLUGINFILE} (version: ${PLUGIN_VERSION})"
Report "plugin_enabled_phase${PLUGIN_PHASE}[]=${FIND2}|${PLUGIN_VERSION}|"
- if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN_ENABLED=$((${N_PLUGIN_ENABLED} + 1)); fi
+ if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN_ENABLED=$((N_PLUGIN_ENABLED + 1)); fi
Display --indent 2 --text "- ${CYAN}Plugin${NORMAL}: ${WHITE}${FIND2}${NORMAL}"
if [ ${PLUGIN_PHASE} -eq 1 ]; then Progress " ["; fi
. ${PLUGINFILE}
@@ -928,7 +991,7 @@ ${NORMAL}
LogText "Info: perform tests from all categories"
INCLUDE_TESTS="boot_services kernel memory_processes authentication shells \
- filesystems usb storage storage_nfs nameservices dns ports_packages networking printers_spools \
+ filesystems usb storage storage_nfs nameservices dns ports_packages networking printers_spoolers \
mail_messaging firewalls webservers ssh snmp databases ldap php squid logging \
insecure_services banners scheduling accounting time crypto virtualization containers \
mac_frameworks file_integrity tooling malware file_permissions homedirs \
@@ -942,7 +1005,7 @@ ${NORMAL}
for INCLUDE_TEST in ${INCLUDE_TESTS}; do
INCLUDE_FILE="${INCLUDEDIR}/tests_${INCLUDE_TEST}"
if [ -f ${INCLUDE_FILE} ]; then
- if SafePerms ${INCLUDE_FILE}; then
+ if SafeFile ${INCLUDE_FILE}; then
. ${INCLUDE_FILE}
else
LogText "Exception: skipping test category ${INCLUDE_TEST}, file ${INCLUDE_FILE} has bad permissions (should be 640, 600 or 400)"
@@ -1029,7 +1092,7 @@ ${NORMAL}
if [ -f ${INCLUDEDIR}/report ]; then SafePerms ${INCLUDEDIR}/report; . ${INCLUDEDIR}/report; fi
# Show tool tips
- if [ -f ${INCLUDEDIR}/hints_tips ]; then SafePerms ${INCLUDEDIR}/hints_tips; . ${INCLUDEDIR}/hints_tips; fi
+ if [ -f ${INCLUDEDIR}/tool_tips ]; then SafePerms ${INCLUDEDIR}/tool_tips; . ${INCLUDEDIR}/tool_tips; fi
LogText "================================================================================"
LogText "Tests performed: ${CTESTS_PERFORMED}"
@@ -1057,7 +1120,12 @@ ${NORMAL}
LogText "Program ended successfully"
LogText "================================================================================"
- if [ -z "${CUSTOM_PROFILE}" ]; then DisplayToolTip "Enhance ${PROGRAM_NAME} audits by adding your settings to custom.prf (see ${DEFAULT_PROFILE} for all settings)"; fi
+ # Tool tips
+
+ if [ ${QUIET} -eq 0 ]; then
+
+ if [ -z "${CUSTOM_PROFILE}" ]; then DisplayToolTip "Enhance ${PROGRAM_NAME} audits by adding your settings to custom.prf (see ${DEFAULT_PROFILE} for all settings)"; fi
+ fi
# Clean exit (Delete PID file)
if [ ${TOTAL_WARNINGS} -gt 0 ]; then
@@ -1075,4 +1143,4 @@ ${NORMAL}
#
#================================================================================
-# Lynis - Copyright 2007-2018, Michael Boelen, CISOfy - https://cisofy.com
+# Lynis - Copyright 2007-2020, Michael Boelen, CISOfy - https://cisofy.com