mirror of
https://github.com/CISOfy/lynis.git
synced 2026-03-11 08:55:28 +00:00
These two tests are essentially identical. There is no need separate the DragonFly and FreeBSD tests. This will make it easier to add support for other BSD systems.
1612 lines
81 KiB
Bash
1612 lines
81 KiB
Bash
#!/bin/sh
|
|
|
|
#################################################################################
|
|
#
|
|
# Lynis
|
|
# ------------------
|
|
#
|
|
# Copyright 2007-2013, Michael Boelen
|
|
# Copyright 2007-2020, 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.
|
|
#
|
|
#################################################################################
|
|
#
|
|
# User, Group and authentication tests
|
|
#
|
|
#################################################################################
|
|
#
|
|
LDAP_AUTH_ENABLED=0
|
|
LDAP_PAM_ENABLED=0
|
|
LDAP_CONF_LOCATIONS="${ROOTDIR}etc/ldap.conf ${ROOTDIR}etc/ldap/ldap.conf ${ROOTDIR}etc/openldap/ldap.conf ${ROOTDIR}usr/local/etc/ldap.conf ${ROOTDIR}usr/local/etc/openldap/ldap.conf"
|
|
PAM_FILE_LOCATIONS="${ROOTDIR}lib/arm-linux-gnueabihf/security ${ROOTDIR}lib/i386-linux-gnu/security ${ROOTDIR}lib/security ${ROOTDIR}lib/x86_64-linux-gnu/security ${ROOTDIR}lib64/security ${ROOTDIR}usr/lib /usr/lib/security"
|
|
SUDOERS_LOCATIONS="${ROOTDIR}etc/sudoers ${ROOTDIR}usr/local/etc/sudoers ${ROOTDIR}usr/pkg/etc/sudoers"
|
|
SUDOERS_FILE=""
|
|
#
|
|
#################################################################################
|
|
#
|
|
InsertSection "Users, Groups and Authentication"
|
|
|
|
# Test : AUTH-9204
|
|
# Description : Check users with UID zero (0)
|
|
# Notes : Ignores :0: in file if match is in NIS related line
|
|
Register --test-no AUTH-9204 --weight L --network NO --category security --description "Check users with an UID of zero"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
# Search accounts with UID 0
|
|
LogText "Test: Searching accounts with UID 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 [ -n "${FIND}" ]; then
|
|
Display --indent 2 --text "- Administrator accounts" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: Found more than one administrator accounts"
|
|
ReportWarning "${TEST_NO}" "Multiple users with UID 0 found in passwd file"
|
|
for USER in ${FIND}; do
|
|
LogText "Administrator account: ${USER}"
|
|
Report "user_with_uid_zero[]=${USER}"
|
|
if [ "${USER}" = "toor" ]; then
|
|
LogText "BSD note: default there is a user 'toor' installed. This account is considered useless unless it"
|
|
LogText "is assigned a password and used for daily operations or emergencies. ie: bad shell for root user."
|
|
ReportSuggestion "${TEST_NO}" "Use vipw to delete the 'toor' user if not used."
|
|
fi
|
|
done
|
|
else
|
|
Display --indent 2 --text "- Administrator accounts" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: No accounts found with UID 0 other than root."
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9208
|
|
# Description : Check non-unique accounts
|
|
Register --test-no AUTH-9208 --weight L --network NO --category security --description "Check non-unique accounts in passwd file"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking for non-unique accounts"
|
|
if [ "${OS}" = "DragonFly" -o "${OS}" = "FreeBSD" -o "${OS}" = "NetBSD" -o "${OS}" = "OpenBSD" ]; then
|
|
PASSWD_FILE="${ROOTDIR}etc/master.passwd"
|
|
else
|
|
PASSWD_FILE="${ROOTDIR}etc/passwd"
|
|
fi
|
|
# Check password file
|
|
if [ -f ${PASSWD_FILE} ]; then
|
|
FIND=$(${GREPBINARY} -v '^#' ${PASSWD_FILE} | ${CUTBINARY} -d ':' -f3 | ${SORTBINARY} | uniq -d)
|
|
if [ "${FIND}" = "" ]; then
|
|
Display --indent 2 --text "- Unique UIDs" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: all accounts found in ${PASSWD_FILE} are unique"
|
|
else
|
|
Display --indent 2 --text "- Unique UIDs" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: found multiple accounts with same UID"
|
|
LogText "Output (non-unique UIDs): ${FIND}"
|
|
ReportWarning "${TEST_NO}" "Multiple accounts found with same UID"
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Unique UIDs" --result "${STATUS_SKIPPED}" --color WHITE
|
|
LogText "Result: test skipped, ${PASSWD_FILE} file not available"
|
|
fi
|
|
LogText "Remarks: Non unique UIDs can be a risk for the system or part of a configuration mistake"
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9212
|
|
# Description : Test group file with chkgrp tool (ie FreeBSD)
|
|
LogText "Prerequisite test: /usr/sbin/chkgrp"
|
|
if [ -x ${ROOTDIR}usr/sbin/chkgrp ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9212 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Test group file"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
Display --indent 2 --text "- Checking chkgrp tool" --result "${STATUS_FOUND}" --color GREEN
|
|
LogText "Result: /usr/sbin/chkgrp binary found. Using this to perform next test(s)."
|
|
LogText "Test: Testing consistency of /etc/group file"
|
|
FIND=$(${ROOTDIR}usr/sbin/chkgrp | ${GREPBINARY} -v 'is fine')
|
|
if [ "${FIND}" = "" ]; then
|
|
Display --indent 4 --text "- Checking consistency of /etc/group file" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: chkgrp test performed, Group file seems to be ok."
|
|
else
|
|
Display --indent 4 --text "- Checking consistency of /etc/group file" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: chkgrp found some errors. Run the tool manually to see details."
|
|
LogText "chkgrp output: ${FIND}"
|
|
ReportWarning "${TEST_NO}" "chkgrp reported inconsistencies in /etc/group file"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9216
|
|
# Description : Check /etc/group and shadow group files
|
|
# Notes : Run grpck to test group files (most likely /etc/group and shadow group files)
|
|
if [ -n "${GRPCKBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9216 --preqs-met ${PREQS_MET} --weight L --network NO --root-only YES --category security --description "Check group and shadow group files"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking for grpck binary output"
|
|
|
|
case ${OS} in
|
|
"AIX") FIND=$(${GRPCKBINARY} -n ALL 2> /dev/null ; echo $?) ;;
|
|
"Linux")
|
|
if [ "${LINUX_VERSION}" = "SuSE" ]; then
|
|
FIND=$(${GRPCKBINARY} -q -r > /dev/null ; echo $?)
|
|
else
|
|
FIND=$(${GRPCKBINARY} -r 2> /dev/null ; echo $?)
|
|
fi
|
|
;;
|
|
*) FIND=$(${GRPCKBINARY} 2> /dev/null ; echo $?) ;;
|
|
esac
|
|
|
|
# Check exit-code
|
|
if [ "${FIND}" = "0" ]; then
|
|
Display --indent 2 --text "- Consistency of group files (grpck)" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: grpck binary didn't find any errors in the group files"
|
|
else
|
|
Display --indent 2 --text "- Consistency of group files (grpck)" --result "${STATUS_WARNING}" --color RED
|
|
ReportWarning "${TEST_NO}" "grpck binary found errors in one or more group files"
|
|
fi
|
|
unset FIND
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9218
|
|
# Description : Check login shells for passwordless accounts
|
|
# Notes : Results should be checked
|
|
Register --test-no AUTH-9218 --os "DragonFly FreeBSD" --weight L --network NO --category security --description "Check login shells for passwordless accounts"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
LogText "Test: Checking login shells"
|
|
if [ -f ${ROOTDIR}etc/master.passwd ]; then
|
|
# Check for all shells, except: (/usr)/sbin/nologin /nonexistent
|
|
FIND=$(${GREPBINARY} "[a-z]:\*:" ${ROOTDIR}etc/master.passwd | ${EGREPBINARY} -v '^#|/sbin/nologin|/usr/sbin/nologin|/nonexistent' | ${SEDBINARY} 's/ /!space!/g')
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 2 --text "- Login shells" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
Display --indent 2 --text "- Login shells" --result "${STATUS_WARNING}" --color RED
|
|
for LINE in ${FIND}; do
|
|
LINE=$(echo ${LINE} | ${SEDBINARY} 's/!space!/ /g')
|
|
SHELL=$(echo ${LINE} | ${AWKBINARY} -F: '{ print $10 }')
|
|
LogText "Output: ${LINE}"
|
|
if [ -z "${SHELL}" ]; then
|
|
LogText "Result: found no shell on line"
|
|
else
|
|
LogText "Result: found possible harmful shell ${SHELL}"
|
|
if [ -f ${SHELL} ]; then
|
|
LogText "Result: shell ${SHELL} does exist"
|
|
FOUND=1
|
|
else
|
|
LogText "Result: shell ${SHELL} does not exist"
|
|
ReportSuggestion "${TEST_NO}" "Determine if account is needed, as shell ${SHELL} does not exist"
|
|
fi
|
|
fi
|
|
done
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
ReportWarning "${TEST_NO}" "Possible harmful shell found (for passwordless account!)"
|
|
fi
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Login shells" --result "${STATUS_SKIPPED}" --color WHITE
|
|
LogText "Result: No ${ROOTDIR}etc/master.passwd file found"
|
|
fi
|
|
unset LINE SHELL
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9222
|
|
# Description : Check unique group IDs
|
|
Register --test-no AUTH-9222 --weight L --network NO --category security --description "Check unique groups (IDs)"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking for non unique group ID's in /etc/group"
|
|
FIND=$(${GREPBINARY} -v '^#' ${ROOTDIR}etc/group | ${GREPBINARY} -v '^$' | ${AWKBINARY} -F: '{ print $3 }' | ${SORTBINARY} | uniq -d)
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 2 --text "- Unique group IDs" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: All group ID's are unique"
|
|
Report "auth_group_ids_unique=1"
|
|
else
|
|
Display --indent 2 --text "- Unique group IDs" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: Found the same group ID multiple times"
|
|
for I in ${FIND}; do
|
|
Report "auth_groups_nonunique[]=${I}"
|
|
LogText "Non-unique group: ${I}"
|
|
done
|
|
ReportSuggestion "${TEST_NO}" "Check your /etc/group file and correct any inconsistencies"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9226
|
|
# Description : Check unique group names
|
|
if [ -f ${ROOTDIR}etc/group ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9226 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check unique group names"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking for non unique group names in ${ROOTDIR}etc/group"
|
|
FIND=$(${GREPBINARY} -v '^#' ${ROOTDIR}etc/group | ${GREPBINARY} -v '^$' | ${AWKBINARY} -F: '{ print $1 }' | ${SORTBINARY} | uniq -d)
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 2 --text "- Unique group names" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: All group names are unique"
|
|
Report "auth_group_names_unique=1"
|
|
else
|
|
Display --indent 2 --text "- Unique group names" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: Found the same group name multiple times"
|
|
for I in ${FIND}; do
|
|
Report "auth_groups_nonunique[]=${I}"
|
|
LogText "Non-unique group: ${I}"
|
|
done
|
|
ReportSuggestion "${TEST_NO}" "Check your ${ROOTDIR}etc/group file and correct any inconsistencies"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9228
|
|
# Description : Check password file consistency with pwck
|
|
# Notes : Operating systems include Linux, Solaris
|
|
if [ -x ${ROOTDIR}usr/sbin/pwck ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9228 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check password file consistency with pwck"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking password file consistency (pwck)"
|
|
TESTED=0
|
|
case ${OS} in
|
|
"Linux")
|
|
FIND=$(${ROOTDIR}usr/sbin/pwck -q -r 2> /dev/null; echo $?)
|
|
TESTED=1
|
|
;;
|
|
"Solaris" | "HP-UX")
|
|
FIND=$(${ROOTDIR}usr/sbin/pwck 2> /dev/null; echo $?)
|
|
TESTED=1
|
|
;;
|
|
*)
|
|
LogText "Dev: found ${ROOTDIR}usr/sbin/pwck, but unsure how to call it on this operating system"
|
|
ReportException "${TEST_NO}:1" "Found ${ROOTDIR}usr/sbin/pwck, but unsure how to call it on this operating system"
|
|
;;
|
|
esac
|
|
# Only display if this test has been executed
|
|
if [ ${TESTED} -eq 1 -a "${FIND}" = "0" ]; then
|
|
Display --indent 2 --text "- Password file consistency" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: pwck check didn't find any problems"
|
|
AddHP 2 2
|
|
else
|
|
Display --indent 2 --text "- Password file consistency" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
LogText "Result: pwck found one or more errors/warnings in the password file."
|
|
ReportSuggestion "${TEST_NO}" "Run pwck manually and correct any errors in the password file"
|
|
AddHP 0 2
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9229
|
|
# Description : Check password hashing methods vs. recommendations in crypt(5)
|
|
# Notes : Applicable to all Unix-like OS
|
|
# Requires read access to /etc/shadow (if it exists)
|
|
Register --test-no AUTH-9229 --root-only YES --weight L --network NO --category security --description "Check password hashing methods"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking password hashing methods"
|
|
SHADOW="";
|
|
if [ -e ${ROOTDIR}etc/shadow ]; then SHADOW="${ROOTDIR}etc/shadow"; fi
|
|
FIND=$(${CAT_BINARY} ${ROOTDIR}etc/passwd ${SHADOW} | ${AWKBINARY} -F : '{print length($2) ":" $2 }' | while read METHOD; do
|
|
case ${METHOD} in
|
|
1:\* | 1:x | 0: | *:!*)
|
|
# disabled | shadowed | no password | locked account
|
|
;;
|
|
*:\$5\$*| *:\$6\$*)
|
|
# sha256crypt | sha512crypt: check number of rounds, should be >5000
|
|
ROUNDS=$(echo "${METHOD}" | sed -n 's/.*rounds=\([0-9]*\)\$.*/\1/gp')
|
|
if [ -z "${ROUNDS}" ]; then
|
|
echo 'sha256crypt/sha512crypt(default<=5000rounds)'
|
|
elif [ "${ROUNDS}" -le 5000 ]; then
|
|
echo 'sha256crypt/sha512crypt(<=5000rounds)'
|
|
fi
|
|
;;
|
|
*:\$y\$* | *:\$gy\$* | *:\$2b\$* | *:\$7\$*)
|
|
# yescrypt | gost-yescrypt | bcrypt | scrypt
|
|
;;
|
|
*:_*)
|
|
echo bsdicrypt
|
|
;;
|
|
*:\$1\$*)
|
|
echo md5crypt
|
|
;;
|
|
*:\$3\$*)
|
|
echo NT
|
|
;;
|
|
*:\$md5*)
|
|
echo SunMD5
|
|
;;
|
|
*:\$sha1*)
|
|
echo sha1crypt
|
|
;;
|
|
13:* | 178:*)
|
|
echo bigcrypt/descrypt
|
|
;;
|
|
*)
|
|
echo "Unknown password hashing method ${METHOD}. Please report to lynis-dev@cisofy.com"
|
|
;;
|
|
esac
|
|
done | ${SORTBINARY} -u | ${TRBINARY} '\n' ' ')
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 2 --text "- Password hashing methods" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: no poor password hashing methods found"
|
|
AddHP 2 2
|
|
else
|
|
Display --indent 2 --text "- Password hashing methods" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
LogText "Result: poor password hashing methods found: ${FIND}"
|
|
ReportSuggestion "${TEST_NO}" "Check PAM configuration, add rounds if applicable and expire passwords to encrypt with new values"
|
|
AddHP 0 2
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9230
|
|
# Description : Check group password hashing rounds in login.defs
|
|
# Notes : Applicable to all Unix-like OS
|
|
PREQS_MET="NO"
|
|
if [ -f ${ROOTDIR}etc/login.defs ]; then
|
|
PREQS_MET="YES"
|
|
fi
|
|
Register --test-no AUTH-9230 --preqs-met ${PREQS_MET} --root-only NO --weight L --network NO --category security --description "Check group password hashing rounds"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking SHA_CRYPT_MIN_ROUNDS option in ${ROOTDIR}etc/login.defs"
|
|
FIND=$(${GREPBINARY} "^SHA_CRYPT_MIN_ROUNDS" ${ROOTDIR}etc/login.defs | ${AWKBINARY} '{ if ($1=="SHA_CRYPT_MIN_ROUNDS") { print $2 } }')
|
|
if [ -z "${FIND}" -o "${FIND}" = "0" ]; then
|
|
LogText "Result: number of minimum rounds used by the encryption algorithm is not configured"
|
|
Display --indent 2 --text "- Checking minimum group password hashing rounds" --result "${STATUS_DISABLED}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Configure minimum encryption algorithm rounds in /etc/login.defs"
|
|
AddHP 0 2
|
|
elif [ "${FIND}" -lt 5000 ]; then
|
|
LogText "Result: low number of minimum encryption algorithm rounds found: ${FIND}"
|
|
PASSWORD_MINIMUM_ROUNDS=${FIND}
|
|
Display --indent 2 --text "- Group password hashing rounds (minimum)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
AddHP 1 2
|
|
else
|
|
LogText "Result: number of encryption algorithm rounds is ${FIND}"
|
|
PASSWORD_MINIMUM_ROUNDS=${FIND}
|
|
Display --indent 2 --text "- Group password hashing rounds (minimum)" --result CONFIGURED --color GREEN
|
|
AddHP 2 2
|
|
fi
|
|
|
|
LogText "Test: Checking SHA_CRYPT_MAX_ROUNDS option in ${ROOTDIR}etc/login.defs"
|
|
FIND=$(${GREPBINARY} "^SHA_CRYPT_MAX_ROUNDS" ${ROOTDIR}etc/login.defs | ${AWKBINARY} '{ if ($1=="SHA_CRYPT_MAX_ROUNDS") { print $2 } }')
|
|
if [ -z "${FIND}" -o "${FIND}" = "0" ]; then
|
|
LogText "Result: number of maximum rounds used by the encryption algorithm is not configured"
|
|
Display --indent 2 --text "- Checking maximum group password hashing rounds" --result "${STATUS_DISABLED}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Configure maximum encryption algorithm rounds in /etc/login.defs"
|
|
AddHP 0 2
|
|
elif [ "${FIND}" -lt 10000 ]; then
|
|
LogText "Result: low number of maximum encryption algorithm rounds found: ${FIND}"
|
|
PASSWORD_MINIMUM_ROUNDS=${FIND}
|
|
Display --indent 2 --text "- Group password hashing rounds (maximum)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
AddHP 1 2
|
|
else
|
|
LogText "Result: number of encryption algorithm rounds is ${FIND}"
|
|
PASSWORD_MINIMUM_ROUNDS=${FIND}
|
|
Display --indent 2 --text "- Group password hashing rounds (maximum)" --result CONFIGURED --color GREEN
|
|
AddHP 2 2
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9234
|
|
# Description : Query user accounts
|
|
# Notes : AIX: 100+
|
|
# HPUX: 100+
|
|
# macOS doesn't have any user info in /etc/passwd, users are managed with opendirectoryd)
|
|
# OpenBSD/NetBSD: 1000-60000, excluding 32767 (default)
|
|
# Arch Linux / CentOS / Ubuntu: 1000+
|
|
Register --test-no AUTH-9234 --weight L --network NO --category security --description "Query user accounts"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Read system users (including root user) from password database (e.g. /etc/passwd)"
|
|
FIND=""
|
|
|
|
case ${OS} in
|
|
"AIX")
|
|
LogText "AIX real users output (ID = 0, or 100+):"
|
|
FIND=$(${AWKBINARY} -F: '($3 >= 100 && $3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd)
|
|
;;
|
|
|
|
"FreeBSD")
|
|
LogText "FreeBSD real users output (ID = 0, or 1000+, but not 65534):"
|
|
FIND=$(${AWKBINARY} -F: '($3 >= 1000 && $3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd)
|
|
;;
|
|
|
|
"Linux")
|
|
UID_MIN=""
|
|
if [ -f ${ROOTDIR}etc/login.defs ]; then
|
|
UID_MIN=$(${GREPBINARY} "^UID_MIN" /etc/login.defs | ${AWKBINARY} '{print $2}')
|
|
LogText "Result: found minimal user id specified: ${UID_MIN}"
|
|
fi
|
|
if [ "${UID_MIN}" = "" ]; then UID_MIN="1000"; fi
|
|
LogText "Linux real users output (ID = 0, or ${UID_MIN}+, but not 65534):"
|
|
FIND=$(${AWKBINARY} -v UID_MIN="${UID_MIN}" -F: '($3 >= UID_MIN && $3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd)
|
|
;;
|
|
|
|
"macOS")
|
|
LogText "macOS real users output (ID = 0, or 500-599) using dscacheutil"
|
|
FIND_USERS=$(dscacheutil -q user | ${GREPBINARY} -A 3 -B 2 -e "^uid: 5[0-9][0-9]" | ${GREPBINARY} "^name: " | ${AWKBINARY} '{print $2}')
|
|
if [ -n "${FIND_USERS}" ]; then
|
|
for FUSERNAME in ${FIND_USERS}; do
|
|
FDETAILS=$(dscacheutil -q user -a name ${FUSERNAME} | ${GREPBINARY} "^uid: " | ${AWKBINARY} '{print $2}')
|
|
FIND="${FUSERNAME},${FDETAILS} ${FIND}"
|
|
done
|
|
else
|
|
FIND=""
|
|
fi
|
|
;;
|
|
|
|
"NetBSD"|"OpenBSD")
|
|
if [ -f ${ROOTDIR}etc/usermgmt.conf ]; then
|
|
UID_RANGE=$(${GREPBINARY} "^range" ${ROOTDIR}etc/usermgmt.conf | ${AWKBINARY} '{ sub(/\.\./, "-", $2); print $2 }')
|
|
fi
|
|
if [ -n "${UID_RANGE}" ]; then
|
|
LogText "Result: found configured user id range specified: ${UID_RANGE}"
|
|
UID_MIN=$(echo $UID_RANGE | ${AWKBINARY} -F- '{ print $1 }')
|
|
UID_MAX=$(echo $UID_RANGE | ${AWKBINARY} -F- '{ print $2 }')
|
|
else
|
|
UID_MIN=1000
|
|
UID_MAX=60000
|
|
LogText "Result: no configured user id range specified; using default ${UID_MIN}-${UID_MAX}"
|
|
fi
|
|
LogText "${OS} real users output (ID = 0, or ${UID_MIN}-${UID_MAX}, but not 32767):"
|
|
FIND=$(${AWKBINARY} -v UID_MIN="${UID_MIN}" -v UID_MAX="${UID_MAX}" -F: '($3 >= UID_MIN && $3 <= UID_MAX && $3 != 32767) || ($3 == 0) { print $1","$3 }' /etc/passwd)
|
|
;;
|
|
|
|
"Solaris")
|
|
LogText "Solaris real users output (ID =0, or 100+, but not 60001/65534):"
|
|
FIND=$(${AWKBINARY} -F: '($3 >= 100 && $3 != 60001 && $3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd)
|
|
;;
|
|
|
|
*)
|
|
# Want to help improving Lynis? Determine what user IDs belong to normal user accounts
|
|
ReportException "${TEST_NO}:1" "Can not determine user accounts"
|
|
;;
|
|
esac
|
|
|
|
# Check if we got any output
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 4 --text "Result: No users found/unknown result"
|
|
LogText "Result: Querying of system users skipped"
|
|
Display --indent 2 --text "- Query system users (non daemons)" --result "${STATUS_UNKNOWN}" --color YELLOW
|
|
else
|
|
Display --indent 2 --text "- Query system users (non daemons)" --result "${STATUS_DONE}" --color GREEN
|
|
for I in ${FIND}; do
|
|
if [ -n "${I}" ]; then
|
|
LogText "Real user: ${I}"
|
|
Report "real_user[]=${I}"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9240
|
|
# Description : Query NIS+ authentication support
|
|
Register --test-no AUTH-9240 --weight L --network NO --category security --description "Query NIS+ authentication support"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if [ -f /etc/nsswitch.conf ]; then
|
|
FIND=$(${EGREPBINARY} "^passwd" /etc/nsswitch.conf | ${EGREPBINARY} "compat|nisplus")
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: NIS+ authentication not enabled"
|
|
Display --indent 2 --text "- NIS+ authentication support" --result "NOT ENABLED" --color WHITE
|
|
else
|
|
FIND2=$(${EGREPBINARY} "^passwd_compat" ${ROOTDIR}etc/nsswitch.conf | ${GREPBINARY} "nisplus")
|
|
FIND3=$(${EGREPBINARY} "^passwd" ${ROOTDIR}etc/nsswitch.conf | ${GREPBINARY} "nisplus")
|
|
if [ -n "${FIND2}" -o -n "${FIND3}" ]; then
|
|
LogText "Result: NIS+ authentication enabled"
|
|
Display --indent 2 --text "- NIS+ authentication support" --result "${STATUS_ENABLED}" --color GREEN
|
|
else
|
|
LogText "Result: NIS+ authentication not enabled"
|
|
Display --indent 2 --text "- NIS+ authentication support" --result "NOT ENABLED" --color WHITE
|
|
fi
|
|
fi
|
|
else
|
|
LogText "Result: /etc/nsswitch.conf not found"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9242
|
|
# Description : Query NIS authentication support
|
|
Register --test-no AUTH-9242 --weight L --network NO --category security --description "Query NIS authentication support"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if [ -f /etc/nsswitch.conf ]; then
|
|
FIND=$(${EGREPBINARY} "^passwd" /etc/nsswitch.conf | ${EGREPBINARY} "compat|nis" | ${GREPBINARY} -v "nisplus")
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: NIS authentication not enabled"
|
|
Display --indent 2 --text "- NIS authentication support" --result "NOT ENABLED" --color WHITE
|
|
else
|
|
FIND2=$(${EGREPBINARY} "^passwd_compat" /etc/nsswitch.conf | ${GREPBINARY} "nis" | ${GREPBINARY} -v "nisplus")
|
|
FIND3=$(${EGREPBINARY} "^passwd" /etc/nsswitch.conf | ${GREPBINARY} "nis" | ${GREPBINARY} -v "nisplus")
|
|
if [ -n "${FIND2}" -o -n "${FIND3}" ]; then
|
|
LogText "Result: NIS authentication enabled"
|
|
Display --indent 2 --text "- NIS authentication support" --result "${STATUS_ENABLED}" --color GREEN
|
|
else
|
|
LogText "Result: NIS authentication not enabled"
|
|
Display --indent 2 --text "- NIS authentication support" --result "NOT ENABLED" --color WHITE
|
|
fi
|
|
fi
|
|
else
|
|
LogText "Result: /etc/nsswitch.conf not found"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9250
|
|
# Description : Check for sudoers file
|
|
Register --test-no AUTH-9250 --weight L --network NO --category security --description "Checking sudoers file"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
for I in ${SUDOERS_LOCATIONS}; do
|
|
LogText "Test: checking presence ${I}"
|
|
if [ -f ${I} ]; then
|
|
FOUND=1
|
|
SUDOERS_FILE="${I}"
|
|
LogText "Result: found file (${SUDOERS_FILE})"
|
|
else
|
|
LogText "Result: file ${I} not found"
|
|
fi
|
|
done
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
LogText "Result: sudoers file found (${SUDOERS_FILE})"
|
|
Display --indent 2 --text "- Sudoers file(s)" --result "${STATUS_FOUND}" --color GREEN
|
|
else
|
|
LogText "Result: sudoers file NOT found"
|
|
Display --indent 2 --text "- Sudoers file" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9252
|
|
# Description : Check ownership and permissions for sudo configuration files
|
|
if [ -n "${SUDOERS_FILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9252 --preqs-met ${PREQS_MET} --weight L --network NO --root-only YES --category security --description "Check ownership and permissions for sudo configuration files"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
SUDO_CONFIG_FILES="${SUDOERS_FILE}"
|
|
SUDOERS_D="${SUDOERS_FILE}.d"
|
|
if [ -d "${SUDOERS_D}" ]; then
|
|
LogText "Test: checking drop-in directory (${SUDOERS_D})"
|
|
FIND=$(${LSBINARY} -ld ${SUDOERS_D} | ${CUTBINARY} -c 2-10)
|
|
FIND2=$(${LSBINARY} -lnd ${SUDOERS_D} | ${AWKBINARY} '{print $3$4}')
|
|
LogText "Result: Found directory permissions: ${FIND} and owner UID GID: ${FIND2}"
|
|
case "${FIND}" in
|
|
rwx[r-][w-][x-]--- )
|
|
LogText "Result: directory ${SUDOERS_D} permissions OK"
|
|
if [ "${FIND2}" = "00" ]; then
|
|
LogText "Result: directory ${SUDOERS_D} ownership OK"
|
|
Display --indent 4 --text "- Permissions for directory: ${SUDOERS_D}" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
LogText "Result: directory ${SUDOERS_D} has possibly unsafe ownership"
|
|
Display --indent 4 --text "- Permissions for directory: ${SUDOERS_D}" --result "${STATUS_WARNING}" --color RED
|
|
fi
|
|
;;
|
|
* )
|
|
LogText "Result: directory ${SUDOERS_D} has possibly unsafe permissions"
|
|
if [ "${FIND2}" = "00" ]; then
|
|
LogText "Result: directory ${SUDOERS_D} ownership OK"
|
|
else
|
|
LogText "Result: directory ${SUDOERS_D} has possibly unsafe ownership"
|
|
fi
|
|
Display --indent 4 --text "- Permissions for directory: ${SUDOERS_D}" --result "${STATUS_WARNING}" --color RED
|
|
;;
|
|
esac
|
|
SUDO_CONFIG_FILES="${SUDO_CONFIG_FILES} $(${FINDBINARY} ${SUDOERS_D} -type f -print)"
|
|
fi
|
|
for f in ${SUDO_CONFIG_FILES}; do
|
|
LogText "Test: checking file (${f})"
|
|
FIND=$(${LSBINARY} -l ${f} | ${CUTBINARY} -c 2-10)
|
|
FIND2=$(${LSBINARY} -ln ${f} | ${AWKBINARY} '{print $3$4}')
|
|
LogText "Result: Found file permissions: ${FIND} and owner UID GID: ${FIND2}"
|
|
case "${FIND}" in
|
|
r[w-]-[r-][w-]---- )
|
|
LogText "Result: file ${f} permissions OK"
|
|
if [ "${FIND2}" = "00" ]; then
|
|
LogText "Result: file ${f} ownership OK"
|
|
Display --indent 4 --text "- Permissions for: ${f}" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
LogText "Result: file ${f} has possibly unsafe ownership"
|
|
Display --indent 4 --text "- Permissions for: ${f}" --result "${STATUS_WARNING}" --color RED
|
|
fi
|
|
;;
|
|
* )
|
|
LogText "Result: file ${f} has possibly unsafe permissions"
|
|
if [ "${FIND2}" = "00" ]; then
|
|
LogText "Result: file ${f} ownership OK"
|
|
else
|
|
LogText "Result: file ${f} has possibly unsafe ownership"
|
|
fi
|
|
Display --indent 4 --text "- Permissions for: ${f}" --result "${STATUS_WARNING}" --color RED
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9254
|
|
# Description : Solaris test to check passwordless accounts
|
|
Register --test-no AUTH-9254 --os Solaris --weight L --network NO --root-only YES --category security --description "Solaris passwordless accounts"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FIND=$(logins -p | ${AWKBINARY} '{ print $1 }')
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: no passwordless accounts found"
|
|
Display --indent 2 --text "- Passwordless accounts on Solaris" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
for I in ${FIND}; do
|
|
ReportWarning "${TEST_NO}" "Found passwordless account (${I})"
|
|
done
|
|
Display --indent 2 --text "- Passwordless accounts on Solaris" --result "${STATUS_WARNING}" --color RED
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9262
|
|
# Description : Search for PAM password strength testing libraries
|
|
Register --test-no AUTH-9262 --weight L --network NO --category security --description "Checking presence password strength testing tools (PAM)"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
FOUND_CRACKLIB=0
|
|
FOUND_PASSWDQC=0
|
|
FOUND_PWQUALITY=0
|
|
|
|
# Cracklib
|
|
LogText "Searching PAM password testing modules (cracklib, passwdqc, pwquality)"
|
|
for I in ${PAM_FILE_LOCATIONS}; do
|
|
|
|
if [ -f ${I}/pam_cracklib.so ]; then
|
|
FOUND_CRACKLIB=1
|
|
FOUND=1
|
|
LogText "Result: found pam_cracklib.so (crack library PAM) in ${I}"
|
|
fi
|
|
|
|
if [ -f ${I}/pam_passwdqc.so ]; then
|
|
FOUND_PASSWDQC=1
|
|
FOUND=1
|
|
LogText "Result: found pam_passwdqc.so (passwd quality control PAM) in ${I}"
|
|
fi
|
|
|
|
if [ -f ${I}/pam_pwquality.so ]; then
|
|
FOUND_PWQUALITY=1
|
|
FOUND=1
|
|
LogText "Result: found pam_pwquality.so (password quality control PAM) in ${I}"
|
|
fi
|
|
done
|
|
|
|
# Cracklib
|
|
if [ ${FOUND_CRACKLIB} -eq 1 ]; then
|
|
LogText "Result: pam_cracklib.so found"
|
|
Report "pam_cracklib=1"
|
|
else
|
|
LogText "Result: pam_cracklib.so NOT found (crack library PAM)"
|
|
fi
|
|
|
|
# Password quality control
|
|
if [ ${FOUND_PASSWDQC} -eq 1 ]; then
|
|
LogText "Result: pam_passwdqc.so found"
|
|
Report "pam_passwdqc=1"
|
|
else
|
|
LogText "Result: pam_passwdqc.so NOT found (passwd quality control PAM)"
|
|
fi
|
|
|
|
# pwquality module
|
|
if [ ${FOUND_PWQUALITY} -eq 1 ]; then
|
|
LogText "Result: pam_pwquality.so found"
|
|
Report "pam_pwquality=1"
|
|
else
|
|
LogText "Result: pam_pwquality.so NOT found (pwquality control PAM)"
|
|
fi
|
|
|
|
if [ ${FOUND} -eq 0 ]; then
|
|
Display --indent 2 --text "- PAM password strength tools" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
LogText "Result: no PAM modules for password strength testing found"
|
|
ReportSuggestion "${TEST_NO}" "Install a PAM module for password strength testing like pam_cracklib or pam_passwdqc"
|
|
AddHP 0 3
|
|
else
|
|
Display --indent 2 --text "- PAM password strength tools" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: found at least one PAM module for password strength testing"
|
|
AddHP 3 3
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9264
|
|
# Description : Scan /etc/pam.conf file
|
|
Register --test-no AUTH-9264 --weight L --network NO --category security --description "Checking presence pam.conf"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking file /etc/pam.conf"
|
|
if [ -f ${ROOTDIR}etc/pam.conf ]; then
|
|
LogText "Result: file ${ROOTDIR}etc/pam.conf exists"
|
|
Display --indent 2 --text "- PAM configuration files (pam.conf)" --result "${STATUS_FOUND}" --color GREEN
|
|
LogText "Test: searching PAM configuration files"
|
|
FIND=$(${EGREPBINARY} -v "^#" ${ROOTDIR}etc/pam.conf | ${EGREPBINARY} -v "^$" | ${SEDBINARY} 's/[[:space:]]/ /g' | ${SEDBINARY} 's/ / /g' | ${SEDBINARY} 's/ /:space:/g')
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: File has no configuration options defined (empty, or only filled with comments and empty lines)"
|
|
else
|
|
LogText "Result: found one or more configuration lines"
|
|
for LINE in ${FIND}; do
|
|
LINE=$(echo ${LINE} | ${SEDBINARY} 's/:space:/ /g')
|
|
LogText "Found line: ${LINE}"
|
|
done
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/pam.conf could not be found"
|
|
Display --indent 2 --text "- PAM configuration file (pam.conf)" --result "${STATUS_NOT_FOUND}" --color WHITE
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9266
|
|
# Description : Searching available PAM configurations (/etc/pam.d)
|
|
Register --test-no AUTH-9266 --weight L --network NO --category security --description "Checking presence pam.d files"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking directory ${ROOTDIR}etc/pam.d"
|
|
if [ -d ${ROOTDIR}etc/pam.d ]; then
|
|
LogText "Result: directory /etc/pam.d exists"
|
|
Display --indent 2 --text "- PAM configuration files (pam.d)" --result "${STATUS_FOUND}" --color GREEN
|
|
LogText "Test: searching PAM configuration files"
|
|
FIND=$(${FINDBINARY} ${ROOTDIR}etc/pam.d \! -name "*.pam-old" -type f -print | sort)
|
|
for FILE in ${FIND}; do
|
|
LogText "Found file: ${FILE}"
|
|
done
|
|
else
|
|
LogText "Result: directory /etc/pam.d could not be found"
|
|
Display --indent 2 --text "- PAM configuration files (pam.d)" --result "${STATUS_NOT_FOUND}" --color WHITE
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9268
|
|
# Description : Searching available PAM files
|
|
# Notes : PAM is used on AIX, FreeBSD, Linux, HPUX, NetBSD, Solaris
|
|
case "${OS}" in
|
|
"AIX"|"FreeBSD"|"Linux"|"HPUX"|"NetBSD"|"Solaris")
|
|
PREQS_MET="YES" ;;
|
|
*)
|
|
PREQS_MET="NO" ;;
|
|
esac
|
|
Register --test-no AUTH-9268 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Checking presence pam.d files"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
LogText "Test: Searching pam modules"
|
|
for DIR in ${PAM_FILE_LOCATIONS}; do
|
|
LogText "Test: Checking ${DIR}"
|
|
if [ -d ${DIR} -a ! -L ${DIR} ]; then
|
|
LogText "Result: directory ${DIR} exists"
|
|
# Search in the specified directory
|
|
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)
|
|
fi
|
|
if [ -n "${FIND}" ]; then FOUND=1; fi
|
|
for FILE in ${FIND}; do
|
|
LogText "Found file: ${FILE}"
|
|
Report "pam_module[]=${FILE}"
|
|
done
|
|
else
|
|
LogText "Result: directory ${DIR} could not be found or is a symlink to another directory"
|
|
fi
|
|
done
|
|
# Check if we found at least one module
|
|
if [ ${FOUND} -eq 0 ]; then
|
|
Display --indent 2 --text "- PAM modules" --result "${STATUS_NOT_FOUND}" --color WHITE
|
|
LogText "Result: no PAM modules found"
|
|
else
|
|
Display --indent 2 --text "- PAM modules" --result "${STATUS_FOUND}" --color GREEN
|
|
fi
|
|
unset DIR FILE FIND
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9278
|
|
# Description : Search LDAP support in PAM files
|
|
Register --test-no AUTH-9278 --weight L --network NO --category security --description "Determine LDAP support in PAM files"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
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 [ -n "${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: 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
|
|
Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_NOT_FOUND}" --color WHITE
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9282 and AUTH-9283
|
|
# Note : Every Linux based operating system seem to have different passwd
|
|
# options, so we have to check the version first.
|
|
if [ "${OS}" = "Linux" ]; then
|
|
if [ "${OS_REDHAT_OR_CLONE}" -eq 0 ]; then
|
|
case ${LINUX_VERSION} in
|
|
"SuSE")
|
|
PREQS_MET="YES"
|
|
FIND_P=$(passwd -a -S 2> /dev/null | ${AWKBINARY} '{ if ($2=="P" && $5=="99999") print $1 }')
|
|
FIND2=$(passwd -a -S 2> /dev/null | ${AWKBINARY} '{ if ($2=="NP") print $1 }')
|
|
;;
|
|
*)
|
|
PREQS_MET="YES"
|
|
FIND_P=$(passwd --all --status 2> /dev/null | ${AWKBINARY} '{ if ($2=="P" && $5=="99999") print $1 }')
|
|
FIND2=$(passwd --all --status 2> /dev/null | ${AWKBINARY} '{ if ($2=="NP") print $1 }')
|
|
;;
|
|
esac
|
|
elif [ "${OS_REDHAT_OR_CLONE}" -eq 1 ]; then
|
|
PREQS_MET="YES"
|
|
FIND_P=$(for I in $(${AWKBINARY} -F: '{print $1}' "${ROOTDIR}etc/passwd") ; do passwd -S "$I" | ${AWKBINARY} '{ if ($2=="PS" && $5=="99999") print $1 }' ; done)
|
|
FIND2=$(for I in $(${AWKBINARY} -F: '{print $1}' "${ROOTDIR}etc/passwd") ; do passwd -S "$I" | ${AWKBINARY} '{ if ($2=="NP") print $1 }' ; done)
|
|
else
|
|
LogText "Result: skipping test for this Linux version"
|
|
ReportManual "AUTH-9282:01"
|
|
PREQS_MET="NO"
|
|
FIND_P=""
|
|
FIND2=""
|
|
fi
|
|
else
|
|
PREQS_MET="NO"
|
|
fi
|
|
|
|
# Test : AUTH-9282
|
|
# Description : Search password protected accounts without expire (Linux)
|
|
Register --test-no AUTH-9282 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Checking password protected account without expire date"
|
|
if [ "${SKIPTEST}" -eq 0 ]; then
|
|
LogText "Test: Checking Linux version and password expire date status"
|
|
if [ -z "${FIND_P}" ]; then
|
|
LogText "Result: all accounts seem to have an expire date"
|
|
Display --indent 2 --text "- Accounts without expire date" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
LogText "Result: found one or more accounts without expire date set"
|
|
for I in ${FIND_P}; do
|
|
LogText "Account without expire date: ${I}"
|
|
done
|
|
Display --indent 2 --text "- Accounts without expire date" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "When possible set expire dates for all password protected accounts"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9283
|
|
# Description : Search passwordless accounts
|
|
Register --test-no AUTH-9283 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Checking accounts without password"
|
|
if [ "${SKIPTEST}" -eq 0 ]; then
|
|
LogText "Test: Checking passwordless accounts"
|
|
if [ -z "${FIND2}" ]; then
|
|
LogText "Result: all accounts seem to have a password"
|
|
Display --indent 2 --text "- Accounts without password" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
LogText "Result: found one or more accounts without password"
|
|
for I in ${FIND2}; do
|
|
LogText "Account without password: ${I}"
|
|
Report "account_without_password=${I}"
|
|
done
|
|
Display --indent 2 --text "- Accounts without password" --result "${STATUS_WARNING}" --color RED
|
|
ReportWarning "${TEST_NO}" "Found accounts without password"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9286
|
|
# Description : Check user password aging
|
|
# Notes : MIN = minimum age, avoid rotation of passwords too quickly
|
|
# : MAX = maximum age, ensure regular change of passwords
|
|
PREQS_MET="NO"
|
|
if [ -f ${ROOTDIR}etc/login.defs ]; then
|
|
PREQS_MET="YES"
|
|
# Future TODO: check if PAM overrule these settings
|
|
fi
|
|
Register --test-no AUTH-9286 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Checking user password aging"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Checking PASS_MIN_DAYS option in ${ROOTDIR}etc/login.defs"
|
|
FIND=$(${GREPBINARY} "^PASS_MIN_DAYS" ${ROOTDIR}etc/login.defs | ${AWKBINARY} '{ if ($1=="PASS_MIN_DAYS") { print $2 } }')
|
|
if [ -z "${FIND}" -o "${FIND}" = "0" ]; then
|
|
LogText "Result: password minimum age is not configured"
|
|
Display --indent 2 --text "- Checking user password aging (minimum)" --result "${STATUS_DISABLED}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Configure minimum password age in /etc/login.defs"
|
|
AddHP 0 1
|
|
else
|
|
LogText "Result: password needs to be at least ${FIND} days old"
|
|
PASSWORD_MINIMUM_DAYS=${FIND}
|
|
Display --indent 2 --text "- User password aging (minimum)" --result CONFIGURED --color GREEN
|
|
AddHP 3 3
|
|
fi
|
|
|
|
LogText "Test: Checking PASS_MAX_DAYS option in ${ROOTDIR}etc/login.defs "
|
|
FIND=$(${GREPBINARY} "^PASS_MAX_DAYS" ${ROOTDIR}etc/login.defs | ${AWKBINARY} '{ if ($1=="PASS_MAX_DAYS") { print $2 } }')
|
|
if [ -z "${FIND}" -o "${FIND}" = "99999" ]; then
|
|
LogText "Result: password aging limits are not configured"
|
|
Display --indent 2 --text "- User password aging (maximum)" --result "${STATUS_DISABLED}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Configure maximum password age in /etc/login.defs"
|
|
AddHP 0 1
|
|
else
|
|
LogText "Result: max password age is ${FIND} days"
|
|
PASSWORD_MAXIMUM_DAYS=${FIND}
|
|
Display --indent 2 --text "- User password aging (maximum)" --result CONFIGURED --color GREEN
|
|
AddHP 3 3
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9288
|
|
# Description : Determine which accounts have an expired password
|
|
# Notes : This test might not work (yet) on all platforms
|
|
if [ -f ${ROOTDIR}etc/shadow ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9288 --preqs-met ${PREQS_MET} --weight L --network NO --root-only YES --category security --description "Checking for expired passwords"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if FileIsReadable ${ROOTDIR}etc/shadow; then
|
|
|
|
if [ "${OS}" = "Solaris" ]; then
|
|
NOW=$(nawk 'BEGIN{print srand()}')
|
|
else
|
|
NOW=$(date "+%s")
|
|
fi
|
|
|
|
DAYS_SINCE_EPOCH=$((NOW / 86400))
|
|
LogText "Data: Days since epoch is ${DAYS_SINCE_EPOCH}"
|
|
LogText "Test: collecting accounts which have an expired password (last day changed + maximum change time)"
|
|
# Skip fields with a !, *, or x, or !* (field $3 is last changed, $5 is maximum changed)
|
|
FIND=$(${EGREPBINARY} -v ":[\!\*x]([\*\!])?:" /etc/shadow | ${AWKBINARY} -v today=${DAYS_SINCE_EPOCH} -F: '{ if (($5!="") && (today>$3+$5)) { print $1 }}')
|
|
if [ -n "${FIND}" ]; then
|
|
for ACCOUNT in ${FIND}; do
|
|
LogText "Result: password of user ${ACCOUNT} has been expired"
|
|
Report "account_password_expired[]=${ACCOUNT}"
|
|
done
|
|
AddHP 0 10
|
|
Display --indent 2 --text "- Checking expired passwords" --result "${STATUS_FOUND}" --color RED
|
|
ReportSuggestion "${TEST_NO}" "Delete accounts which are no longer used"
|
|
else
|
|
LogText "Result: good, no passwords have been expired"
|
|
Display --indent 2 --text "- Checking expired passwords" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 10 10
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Checking expired passwords" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9304
|
|
# Description : Check if single user mode login is properly configured in Solaris
|
|
# Notes : sulogin should be called from svm script (Solaris <10) in /etc/rcS.d
|
|
Register --test-no AUTH-9304 --os Solaris --weight L --network NO --category security --description "Check single user login configuration"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
# Check if file exists (Solaris 10 does not have this file by default)
|
|
if [ -f ${ROOTDIR}etc/default/sulogin ]; then
|
|
LogText "Result: file ${ROOTDIR}etc/default/sulogin exists"
|
|
LogText "Test: checking presence PASSREQ=NO"
|
|
FIND=$(${GREPBINARY} "^PASSREQ=NO" ${ROOTDIR}etc/default/sulogin)
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: option not present or configured to request a password at single user mode login"
|
|
Display --indent 2 --text "- Checking Solaris /etc/default/sulogin file" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 1 1
|
|
else
|
|
LogText "Result: option present, no password needed at single user mode login"
|
|
Display --indent 2 --text "- Checking Solaris /etc/default/sulogin file" --result "${STATUS_WARNING}" --color RED
|
|
ReportWarning "${TEST_NO}" "No password needed for single user mode login"
|
|
AddHP 0 1
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/default/sulogin does not exist"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9306
|
|
# Description : Check if authentication is needed to boot the system
|
|
# Notes : :d_boot_authenticate: is a good option for production machines to
|
|
# avoid unauthorized booting of systems. Option :d_boot_autentication@:
|
|
# disabled a required login.
|
|
Register --test-no AUTH-9306 --os HP-UX --weight L --network NO --category security --description "Check single boot authentication"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
# Check if file exists
|
|
LogText "Test: Searching /tcb/files/auth/system/default"
|
|
if [ -f ${ROOTDIR}tcb/files/auth/system/default ]; then
|
|
LogText "Result: file ${ROOTDIR}tcb/files/auth/system/default exists"
|
|
LogText "Test: checking presence :d_boot_authenticate@:"
|
|
FIND=$(${GREPBINARY} "^:d_boot_authenticate@" /tcb/files/auth/system/default)
|
|
if [ -z "${FIND}" ]; then
|
|
LogText "Result: option not set, password is needed at boot"
|
|
Display --indent 2 --text "- Checking HP-UX boot authentication" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 1 1
|
|
else
|
|
LogText "Result: option present, no password needed at single user mode login"
|
|
Display --indent 2 --text "- Checking HP-UX boot authentication" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Set password for system boot"
|
|
AddHP 0 1
|
|
fi
|
|
else
|
|
LogText "Result: file ${ROOTDIR}tcb/files/auth/system/default does not exist"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9308
|
|
# Description : Check single user mode login for Linux
|
|
Register --test-no AUTH-9308 --os Linux --weight L --network NO --category security --description "Check single user login configuration"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
TEST_PERFORMED=0
|
|
|
|
if [ ${HAS_SYSTEMD} -eq 0 ]; then
|
|
# Check inittab
|
|
LogText "Test: Searching ${ROOTDIR}etc/inittab"
|
|
if [ -f ${ROOTDIR}etc/inittab ]; then
|
|
TEST_PERFORMED=1
|
|
LogText "Result: file ${ROOTDIR}etc/inittab exists"
|
|
LogText "Test: checking presence sulogin for single user mode"
|
|
FIND=$(${EGREPBINARY} "^[a-zA-Z0-9~]+:S:(respawn|wait):/sbin/sulogin" /etc/inittab)
|
|
FIND2=$(${EGREPBINARY} "^su:S:(respawn|wait):/sbin/sulogin" /etc/inittab)
|
|
if [ -n "${FIND}" -o -n "${FIND2}" ]; then
|
|
FOUND=1
|
|
LogText "Result: found sulogin, so single user is protected"
|
|
fi
|
|
else
|
|
LogText "Result: file ${ROOTDIR}etc/inittab does not exist"
|
|
fi
|
|
|
|
# Check init
|
|
LogText "Test: Searching ${ROOTDIR}etc/sysconfig/init"
|
|
if [ -f ${ROOTDIR}etc/sysconfig/init ]; then
|
|
TEST_PERFORMED=1
|
|
LogText "Result: file ${ROOTDIR}etc/sysconfig/init exists"
|
|
LogText "Test: checking presence sulogin for single user mode"
|
|
FIND=$(${GREPBINARY} "^SINGLE=/sbin/sulogin" ${ROOTDIR}etc/sysconfig/init)
|
|
if [ -n "${FIND}" ]; then
|
|
FOUND=1
|
|
LogText "Result: found sulogin, so single user is protected"
|
|
fi
|
|
else
|
|
LogText "Result: file ${ROOTDIR}etc/sysconfig/init does not exist"
|
|
fi
|
|
fi
|
|
|
|
# Systemd support
|
|
SYSTEMD_DIRECTORY="/lib/systemd/system"
|
|
if [ -d ${SYSTEMD_DIRECTORY} ]; then
|
|
FILES="console-shell.service emergency.service rescue.service"
|
|
LogText "Test: going to check several systemd targets now"
|
|
for I in ${FILES}; do
|
|
FILE="${SYSTEMD_DIRECTORY}/${I}"
|
|
LogText "Test: checking if target ${I} is available (${FILE})"
|
|
if [ -f ${FILE} ]; then
|
|
# Mark test as performed only when at least 1 target exists (e.g. Ubuntu 14.04 has limited systemd support)
|
|
TEST_PERFORMED=1
|
|
LogText "Result: found target ${I}"
|
|
FIND=$(${EGREPBINARY} "^ExecStart=" ${FILE} | ${GREPBINARY} "sulogin")
|
|
if [ "${FIND}" = "" ]; then
|
|
LogText "Result: did not find sulogin specified, possible risk of getting into single user mode without authentication"
|
|
else
|
|
LogText "Result: sulogin was found, which is a good measure to protect single user mode"
|
|
FOUND=1
|
|
fi
|
|
else
|
|
LogText "Result: target ${I} not found"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ ${TEST_PERFORMED} -eq 1 ]; then
|
|
if [ ${FOUND} -eq 0 ]; then
|
|
LogText "Result: option not set, no password needed at single user mode boot"
|
|
Display --indent 2 --text "- Checking Linux single user mode authentication" --result "${STATUS_WARNING}" --color RED
|
|
ReportWarning "${TEST_NO}" "No password set for single mode"
|
|
ReportSuggestion "${TEST_NO}" "Set password for single user mode to minimize physical access attack surface"
|
|
AddHP 0 2
|
|
else
|
|
LogText "Result: option set, password is needed at single user mode boot"
|
|
Display --indent 2 --text "- Checking Linux single user mode authentication" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
fi
|
|
else
|
|
LogText "Result: no tests performed"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9328
|
|
# Description : Check default umask in common files
|
|
# Notes: This test should be moved later to shells section
|
|
# /etc/login.defs
|
|
# pam_umask
|
|
Register --test-no AUTH-9328 --weight L --network NO --category security --description "Default umask values"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
Display --indent 2 --text "- Determining default umask"
|
|
GOOD_UMASK=0
|
|
WEAK_UMASK=0
|
|
|
|
# /etc/profile.d
|
|
LogText "Test: Checking ${ROOTDIR}etc/profile.d directory"
|
|
if [ -d ${ROOTDIR}etc/profile.d ]; then
|
|
FOUND=0
|
|
FIND=$(ls ${ROOTDIR}etc/profile.d/* 2> /dev/null)
|
|
if [ -n "${FIND}" ]; then
|
|
LogText "Result: found /etc/profile.d, with one or more files in it"
|
|
for FILE in ${FIND}; do
|
|
HAS_MASK=$(${GREPBINARY} umask ${FILE} 2> /dev/null | ${SEDBINARY} 's/^[ \t]*//' | ${GREPBINARY} -v "^#" | ${AWKBINARY} '{ print $2 }')
|
|
for MASK in ${HAS_MASK}; do
|
|
if [ "${MASK}" = "077" -o "${MASK}" = "027" -o "${MASK}" = "0077" -o "${MASK}" = "0027" ]; then
|
|
LogText "Result: found a strong umask '${MASK}' set in ${FILE}"
|
|
GOOD_UMASK=1
|
|
else
|
|
LogText "Result: found a weak umask '${MASK}' set in ${FILE}"
|
|
WEAK_UMASK=1
|
|
fi
|
|
done
|
|
done
|
|
else
|
|
LogText "Result: found /etc/profile.d, but it does not contain any files"
|
|
fi
|
|
else
|
|
LogText "Result: /etc/profile.d not found"
|
|
fi
|
|
|
|
# Test /etc/profile (only if we didn't find a good umask in profile.d)
|
|
LogText "Test: Checking /etc/profile"
|
|
if [ -f /etc/profile -a ${GOOD_UMASK} -eq 0 ]; then
|
|
LogText "Result: file /etc/profile exists"
|
|
LogText "Test: Checking umask value in /etc/profile"
|
|
FIND=$(${GREPBINARY} "umask" /etc/profile | ${SEDBINARY} 's/^[ \t]*//' | ${GREPBINARY} -v "^#" | ${AWKBINARY} '{ print $2 }')
|
|
FIND2=$(${GREPBINARY} "umask" /etc/profile | ${SEDBINARY} 's/^[ \t]*//' | ${GREPBINARY} -v "^#" | ${AWKBINARY} '{ print $2 }' | wc -l)
|
|
FOUND_UMASK=0
|
|
if [ "${FIND2}" = "0" ]; then
|
|
LogText "Result: did not find umask in /etc/profile"
|
|
elif [ "${FIND2}" = "1" ]; then
|
|
LogText "Result: found umask (prefixed with spaces)"
|
|
FOUND_UMASK=1
|
|
if [ ! "${FIND}" = "077" -a ! "${FIND}" = "027" -a ! "${FIND}" = "0077" -a ! "${FIND}" = "0027" ]; then
|
|
LogText "Result: found umask ${FIND}, which could be more strict"
|
|
WEAK_UMASK=1
|
|
else
|
|
LogText "Result: found umask ${FIND}, which is fine"
|
|
GOOD_UMASK=1
|
|
fi
|
|
# Found more than 1 umask value in profile
|
|
else
|
|
LogText "Result: found multiple umask values configured in /etc/profile"
|
|
FOUND_UMASK=1
|
|
for I in ${FIND}; do
|
|
if [ ! "${I}" = "077" -a ! "${I}" = "027" -a ! "${I}" = "0077" -a ! "${I}" = "0027" ]; then
|
|
LogText "Result: umask ${I} could be more strict"
|
|
WEAK_UMASK=1
|
|
AddHP 1 2
|
|
else
|
|
LogText "Result: Found umask ${I}, which is fine"
|
|
AddHP 2 2
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ ${FOUND_UMASK} -eq 1 ]; then
|
|
if [ ${WEAK_UMASK} -eq 0 ]; then
|
|
Display --indent 4 --text "- umask (/etc/profile and /etc/profile.d)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
elif [ ${GOOD_UMASK} -eq 1 -a ${WEAK_UMASK} -eq 1 ]; then
|
|
Display --indent 4 --text "- umask (/etc/profile and /etc/profile.d)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Some umasks found could be more strict (e.g. 027)"
|
|
AddHP 1 2
|
|
else
|
|
Display --indent 4 --text "- umask (/etc/profile and /etc/profile.d)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/profile or /etc/profile.d/custom.sh could be more strict (e.g. 027)"
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
# Some operating systems don't have a default umask defined in /etc/profile (Debian)
|
|
LogText "Result: found no umask. Please check if this is correct"
|
|
Display --indent 4 --text "- umask (/etc/profile)" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/profile does not exist"
|
|
fi
|
|
|
|
# /etc/passwd
|
|
LogText "Test: Checking umask entries in /etc/passwd (pam_umask)"
|
|
if [ -f /etc/passwd ]; then
|
|
LogText "Result: file /etc/passwd exists"
|
|
LogText "Test: Checking umask value in /etc/passwd"
|
|
FIND=$(${GREPBINARY} "umask=" /etc/passwd)
|
|
if [ "${FIND}" = "" ]; then
|
|
ReportManual "AUTH-9328:03"
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/passwd does not exist"
|
|
fi
|
|
|
|
# /etc/login.defs
|
|
LogText "Test: Checking /etc/login.defs"
|
|
if [ -f /etc/login.defs ]; then
|
|
LogText "Result: file /etc/login.defs exists"
|
|
LogText "Test: Checking umask value in /etc/login.defs"
|
|
FIND=$(${GREPBINARY} "^UMASK" /etc/login.defs | ${AWKBINARY} '{ print $2 }')
|
|
if [ "${FIND}" = "" ]; then
|
|
LogText "Result: umask value is not configured (most likely it will have the default 022 value)"
|
|
Display --indent 4 --text "- umask (/etc/login.defs)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/login.defs could not be found and defaults usually to 022, which could be more strict like 027"
|
|
AddHP 1 2
|
|
elif [ "${FIND}" = "077" -o "${FIND}" = "027" -o "${FIND}" = "0077" -o "${FIND}" = "0027" ]; then
|
|
LogText "Result: umask is ${FIND}, which is fine"
|
|
Display --indent 4 --text "- umask (/etc/login.defs)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: found umask ${FIND}, which could be improved"
|
|
Display --indent 4 --text "- umask (/etc/login.defs)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/login.defs could be more strict like 027"
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/login.defs does not exist"
|
|
fi
|
|
|
|
# Red Hat /etc/init.d/functions
|
|
LogText "Test: Checking /etc/init.d/functions"
|
|
if [ -f /etc/init.d/functions ]; then
|
|
LogText "Result: file /etc/init.d/functions exists"
|
|
LogText "Test: Checking umask value in /etc/init.d/functions"
|
|
FIND=$(${GREPBINARY} "^umask" /etc/init.d/functions | ${AWKBINARY} '{ print $2 }')
|
|
if [ "${FIND}" = "" ]; then
|
|
LogText "Result: umask is not configured"
|
|
Display --indent 4 --text "- umask (/etc/init.d/functions)" --result "${STATUS_NONE}" --color WHITE
|
|
elif [ "${FIND}" = "077" -o "${FIND}" = "027" -o "${FIND}" = "0077" -o "${FIND}" = "0027" ]; then
|
|
LogText "Result: umask is ${FIND}, which is fine"
|
|
Display --indent 4 --text "- umask (/etc/init.d/functions)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: found umask ${FIND}, which could be improved"
|
|
Display --indent 4 --text "- umask (/etc/init.d/functions)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/init.d/functions does not exist"
|
|
fi
|
|
|
|
# /etc/init.d/rc
|
|
LogText "Test: Checking /etc/init.d/rc"
|
|
if [ -f /etc/init.d/rc ]; then
|
|
LogText "Result: file /etc/init.d/rc exists"
|
|
LogText "Test: Checking UMASK value in /etc/init.d/rc"
|
|
FIND=$(${GREPBINARY} -i "^UMASK" /etc/init.d/rc | ${AWKBINARY} '{ print $2 }')
|
|
if [ "${FIND}" = "" ]; then
|
|
LogText "Result: UMASK value is not configured (most likely it will have the default 022 value)"
|
|
Display --indent 4 --text "- Checking umask (/etc/init.d/rc)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/init.d/rc could not be found and defaults usually to 022, which could be more strict like 027"
|
|
AddHP 1 2
|
|
elif [ "${FIND}" = "077" -o "${FIND}" = "027" -o "${FIND}" = "0077" -o "${FIND}" = "0027" ]; then
|
|
LogText "Result: umask is ${FIND}, which is fine"
|
|
Display --indent 4 --text "- umask (/etc/init.d/rc)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: found umask ${FIND}, which could be improved"
|
|
Display --indent 4 --text "- umask (/etc/init.d/rc)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/init.d/rc could be more strict like 027"
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/init.d/rc does not exist"
|
|
fi
|
|
|
|
# FreeBSD
|
|
if [ -f /etc/login.conf ]; then
|
|
FOUND=0
|
|
WEAK_UMASK=0
|
|
LogText "Result: file /etc/login.conf exists"
|
|
FIND=$(${GREPBINARY} "umask" /etc/login.conf | ${SEDBINARY} 's/#.*//' | ${SEDBINARY} -E 's/^[[:cntrl:]]//' | ${GREPBINARY} -v '^$' | ${AWKBINARY} -F: '{ print $2}' | ${AWKBINARY} -F= '{ if ($1=="umask") { print $2 }}')
|
|
if [ ! "${FIND}" = "" ]; then
|
|
for UMASK_VALUE in ${FIND}; do
|
|
case ${UMASK_VALUE} in
|
|
027|0027|077|0077)
|
|
LogText "Result: found umask value ${UMASK_VALUE}, which is fine"
|
|
AddHP 2 2
|
|
FOUND=1
|
|
;;
|
|
*)
|
|
AddHP 0 2
|
|
FOUND=1
|
|
WEAK_UMASK=1
|
|
LogText "Result: found umask value ${UMASK_VALUE}, which can be more strict"
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
if [ ${WEAK_UMASK} -eq 0 ]; then
|
|
Display --indent 4 --text "- umask (/etc/login.conf)" --result "${STATUS_OK}" --color GREEN
|
|
else
|
|
Display --indent 4 --text "- umask (/etc/login.conf)" --result "${STATUS_WEAK}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Umask in /etc/login.conf could be more strict like 027"
|
|
fi
|
|
else
|
|
LogText "Result: no umask setting found in /etc/login.conf, which is unexpected"
|
|
Display --indent 4 --text "- umask (/etc/login.conf)" --result "${STATUS_NONE}" --color YELLOW
|
|
fi
|
|
fi
|
|
|
|
# /etc/init.d/rcS
|
|
LogText "Test: Checking /etc/init.d/rcS"
|
|
if [ -f /etc/init.d/rcS ]; then
|
|
LogText "Result: file /etc/init.d/rcS exists"
|
|
LogText "Test: Checking if script runs another script."
|
|
FIND=$(${GREPBINARY} -i "^exec " /etc/init.d/rcS | ${AWKBINARY} '{ print $2 }')
|
|
if [ "${FIND}" = "" ]; then
|
|
FIND2=$(${GREPBINARY} -i "^UMASK" /etc/init.d/rcS | ${AWKBINARY} '{ print $2 }')
|
|
if [ "${FIND2}" = "" ]; then
|
|
LogText "Result: UMASK value is not configured (most likely it will have the default 022 value)"
|
|
Display --indent 4 --text "- Checking umask (/etc/init.d/rcS)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/init.d/rcS could not be found and defaults usually to 022, which could be more strict like 027"
|
|
AddHP 1 2
|
|
elif [ "${FIND2}" = "077" -o "${FIND2}" = "027" ]; then
|
|
LogText "Result: umask is ${FIND2}, which is fine"
|
|
Display --indent 4 --text "- umask (/etc/init.d/rcS)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: found umask ${FIND2}, which could be improved"
|
|
Display --indent 4 --text "- umask (/etc/init.d/rcS)" --result "${STATUS_SUGGESTION}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Default umask in /etc/init.d/rcS could be more strict like 027"
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
# Improve check
|
|
LogText "Result: exec line present in file, setting of umask not needed in this script"
|
|
LogText "Output: ${FIND}"
|
|
fi
|
|
else
|
|
LogText "Result: file /etc/init.d/rcS does not exist"
|
|
fi
|
|
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9340
|
|
# Description : Solaris account locking
|
|
Register --test-no AUTH-9340 --os Solaris --weight L --network NO --category security --description "Solaris account locking"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
if [ -f ${ROOTDIR}etc/security/policy.conf ]; then
|
|
LogText "Result: found ${ROOTDIR}etc/security/policy.conf"
|
|
FIND=$(${GREPBINARY} "^LOCK_AFTER_RETRIES" /etc/security/policy.conf)
|
|
if [ ! "${FIND}" = "" ]; then
|
|
FOUND=1
|
|
LogText "Result: account locking option set"
|
|
LogText "Output: ${FIND}"
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: option LOCK_AFTER_RETRIES not set"
|
|
AddHP 1 2
|
|
fi
|
|
else
|
|
LogText "Result: ${ROOTDIR}etc/security/policy.conf does not exist"
|
|
fi
|
|
# If policy.conf does not exist, we most likely deal with a Solaris version below 10
|
|
# and we proceed with checking the softer option RETRIES in /etc/default/login
|
|
# which does not lock account, but discourages brute force password attacks.
|
|
if [ ${FOUND} -eq 0 ]; then
|
|
LogText "Test: checking ${ROOTDIR}etc/default/login"
|
|
if [ -f ${ROOTDIR}etc/default/login ]; then
|
|
LogText "Result: file ${ROOTDIR}etc/default/login exists"
|
|
FIND=$(${GREPBINARY} "^RETRIES" ${ROOTDIR}etc/default/login)
|
|
if [ -n "${FIND}" ]; then
|
|
FOUND=1
|
|
LogText "Result: retries option configured"
|
|
LogText "Output: ${FIND}"
|
|
AddHP 2 2
|
|
else
|
|
LogText "Result: retries option not configured"
|
|
AddHP 1 2
|
|
fi
|
|
else
|
|
LogText "Result: file ${ROOTDIR}etc/default/login does not exist"
|
|
fi
|
|
fi
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
Display --indent 2 --text "- Checking account locking" --result "${STATUS_ENABLED}" --color GREEN
|
|
else
|
|
Display --indent 2 --text "- Checking account locking" --result "NOT ENABLED" --color YELLOW
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9402
|
|
# Description : Query LDAP authentication support
|
|
Register --test-no AUTH-9402 --weight L --network NO --category security --description "Query LDAP authentication support"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if [ -f ${ROOTDIR}etc/nsswitch.conf ]; then
|
|
FIND=$(${EGREPBINARY} "^passwd" ${ROOTDIR}etc/nsswitch.conf | ${GREPBINARY} "ldap")
|
|
if [ "${FIND}" = "" ]; then
|
|
LogText "Result: LDAP authentication not enabled"
|
|
Display --indent 2 --text "- LDAP authentication support" --result "NOT ENABLED" --color WHITE
|
|
else
|
|
LogText "Result: LDAP authentication enabled"
|
|
Display --indent 2 --text "- LDAP authentication support" --result "${STATUS_ENABLED}" --color GREEN
|
|
LDAP_AUTH_ENABLED=1
|
|
fi
|
|
else
|
|
LogText "Result: /etc/nsswitch.conf not found"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9406
|
|
# Description : Check LDAP servers in client configuration
|
|
if [ ${LDAP_AUTH_ENABLED} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9406 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Query LDAP servers in client configuration"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: checking ldap.conf options"
|
|
for FILE in ${LDAP_CONF_LOCATIONS}; do
|
|
LogText "Test: checking ${FILE}"
|
|
if [ -f ${FILE} ]; then
|
|
LogText "Result: file ${FILE} exists, LDAP being used"
|
|
LDAP_CLIENT_CONFIG_FILE="${FILE}"
|
|
LogText "Test: checking LDAP servers in file ${FILE}"
|
|
FIND=$(${EGREPBINARY} "^host " ${FILE} | ${AWKBINARY} '{ print $2 }')
|
|
for SERVER in ${FIND}; do
|
|
Display --indent 6 --text "LDAP server: ${SERVER}"
|
|
LogText "Result: found LDAP server ${SERVER}"
|
|
Report "ldap_server[]=${SERVER}"
|
|
done
|
|
else
|
|
LogText "Result: ${FILE} does NOT exist"
|
|
fi
|
|
done
|
|
unset FILE FIND SERVER
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9408
|
|
# Description : Logging of failed login attempts
|
|
Register --test-no AUTH-9408 --weight L --network NO --category security --description "Logging of failed login attempts"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if [ -f "${ROOTDIR}etc/pam.conf" ]; then
|
|
FOUND_PAM_TALLY2=0
|
|
FOUND_TALLYLOG=0
|
|
if [ -s "${ROOTDIR}var/log/tallylog" ]; then
|
|
FOUND_TALLYLOG=1
|
|
LogText "Result: found ${ROOTDIR}var/log/tallylog with a size bigger than zero"
|
|
else
|
|
LogText "Result: did not find ${ROOTDIR}var/log/tallylog on disk or its file size is zero bytes"
|
|
fi
|
|
# Determine if pam_tally2 is available
|
|
for D in $(GetReportData --key "pam_module\\\[\\\]"); do
|
|
if ContainsString "pam_tally2" "${D}"; then
|
|
LogText "Result: found pam_tally2 module on disk"
|
|
FOUND_PAM_TALLY2=1
|
|
fi
|
|
done
|
|
if [ ${FOUND_PAM_TALLY2} -eq 1 -a ${FOUND_TALLYLOG} -eq 1 ]; then
|
|
LogText "Outcome: authentication failures are logged using pam_tally2"
|
|
AUTH_FAILED_LOGINS_LOGGED=1
|
|
Report "auth_failed_logins_tooling[]=pam_tally2"
|
|
else
|
|
LogText "Outcome: it looks like pam_tally2 is not configured to log failed login attempts"
|
|
fi
|
|
|
|
unset FOUND_PAM_TALLY2 FOUND_TALLYLOG
|
|
fi
|
|
# Also check /etc/logins.defs, although its usage decreased over the years
|
|
if [ -f ${ROOTDIR}etc/login.defs ]; then
|
|
LogText "Test: Checking FAILLOG_ENAB option in ${ROOTDIR}etc/login.defs "
|
|
FIND=$(${GREPBINARY} "^FAILLOG_ENAB" ${ROOTDIR}etc/login.defs | ${AWKBINARY} '{ if ($1=="FAILLOG_ENAB") { print $2 } }')
|
|
# Search for enabled status (yes), otherwise consider it to be disabled (e.g. empty, or other value)
|
|
if [ "${FIND}" = "yes" ]; then
|
|
AUTH_FAILED_LOGINS_LOGGED=1
|
|
Report "auth_failed_logins_tooling[]=/etc/login.defs"
|
|
LogText "Result: FAILLOG_ENAB is set to 'yes'"
|
|
LogText "Outcome: failed login attempts are logged in ${ROOTDIR}var/log/faillog"
|
|
Display --indent 2 --text "- Logging failed login attempts" --result "${STATUS_ENABLED}" --color GREEN
|
|
else
|
|
LogText "Result: failed login attempts may not logged"
|
|
Display --indent 2 --text "- Logging failed login attempts" --result "${STATUS_DISABLED}" --color YELLOW
|
|
fi
|
|
fi
|
|
|
|
if [ ${AUTH_FAILED_LOGINS_LOGGED} -eq 1 ]; then
|
|
AddHP 3 3
|
|
else
|
|
AddHP 0 1
|
|
#ReportSuggestion "${TEST_NO}" "Configure failed login attempts to be logged using pam_tally2 or /etc/login.defs"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9409
|
|
# Description : Check for doas file
|
|
DOAS_FILE=""
|
|
Register --test-no AUTH-9409 --os OpenBSD --weight L --network NO --category security --description "Checking /etc/doas.conf file"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
LogText "Test: checking presence /etc/doas.conf"
|
|
if [ -f /etc/doas.conf ]; then
|
|
DOAS_FILE=/etc/doas.conf
|
|
FOUND=1
|
|
LogText "Result: file /etc/doas.conf found"
|
|
else
|
|
LogText "Result: file /etc/doas.conf not found"
|
|
fi
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
LogText "Result: /etc/doas.conf file found"
|
|
Display --indent 2 --text "- doas file" --result "${STATUS_FOUND}" --color GREEN
|
|
else
|
|
LogText "Result: doas file NOT found"
|
|
Display --indent 2 --text "- doas file" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : AUTH-9410
|
|
# Description : Check for doas file permissions
|
|
if [ -n "${DOAS_FILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no AUTH-9410 --os OpenBSD --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check /etc/doas.conf file permissions"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: checking /etc/doas.conf permissions"
|
|
FIND=$(ls -l ${DOAS_FILE} | ${CUTBINARY} -c 2-10)
|
|
LogText "Result: Found /etc/doas.conf file permissions: ${FIND}"
|
|
case "${FIND}" in
|
|
r[w-]-[r-][w-]---- )
|
|
LogText "Result: file /etc/doas.conf has correct permissions"
|
|
Display --indent 4 --text "- Check doas file permissions" --result "${STATUS_OK}" --color GREEN
|
|
;;
|
|
* )
|
|
LogText "Result: file has possibly unsafe file permissions"
|
|
Display --indent 4 --text "- Check doas file permissions" --result "${STATUS_WARNING}" --color RED
|
|
;;
|
|
esac
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
|
|
Report "auth_failed_logins_logged=${AUTH_FAILED_LOGINS_LOGGED}"
|
|
Report "ldap_auth_enabled=${LDAP_AUTH_ENABLED}"
|
|
Report "ldap_pam_enabled=${LDAP_PAM_ENABLED}"
|
|
if [ -n "${LDAP_CLIENT_CONFIG_FILE}" ]; then Report "ldap_config_file=${LDAP_CLIENT_CONFIG_FILE}"; fi
|
|
Report "password_min_days=${PASSWORD_MINIMUM_DAYS}"
|
|
Report "password_max_days=${PASSWORD_MAXIMUM_DAYS}"
|
|
|
|
WaitForKeyPress
|
|
|
|
#
|
|
#================================================================================
|
|
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com
|