Add sudo management in main and utils

* perform readonly checks as a regular user
    * sudo -n is used for checks requiring root privileges
    * increase accountability by providing log of individual access to sensitive files
This commit is contained in:
Charles Herlin 2017-11-09 15:45:42 +01:00
parent b5a952e0f0
commit b41df080cf
30 changed files with 187 additions and 53 deletions

View File

@ -80,6 +80,11 @@ configuration. It will run all scripts in audit mode. If a script passes,
it will automatically be enabled for future runs. Do NOT use this option it will automatically be enabled for future runs. Do NOT use this option
if you have already started to customize your configuration. if you have already started to customize your configuration.
``--sudo``: Audit your system as a normal user, but allow sudo escalation to read
specific root read-only files. You need to provide a sudoers file in /etc/sudoers.d/
with NOPASWD option, since checks are executed with ``sudo -n`` option, that will
not prompt for a password.
## Hacking ## Hacking
**Getting the source** **Getting the source**

View File

@ -22,6 +22,7 @@ AUDIT_ALL=0
AUDIT_ALL_ENABLE_PASSED=0 AUDIT_ALL_ENABLE_PASSED=0
ALLOW_SERVICE_LIST=0 ALLOW_SERVICE_LIST=0
SET_HARDENING_LEVEL=0 SET_HARDENING_LEVEL=0
SUDO_MODE=''
usage() { usage() {
cat << EOF cat << EOF
@ -83,6 +84,13 @@ OPTIONS:
The test number is the numbered prefix of the script, The test number is the numbered prefix of the script,
i.e. the test number of 1.2_script_name.sh is 1.2. i.e. the test number of 1.2_script_name.sh is 1.2.
--sudo
This option lets you audit your system as a normal user, but allows sudo
escalation to gain read-only access to root files. Note that you need to
provide a sudoers file with NOPASSWD option in /etc/sudoers.d/ because
the '-n' option instructs sudo not to prompt for a password.
Finally note that '--sudo' mode only works for audit mode.
EOF EOF
exit 0 exit 0
} }
@ -124,6 +132,9 @@ while [[ $# > 0 ]]; do
TEST_LIST[${#TEST_LIST[@]}]="$2" TEST_LIST[${#TEST_LIST[@]}]="$2"
shift shift
;; ;;
--sudo)
SUDO_MODE='--sudo'
;;
-h|--help) -h|--help)
usage usage
;; ;;
@ -197,14 +208,14 @@ for SCRIPT in $(ls $CIS_ROOT_DIR/bin/hardening/*.sh -v); do
info "Treating $SCRIPT" info "Treating $SCRIPT"
if [ $AUDIT = 1 ]; then if [ $AUDIT = 1 ]; then
debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit" debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit $SUDO_MODE"
$SCRIPT --audit $SCRIPT --audit $SUDO_MODE
elif [ $AUDIT_ALL = 1 ]; then elif [ $AUDIT_ALL = 1 ]; then
debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit-all" debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit-all $SUDO_MODE"
$SCRIPT --audit-all $SCRIPT --audit-all $SUDO_MODE
elif [ $AUDIT_ALL_ENABLE_PASSED = 1 ]; then elif [ $AUDIT_ALL_ENABLE_PASSED = 1 ]; then
debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit-all" debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT --audit-all $SUDO_MODE"
$SCRIPT --audit-all $SCRIPT --audit-all $SUDO_MODE
elif [ $APPLY = 1 ]; then elif [ $APPLY = 1 ]; then
debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT" debug "$CIS_ROOT_DIR/bin/hardening/$SCRIPT"
$SCRIPT $SCRIPT

View File

@ -16,7 +16,7 @@ HARDENING_LEVEL=2
# 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 there are suid files" info "Checking if there are suid files"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000 -print) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -type f -perm -4000 -print)
for BINARY in $RESULT; do for BINARY in $RESULT; do
if grep -q $BINARY <<< "$EXCEPTIONS"; then if grep -q $BINARY <<< "$EXCEPTIONS"; then
debug "$BINARY is confirmed as an exception" debug "$BINARY is confirmed as an exception"

View File

@ -16,7 +16,7 @@ HARDENING_LEVEL=2
# 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 there are sgid files" info "Checking if there are sgid files"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 -print) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -type f -perm -2000 -print)
for BINARY in $RESULT; do for BINARY in $RESULT; do
if grep -q $BINARY <<< "$EXCEPTIONS"; then if grep -q $BINARY <<< "$EXCEPTIONS"; then
debug "$BINARY is confirmed as an exception" debug "$BINARY is confirmed as an exception"

View File

@ -16,7 +16,7 @@ HARDENING_LEVEL=3
# 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 there are world writable files" info "Checking if there are world writable files"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002 -print 2>/dev/null) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -type f -perm -0002 -print 2>/dev/null)
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some world writable files are present" crit "Some world writable files are present"
FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ') FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ')

View File

@ -18,7 +18,7 @@ USER='root'
# 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 there are unowned files" info "Checking if there are unowned files"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -nouser -print 2>/dev/null) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -nouser -print 2>/dev/null)
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some unowned files are present" crit "Some unowned files are present"
FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ') FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ')

View File

@ -18,7 +18,7 @@ GROUP='root'
# 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 there are ungrouped files" info "Checking if there are ungrouped files"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -nogroup -print 2>/dev/null) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -nogroup -print 2>/dev/null)
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some ungrouped files are present" crit "Some ungrouped files are present"
FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ') FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ')

View File

@ -18,7 +18,7 @@ FILE='/etc/shadow'
# 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 an empty password" info "Checking if accounts have an empty password"
RESULT=$(cat $FILE | awk -F: '($2 == "" ) { print $1 }') RESULT=$($SUDO_CMD cat $FILE | awk -F: '($2 == "" ) { print $1 }')
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some accounts have an empty password" crit "Some accounts have an empty password"
crit $RESULT crit $RESULT

View File

@ -19,7 +19,7 @@ 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 a legacy password entry" info "Checking if accounts have a legacy password entry"
if grep '^+:' $FILE -q; then if $SUDO_CMD grep '^+:' $FILE -q; then
RESULT=$(grep '^+:' $FILE) RESULT=$(grep '^+:' $FILE)
crit "Some accounts have a legacy password entry" crit "Some accounts have a legacy password entry"
crit $RESULT crit $RESULT

View File

@ -16,7 +16,7 @@ HARDENING_LEVEL=2
# 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 setuid is set on world writable Directories" info "Checking if setuid is set on world writable Directories"
RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d \( -perm -0002 -a ! -perm -1000 \) -print 2>/dev/null) RESULT=$(df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' $SUDO_CMD find '{}' -xdev -type d \( -perm -0002 -a ! -perm -1000 \) -print 2>/dev/null)
if [ ! -z "$RESULT" ]; then if [ ! -z "$RESULT" ]; then
crit "Some world writable directories are not on sticky bit mode!" crit "Some world writable directories are not on sticky bit mode!"
FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ') FORMATTED_RESULT=$(sed "s/ /\n/g" <<< $RESULT | sort | uniq | tr '\n' ' ')

View File

@ -19,7 +19,7 @@ PATTERN='NX[[:space:]]\(Execute[[:space:]]Disable\)[[:space:]]protection:[[:spac
nx_supported_and_enabled() { nx_supported_and_enabled() {
if grep -q ' nx ' /proc/cpuinfo; then if grep -q ' nx ' /proc/cpuinfo; then
# NX supported, but if noexec=off specified, it's not enabled # NX supported, but if noexec=off specified, it's not enabled
if grep -qi 'noexec=off' /proc/cmdline; then if $SUDO_CMD grep -qi 'noexec=off' /proc/cmdline; then
FNRET=1 # supported but disabled FNRET=1 # supported but disabled
else else
FNRET=0 # supported and enabled FNRET=0 # supported and enabled

View File

@ -17,7 +17,7 @@ HARDENING_EXCEPTION=mail
# 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 netport ports opened" info "Checking netport ports opened"
RESULT=$(netstat -an | grep LIST | grep ":25[[:space:]]") || : RESULT=$($SUDO_CMD netstat -an | grep LIST | grep ":25[[:space:]]") || :
RESULT=${RESULT:-} RESULT=${RESULT:-}
debug "Result is $RESULT" debug "Result is $RESULT"
if [ -z "$RESULT" ]; then if [ -z "$RESULT" ]; then

View File

@ -23,16 +23,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -21,16 +21,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -14,23 +14,30 @@ set -u # One variable unset, it's over
HARDENING_LEVEL=4 HARDENING_LEVEL=4
# Find all files with setuid or setgid set # Find all files with setuid or setgid set
AUDIT_PARAMS=$(find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print \ SUDO_CMD='sudo -n'
AUDIT_PARAMS=$($SUDO_CMD find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print \
"-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=4294967295 \ "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=4294967295 \
-k privileged" }') -k privileged" }')
FILE='/etc/audit/audit.rules' FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -19,16 +19,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -19,16 +19,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -19,16 +19,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -18,16 +18,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -21,16 +21,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -18,16 +18,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -22,16 +22,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -22,16 +22,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -23,16 +23,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -18,16 +18,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -20,16 +20,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

View File

@ -20,16 +20,22 @@ FILE='/etc/audit/audit.rules'
# 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 () {
IFS=$'\n' # define custom IFS and save default one
d_IFS=$IFS
c_IFS=$'\n'
IFS=$c_IFS
for AUDIT_VALUE in $AUDIT_PARAMS; do for AUDIT_VALUE in $AUDIT_PARAMS; do
debug "$AUDIT_VALUE should be in file $FILE" debug "$AUDIT_VALUE should be in file $FILE"
IFS=$d_IFS
does_pattern_exist_in_file $FILE $AUDIT_VALUE does_pattern_exist_in_file $FILE $AUDIT_VALUE
IFS=$c_IFS
if [ $FNRET != 0 ]; then if [ $FNRET != 0 ]; then
crit "$AUDIT_VALUE is not in file $FILE" crit "$AUDIT_VALUE is not in file $FILE"
else else
ok "$AUDIT_VALUE is present in $FILE" ok "$AUDIT_VALUE is present in $FILE"
fi fi
done done
IFS=$d_IFS
} }
# 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

23
cisharden.sudoers Normal file
View File

@ -0,0 +1,23 @@
Cmnd_Alias SCL_CMD = /bin/grep ,\
/bin/zgrep,\
/bin/cat,\
/usr/bin/stat,\
/usr/bin/getent,\
/usr/bin/[,\
/bin/ls,\
/usr/bin/find,\
! /usr/bin/find *-exec*, \
! /usr/bin/find *-delete*,\
/usr/bin/apt-get update -y,\
/usr/bin/apt-get upgrade -s,\
/usr/bin/cut,\
/sbin/iptables -nL,\
/sbin/iptables -nL *,\
/sbin/sysctl net.*,\
/sbin/sysctl fs.*,\
/sbin/sysctl kernel.*,\
/sbin/sysctl -a,\
/bin/dmesg "",\
/bin/netstat
cisharden ALL = (root) NOPASSWD: SCL_CMD

View File

@ -4,6 +4,7 @@ SCRIPT_NAME=${LONG_SCRIPT_NAME%.sh}
CRITICAL_ERRORS_NUMBER=0 # This will be used to see if a script failed, or passed CRITICAL_ERRORS_NUMBER=0 # This will be used to see if a script failed, or passed
status="" status=""
forcedstatus="" forcedstatus=""
SUDO_CMD=""
[ -r $CIS_ROOT_DIR/lib/constants.sh ] && . $CIS_ROOT_DIR/lib/constants.sh [ -r $CIS_ROOT_DIR/lib/constants.sh ] && . $CIS_ROOT_DIR/lib/constants.sh
[ -r $CIS_ROOT_DIR/etc/hardening.cfg ] && . $CIS_ROOT_DIR/etc/hardening.cfg [ -r $CIS_ROOT_DIR/etc/hardening.cfg ] && . $CIS_ROOT_DIR/etc/hardening.cfg
@ -31,6 +32,9 @@ while [[ $# > 0 ]]; do
info "Audit argument passed but script is disabled" info "Audit argument passed but script is disabled"
fi fi
;; ;;
--sudo)
SUDO_CMD="sudo -n"
;;
*) *)
debug "Unknown option passed" debug "Unknown option passed"
;; ;;

View File

@ -8,7 +8,7 @@ has_sysctl_param_expected_result() {
local SYSCTL_PARAM=$1 local SYSCTL_PARAM=$1
local EXP_RESULT=$2 local EXP_RESULT=$2
if [ "$(sysctl $SYSCTL_PARAM 2>/dev/null)" = "$SYSCTL_PARAM = $EXP_RESULT" ]; then if [ "$($SUDO_CMD sysctl $SYSCTL_PARAM 2>/dev/null)" = "$SYSCTL_PARAM = $EXP_RESULT" ]; then
FNRET=0 FNRET=0
elif [ $? = 255 ]; then elif [ $? = 255 ]; then
debug "$SYSCTL_PARAM does not exist" debug "$SYSCTL_PARAM does not exist"
@ -21,7 +21,7 @@ has_sysctl_param_expected_result() {
does_sysctl_param_exists() { does_sysctl_param_exists() {
local SYSCTL_PARAM=$1 local SYSCTL_PARAM=$1
if [ "$(sysctl -a 2>/dev/null |grep "$SYSCTL_PARAM" -c)" = 0 ]; then if [ "$($SUDO_CMD sysctl -a 2>/dev/null |grep "$SYSCTL_PARAM" -c)" = 0 ]; then
FNRET=1 FNRET=1
else else
FNRET=0 FNRET=0
@ -50,7 +50,7 @@ set_sysctl_param() {
does_pattern_exist_in_dmesg() { does_pattern_exist_in_dmesg() {
local PATTERN=$1 local PATTERN=$1
if $(dmesg | grep -qE "$PATTERN"); then if $($SUDO_CMD dmesg | grep -qE "$PATTERN"); then
FNRET=0 FNRET=0
else else
FNRET=1 FNRET=1
@ -63,7 +63,7 @@ does_pattern_exist_in_dmesg() {
does_file_exist() { does_file_exist() {
local FILE=$1 local FILE=$1
if [ -e $FILE ]; then if $SUDO_CMD [ -e $FILE ]; then
FNRET=0 FNRET=0
else else
FNRET=1 FNRET=1
@ -76,8 +76,8 @@ has_file_correct_ownership() {
local GROUP=$3 local GROUP=$3
local USERID=$(id -u $USER) local USERID=$(id -u $USER)
local GROUPID=$(getent group $GROUP | cut -d: -f3) local GROUPID=$(getent group $GROUP | cut -d: -f3)
debug "stat -c '%u %g' $FILE" debug "$SUDO_CMD stat -c '%u %g' $FILE"
if [ "$(stat -c "%u %g" $FILE)" = "$USERID $GROUPID" ]; then if [ "$($SUDO_CMD stat -c "%u %g" $FILE)" = "$USERID $GROUPID" ]; then
FNRET=0 FNRET=0
else else
FNRET=1 FNRET=1
@ -88,7 +88,7 @@ has_file_correct_permissions() {
local FILE=$1 local FILE=$1
local PERMISSIONS=$2 local PERMISSIONS=$2
if [ $(stat -L -c "%a" $1) = "$PERMISSIONS" ]; then if [ $($SUDO_CMD stat -L -c "%a" $1) = "$PERMISSIONS" ]; then
FNRET=0 FNRET=0
else else
FNRET=1 FNRET=1
@ -100,9 +100,9 @@ does_pattern_exist_in_file() {
local PATTERN=$2 local PATTERN=$2
debug "Checking if $PATTERN is present in $FILE" debug "Checking if $PATTERN is present in $FILE"
if [ -r "$FILE" ] ; then if $SUDO_CMD [ -r "$FILE" ] ; then
debug "grep -qE -- '$PATTERN' $FILE" debug "$SUDO_CMD grep -qE -- '$PATTERN' $FILE"
if $(grep -qE -- "$PATTERN" $FILE); then if $($SUDO_CMD grep -qE -- "$PATTERN" $FILE); then
FNRET=0 FNRET=0
else else
FNRET=1 FNRET=1
@ -189,7 +189,7 @@ does_group_exist() {
is_service_enabled() { is_service_enabled() {
local SERVICE=$1 local SERVICE=$1
if [ $(find /etc/rc?.d/ -name "S*$SERVICE" -print | wc -l) -gt 0 ]; then if [ $($SUDO_CMD find /etc/rc?.d/ -name "S*$SERVICE" -print | wc -l) -gt 0 ]; then
debug "Service $SERVICE is enabled" debug "Service $SERVICE is enabled"
FNRET=0 FNRET=0
else else
@ -209,10 +209,10 @@ is_kernel_option_enabled() {
if [ $# -ge 2 ] ; then if [ $# -ge 2 ] ; then
MODULE_NAME="$2" MODULE_NAME="$2"
fi fi
if [ -r "/proc/config.gz" ] ; then if $SUDO_CMD [ -r "/proc/config.gz" ] ; then
RESULT=$(zgrep "^$KERNEL_OPTION=" /proc/config.gz) || : RESULT=$($SUDO_CMD zgrep "^$KERNEL_OPTION=" /proc/config.gz) || :
elif [ -r "/boot/config-$(uname -r)" ] ; then elif $SUDO_CMD [ -r "/boot/config-$(uname -r)" ] ; then
RESULT=$(grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || : RESULT=$($SUDO_CMD grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || :
fi fi
ANSWER=$(cut -d = -f 2 <<< "$RESULT") ANSWER=$(cut -d = -f 2 <<< "$RESULT")
if [ "x$ANSWER" = "xy" ]; then if [ "x$ANSWER" = "xy" ]; then
@ -226,13 +226,13 @@ is_kernel_option_enabled() {
FNRET=2 # Not found FNRET=2 # Not found
fi fi
if [ "$FNRET" -ne 0 -a -n "$MODULE_NAME" -a -d "/lib/modules/$(uname -r)" ] ; then if $SUDO_CMD [ "$FNRET" -ne 0 -a -n "$MODULE_NAME" -a -d "/lib/modules/$(uname -r)" ] ; then
# also check in modules, because even if not =y, maybe # also check in modules, because even if not =y, maybe
# the admin compiled it separately later (or out-of-tree) # the admin compiled it separately later (or out-of-tree)
# as a module (regardless of the fact that we have =m or not) # as a module (regardless of the fact that we have =m or not)
debug "Checking if we have $MODULE_NAME.ko" debug "Checking if we have $MODULE_NAME.ko"
local modulefile=$(find "/lib/modules/$(uname -r)/" -type f -name "$MODULE_NAME.ko") local modulefile=$($SUDO_CMD find "/lib/modules/$(uname -r)/" -type f -name "$MODULE_NAME.ko")
if [ -n "$modulefile" ] ; then if $SUDO_CMD [ -n "$modulefile" ] ; then
debug "We do have $modulefile!" debug "We do have $modulefile!"
# ... but wait, maybe it's blacklisted? check files in /etc/modprobe.d/ for "blacklist xyz" # ... but wait, maybe it's blacklisted? check files in /etc/modprobe.d/ for "blacklist xyz"
if grep -qRE "^\s*blacklist\s+$MODULE_NAME\s*$" /etc/modprobe.d/ ; then if grep -qRE "^\s*blacklist\s+$MODULE_NAME\s*$" /etc/modprobe.d/ ; then
@ -334,10 +334,10 @@ apt_update_if_needed()
if [ $UPDATE_AGE -gt 21600 ] if [ $UPDATE_AGE -gt 21600 ]
then then
# update too old, refresh database # update too old, refresh database
apt-get update -y >/dev/null 2>/dev/null $SUDO_CMD apt-get update -y >/dev/null 2>/dev/null
fi fi
else else
apt-get update -y >/dev/null 2>/dev/null $SUDO_CMD apt-get update -y >/dev/null 2>/dev/null
fi fi
} }
@ -345,7 +345,7 @@ apt_check_updates()
{ {
local NAME="$1" local NAME="$1"
local DETAILS="/dev/shm/${NAME}" local DETAILS="/dev/shm/${NAME}"
apt-get upgrade -s 2>/dev/null | grep -E "^Inst" > $DETAILS || : $SUDO_CMD apt-get upgrade -s 2>/dev/null | grep -E "^Inst" > $DETAILS || :
local COUNT=$(wc -l < "$DETAILS") local COUNT=$(wc -l < "$DETAILS")
FNRET=128 # Unknown function return result FNRET=128 # Unknown function return result
RESULT="" # Result output for upgrade RESULT="" # Result output for upgrade