IMP: enhance scripts that check duplicate UID

Add exception handling in 13.14_check_duplicate_uid
Clarifies output message and explicitly displays found exceptions
Add tests
Apply shellcheck recommendation

modified:   bin/hardening/13.14_check_duplicate_uid.sh
modified:   bin/hardening/13.5_find_0_uid_non_root_account.sh
new file:   tests/hardening/13.14_check_duplicate_uid.sh
new file:   tests/hardening/13.5_find_0_uid_non_root_account.sh
This commit is contained in:
Charles Herlin 2019-02-13 16:07:06 +01:00
parent 7e3ee2eb93
commit 7ad0df963c
4 changed files with 116 additions and 25 deletions

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# run-shellcheck
# #
# CIS Debian Hardening # CIS Debian Hardening
# #
@ -11,28 +11,38 @@
set -e # One error, it's over set -e # One error, it's over
set -u # One variable unset, it's over set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2 HARDENING_LEVEL=2
DESCRIPTION="There is no duplicate UIDs." # shellcheck disable=2034
DESCRIPTION="Checking for duplicate UIDs."
EXCEPTIONS=""
ERRORS=0 ERRORS=0
# This function will be called if the script status is on enabled / audit mode # This function will be called if the script status is on enabled / audit mode
audit () { audit () {
RESULT=$(cat /etc/passwd | cut -f3 -d":" | sort -n | uniq -c | awk {'print $1":"$2'} ) RESULT=$(cut -f3 -d":" < /etc/passwd | sort -n | uniq -c | awk '{print $1":"$2}' )
for LINE in $RESULT; do FOUND_EXCEPTIONS=""
for LINE in $RESULT; do
debug "Working on line $LINE" debug "Working on line $LINE"
OCC_NUMBER=$(awk -F: {'print $1'} <<< $LINE) OCC_NUMBER=$(awk -F: '{print $1}' <<< "$LINE")
USERID=$(awk -F: {'print $2'} <<< $LINE) USERID=$(awk -F: '{print $2}' <<< "$LINE")
if [ $OCC_NUMBER -gt 1 ]; then if [ "$OCC_NUMBER" -gt 1 ]; then
USERS=$(awk -F: '($3 == n) { print $1 }' n=$USERID /etc/passwd | xargs) USERS=$(awk -F: '($3 == n) { print $1 }' n="$USERID" /etc/passwd | xargs)
ERRORS=$((ERRORS+1)) ID_NAMES="($USERID): ${USERS}"
crit "Duplicate UID ($USERID): ${USERS}" if echo "$EXCEPTIONS" | grep -qw "$USERID"; then
debug "$USERID is confirmed as an exception"
FOUND_EXCEPTIONS="$FOUND_EXCEPTIONS $ID_NAMES"
else
ERRORS=$((ERRORS+1))
crit "Duplicate UID $ID_NAMES"
fi
fi fi
done done
if [ $ERRORS = 0 ]; then if [ $ERRORS = 0 ]; then
ok "No duplicate UIDs" ok "No duplicate UIDs${FOUND_EXCEPTIONS:+ apart from configured exceptions:}${FOUND_EXCEPTIONS}"
fi fi
} }
# This function will be called if the script status is on enabled mode # This function will be called if the script status is on enabled mode
@ -40,9 +50,20 @@ apply () {
info "Editing automatically uids may seriously harm your system, report only here" info "Editing automatically uids may seriously harm your system, report only here"
} }
# This function will create the config file for this check with default values
create_config() {
cat <<EOF
status=disabled
# Put here valid UIDs for which multiple usernames are accepted
EXCEPTIONS=""
EOF
}
# This function will check config parameters required # This function will check config parameters required
check_config() { check_config() {
: if [ -z "$EXCEPTIONS" ]; then
EXCEPTIONS="@"
fi
} }
# Source Root Dir Parameter # Source Root Dir Parameter
@ -56,8 +77,9 @@ if [ -z "$CIS_ROOT_DIR" ]; then
fi fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled) # Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r $CIS_ROOT_DIR/lib/main.sh ]; then if [ -r "$CIS_ROOT_DIR"/lib/main.sh ]; then
. $CIS_ROOT_DIR/lib/main.sh # shellcheck source=/opt/debian-cis/lib/main.sh
. "$CIS_ROOT_DIR"/lib/main.sh
else else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_ROOT_DIR in /etc/default/cis-hardening" echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_ROOT_DIR in /etc/default/cis-hardening"
exit 128 exit 128

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# run-shellcheck
# #
# CIS Debian Hardening # CIS Debian Hardening
# #
@ -11,8 +11,11 @@
set -e # One error, it's over set -e # One error, it's over
set -u # One variable unset, it's over set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2 HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Verify root is the only UID 0 account." DESCRIPTION="Verify root is the only UID 0 account."
EXCEPTIONS=""
FILE='/etc/passwd' FILE='/etc/passwd'
RESULT='' RESULT=''
@ -20,23 +23,24 @@ RESULT=''
# This function will be called if the script status is on enabled / audit mode # This function will be called if the script status is on enabled / audit mode
audit () { audit () {
info "Checking if accounts have uid 0" info "Checking if accounts have uid 0"
RESULT=$(cat $FILE | awk -F: '($3 == 0 && $1!="root" ) { print $1 }') RESULT=$(awk -F: '($3 == 0 && $1!="root" ) { print $1 }' "$FILE" )
FOUND_EXCEPTIONS=""
for ACCOUNT in $RESULT; do for ACCOUNT in $RESULT; do
debug "Account : $ACCOUNT" debug "Account : $ACCOUNT"
debug "Exceptions : $EXCEPTIONS" debug "Exceptions : $EXCEPTIONS"
debug "echo \"$EXCEPTIONS\" | grep -q $ACCOUNT" debug "echo \"$EXCEPTIONS\" | grep -qw $ACCOUNT"
if echo "$EXCEPTIONS" | grep -q $ACCOUNT; then if echo "$EXCEPTIONS" | grep -qw "$ACCOUNT"; then
debug "$ACCOUNT is confirmed as an exception" debug "$ACCOUNT is confirmed as an exception"
RESULT=$(sed "s!$ACCOUNT!!" <<< "$RESULT") RESULT=$(sed "s!$ACCOUNT!!" <<< "$RESULT")
FOUND_EXCEPTIONS="$FOUND_EXCEPTIONS $ACCOUNT"
else else
debug "$ACCOUNT not found in exceptions" debug "$ACCOUNT not found in exceptions"
fi fi
done done
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some accounts have uid 0" crit "Some accounts have uid 0: $(tr '\n' ' ' <<< "$RESULT")"
crit $RESULT
else else
ok "No account with uid 0 appart from root and potential configured exceptions" ok "No account with uid 0 appart from root ${FOUND_EXCEPTIONS:+and configured exceptions:}$FOUND_EXCEPTIONS"
fi fi
} }
@ -72,8 +76,9 @@ if [ -z "$CIS_ROOT_DIR" ]; then
fi fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled) # Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r $CIS_ROOT_DIR/lib/main.sh ]; then if [ -r "$CIS_ROOT_DIR"/lib/main.sh ]; then
. $CIS_ROOT_DIR/lib/main.sh # shellcheck source=/opt/debian-cis/lib/main.sh
. "$CIS_ROOT_DIR"/lib/main.sh
else else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_ROOT_DIR in /etc/default/cis-hardening" echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_ROOT_DIR in /etc/default/cis-hardening"
exit 128 exit 128

View File

@ -0,0 +1,33 @@
# run-shellcheck
test_audit() {
describe Running on blank host
register_test retvalshouldbe 0
register_test contain "[ OK ] No duplicate UIDs"
# shellcheck disable=2154
run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
useradd usertest1
useradd usertest2
sed -i 's/1001/1000/g' /etc/passwd
# Proceed to operation that will end up to a non compliant system
describe Tests purposely failing
register_test retvalshouldbe 1
register_test contain "[ KO ] Duplicate UID (1000): usertest1 usertest2"
run noncompliant /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
# shellcheck disable=2016
echo 'EXCEPTIONS="$EXCEPTIONS 1000"' >> /opt/debian-cis/etc/conf.d/"${script}".cfg
describe Adding exceptions
register_test retvalshouldbe 0
register_test contain "[ OK ] No duplicate UIDs apart from configured exceptions: (1000): usertest1 usertest2"
run exception /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
# Cleanup
userdel usertest1
userdel usertest2
sed -i '/usertest1/d' /etc/group
sed -i '/usertest2/d' /etc/group
}

View File

@ -0,0 +1,31 @@
# run-shellcheck
test_audit() {
describe Running on blank host
register_test retvalshouldbe 0
register_test contain "[ OK ] No account with uid 0 appart from root"
# shellcheck disable=2154
run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
useradd usertest1
sed -i 's/1000/0/g' /etc/passwd
# Proceed to operation that will end up to a non compliant system
describe Tests purposely failing
register_test retvalshouldbe 1
register_test contain "[ KO ] Some accounts have uid 0: usertest1"
run noncompliant /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
# shellcheck disable=2016
echo 'EXCEPTIONS="$EXCEPTIONS usertest1"' >> /opt/debian-cis/etc/conf.d/"${script}".cfg
describe Adding exceptions
register_test retvalshouldbe 0
register_test contain "[ OK ] No account with uid 0 appart from root and configured exceptions: usertest1"
run exception /opt/debian-cis/bin/hardening/"${script}".sh --audit-all
# Cleanup
sed -i '/usertest1/d' /etc/passwd
sed -i '/usertest1/d' /etc/shadow
sed -i '/usertest1/d' /etc/group
}