This is an old revision of the document!
This script 'll only list if compliant or not
root@aix /root# cat scripts/cis.sh
#!/usr/bin/ksh93 #@(#) Check security # This script doesn't modify something to your system, just list what is right and wrong # Print in red all commands to modify your settings # Print in green all parameters that need no change, following by OK # Version 1.0 06-2023 EIF (compliance CIS for AIX) dir=`dirname $0` if [ -f $dir/.env ] then . $dir/.env else path_script=$dir export sn=`basename $0 | cut -d. -f1` export logpath=/tmp export logname=$logpath/$sn.log fi DATE=$(date "+%Y%m%d%H%M%S") LINUX_SED=/opt/freeware/bin/sed LINUX_STAT=/opt/freeware/bin/stat LINUX_SORT=/opt/freeware/bin/sort list_files=$logpath/list_files.txt outputcis=$logpath/CIS_AIX7.2_v1.0.0 output=$logname prefix=sec_files_out_ outputdir=$logpath/${prefix}${DATE} mkdir $outputdir tempo=$logpath/tmp_cis # Cleanup find $logpath -type d -name "${prefix}*" -ctime +5 -exec rm -r {} \; 2>/dev/null #----------------------------------------- print_output() { # args header=$1 ruleno=$2 descr=$(echo "$3") result=$4 echo "$ruleno;$descr;$result" | sed 's/\|/\ /g' } #----------------------------------------- check_section_2_1() { # args head=h1 rule="2.1" desc="Collect system configuration regularly" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') file1=/var/log/syslog/inventory.log val=0 val1=$(ls $file1 > /dev/null 2>&1; echo $?) (( val = val + val1 )) if [ "$val" != "0" ] then res=NOK val1=$(cat /etc/syslog.conf | grep "local1.info" | grep -q "$file1"; echo $?) (( val = val + val1 )) if [ "$val" != "0" ] then res=NOK val1=$(cat /etc/syslog.conf | sed '/^$/d' | grep -v '^#' | grep "^local1.info" | awk '{print $2}' | grep -q "\@"; echo $?) (( val = val + val1 )) if [ "$val" != "0" ] then res=NOK val1=$(crontab -l | grep -v '^#' | grep "lsconf" | grep -q "logger"; echo $?) (( val = val + val1 )) if [ "$val" != "0" ] then res=NOK else res=OK fi fi fi else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_2_7() { # args head=h1 rule="2.7" desc="Remove Unused Symbolic Links" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') find -L / \( -fstype jfs -o -fstype jfs2 \) -type l -ls 2>/dev/null | cut -d'/' -f2- | sed 's/^/\//' | sed 's/\->/;/' | sed 's/\ ;/;/' | sed 's/;\ /;/' > $tempo.1 cat /dev/null > $tempo for line in $(cat $tempo.1 | sed 's/\ /|/g') do word1=$(echo $line | cut -d';' -f1 | sed 's/\|/\ /g') word2=$(echo $line | cut -d';' -f2 | sed 's/\|/\ /g') val=$(echo $word2 | grep -c '^/') if [[ "$val" -eq "1" ]] then if [ ! -e $word2 ] then echo $word1 >> $tempo fi else dir1=$(echo $word1 | rev | cut -d'/' -f2- | rev) word3=$(echo "$dir1/$word2") if [ ! -e $word3 ] then echo $word1 >> $tempo fi fi done > $tempo if [ ! -s $tempo ] then res=OK else res=NOK fi cp $tempo /root/link.txt print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_3() { # args head=h1 rule="3.3" desc="Ensure default user umask is 027 or more restrictive" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(lssec -f /etc/security/user -s default -a umask | grep -q 'umask=27';echo $?) if [ "$val" != "0" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_4() { # args head=h1 rule="3.4" desc="Remove group write permission from default groups - exceptions must be in TSD and audit" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(find / \( -fstype jfs -o -fstype jfs2 \) -type f -perm -g+w -ls | wc -l | awk '{print $1}') if [[ "$val" == "0" ]] then res=OK else res=Manual echo "$rule;$desc1;val=$val" >> $logname fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_5() { # args head=h1 rule="3.5" desc="Application Data with requirement for world writable directories" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(find / \( -fstype jfs -o -fstype jfs2 \) -type d -perm -o+w ! -perm -1000 -ls | wc -l | awk '{print $1}') if [[ "$val" == "0" ]] then res=OK else res=NOK echo "$rule;$desc1;val=$val" >> $logname fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_6() { # args head=h1 rule="3.6" desc="Ensure there are no world writable files - exceptions must be in TSD and audit" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(find / \( -fstype jfs -o -fstype jfs2 \) -type f -perm -o+w | wc -l | awk '{print $1}') if [[ "$val" == "0" ]] then res=OK else res=NOK echo "$rule;$desc1;val=$val" >> $logname fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_7() { # args head=h1 rule="3.7" desc="Ensure there are no 'staff' writable files - exceptions must be in TSD and audit" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(find / \( -fstype jfs -o -fstype jfs2 \) -type f -perm -g+w -group staff | wc -l | awk '{print $1}') if [[ "$val" == "0" ]] then res=OK else res=NOK echo "$rule;$desc1;val=$val" >> $logname fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_3_8() { # args head=h1 rule="3.8" desc="Ensure all files and directories are owned by a user (uid) and assigned to a group (gid)" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(find / \( -fstype jfs -o -fstype jfs2 \) \( -type d -o -type f \) \( -nouser -o -nogroup \) -ls | wc -l | awk '{print $1}') if [[ "$val" == "0" ]] then res=OK else res=NOK echo "$rule;$desc1;val=$val" >> $logname fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_1_3_1() { # args head=h1 rule="4.1.3.1" desc="autoconf6" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(cat /etc/rc.tcpip | grep '^start ' | grep -q "autoconf6";echo $?) if [ "$val" -eq "0" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_1_3_2() { # args head=h1 rule="4.1.3.2" desc="ndpd-host" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(cat /etc/rc.tcpip | grep '^start ' | grep -q "ndpd-host";echo $?) if [ "$val" -eq "0" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_1_3_3() { # args head=h1 rule="4.1.3.3" desc="ndpd-router" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(cat /etc/rc.tcpip | grep '^start ' | grep -q "ndpd-router";echo $?) if [ "$val" -eq "0" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_2_18() { # args head=h1 rule="4.2.18" desc="ip6forwarding" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(no -o ip6forwarding | sed 's/\ //g' | grep -q 'ip6forwarding=0'; echo $?) if [ "$val" -eq "0" ] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_3_1() { # args head=h1 rule="4.3.1" desc="Ensure that IP Security is available" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(lsdev -Cc ipsec 2>/dev/null | grep Available | wc -l | awk '{print $1}') if [ "$val" == "2" ] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_3_2() { # args head=h1 rule="4.3.2" desc="Ensure loopback traffic is blocked on external interfaces" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val1=$(lsfilt -v 4 -O 2>/dev/null | grep 127.0.0.0 | wc -l | awk '{print $1}') val2=$(lsfilt -v 6 -O 2>/dev/null | grep ::1 | wc -l | awk '{print $1}') (( val = val1 + val2 )) if [ "$val" == "2" ] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_3_3() { # args head=h1 rule="4.3.3" desc="Ensure that IPsec filters are active" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val1=$(lsfilt -v4 -O -a 2>/dev/null | grep -q inactive | awk '{print $1}') val2=$(lsfilt -v6 -O -a 2>/dev/null | grep -q inactive | awk '{print $1}') (( val = val1 + val2 )) if [ "$val" == "0" ] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_1_7() { # args head=h1 rule="4.5.1.7" desc="CDE - screensaver lock" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') if [ -e /etc/dt/config/*/sys.resources ] then val=$(egrep "dtsession\*saverTimeout:|dtsession\*lockTimeout:" /etc/dt/config/*/sys.resources | rev | cut -d' ' -f1 | rev | awk '{print $1}' | sort -u) if [ "$val" == "10" ] then res=OK else res=NOK fi else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_2_1() { # args head=h1 rule="4.5.2.1" desc="FTPD: Disable root access to ftpd" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep -q "root" /etc/ftpusers 2>/dev/null; echo $?) if [ "$val" -ne "0" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_2_2() { # args head=h1 rule="4.5.2.2" desc="FTPD: Display acceptable usage policy during login" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') # If ftp is disable, doesn't check val=$(grep -c "^ftp[[:blank:]]" /etc/inetd.conf) if [[ $val -gt 0 ]] then val=$(lslpp -Lc | grep "bos.msg.en_US.net.tcp.client" | wc -l | awk '{print $1}') if [ "$val" == "0" ] then res=NOK else if [ `lslpp -L "bos.msg.en_US.net.tcp.client" >/dev/null && print $(dspcat /usr/lib/nls/msg/en_US/ftpd.cat 1 9) | grep -q "Authorized"; echo $?` -ne "0" ] then res=NOK else res=OK fi fi else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_2_3() { # args head=h1 rule="4.5.2.3" desc="FTPD: Prevent world access and group write to files" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') # If ftp is disable, doesn't check val=$(grep -c "^ftp[[:blank:]]" /etc/inetd.conf) if [[ $val -gt 0 ]] then val=$(grep "^ftp[[:blank:]]" /etc/inetd.conf |awk '{print $6, $7, $8, $9, $10}' | grep -c "027") if [ "$val" == "1" ] then res=OK else res=NOK fi else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_1() { # args head=h1 rule="4.5.3.1" desc="OpenSSH: Minimum version is 8.1" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val1=$(sshd -i </dev/null | cut -d'_' -f 2) val=$(echo "$val1 8.1" | awk '{print ($1 >= $2)}') if [[ "$val" -eq "1" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_4() { # args head=h1 rule="4.5.3.4" desc="sshd_config: Restrict users and groups allowed access via OpenSSH" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(/usr/bin/egrep -c "^(AllowUsers|AllowGroups|DenyUsers|DenyGroups)[[:blank:]]" /etc/ssh/sshd_config) if [[ "$val" -gt "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_5() { # args head=h1 rule="4.5.3.5" desc="sshd_config: PermitRootLogin is 'prohibit-password' or 'no'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(/usr/bin/egrep "^PermitRootLogin" /etc/ssh/sshd_config | cut -d' ' -f2- | egrep -c "prohibit-password|no|forced-commands-only") if [[ "$val" -eq "0" ]] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_6() { # args head=h1 rule="4.5.3.6" desc="sshd_config: Banner exists and message contains 'Only authorized users allowed'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^Banner[[:blank:]]" /etc/ssh/sshd_config | grep -c '/etc/ssh/ssh_banner') if [ "$val" == "1" ] then val=$(grep -c 'Unauthorized' /etc/ssh/ssh_banner) if [ "$val" == "1" ] then res=OK else res=NOK fi else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_7() { # args head=h1 rule="4.5.3.7" desc="sshd_config: HostbasedAuthentication is 'no'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^HostbasedAuthentication[[:blank:]]" /etc/ssh/sshd_config | rev | cut -d' ' -f1 | rev) if [[ "$val" == "no" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_8() { # args head=h1 rule="4.5.3.8" desc="sshd_config: IgnoreRhosts is 'yes' or 'shosts-only'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^IgnoreRhosts[[:blank:]]" /etc/ssh/sshd_config | rev | cut -d' ' -f1 | rev) if [[ "$val" == "yes" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_9() { # args head=h1 rule="4.5.3.9" desc="sshd_config: PermitEmptyPasswords is 'no'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^PermitEmptyPasswords[[:blank:]]" /etc/ssh/sshd_config | rev | cut -d' ' -f1 | rev) if [[ "$val" == "no" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_10() { # args head=h1 rule="4.5.3.10" desc="sshd_config: LogLevel is 'INFO' or 'VERBOSE'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^LogLevel[[:blank:]]" /etc/ssh/sshd_config | egrep -c "INFO|VERBOSE") if [[ "$val" -eq "0" ]] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_11() { # args head=h1 rule="4.5.3.11" desc="sshd_config: sftp-server arguments include '-u 027 -f AUTH -l INFO'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^Subsystem[[:blank:]]sftp" /etc/ssh/sshd_config | grep sftp-server | grep -c "027") if [[ "$val" -eq "0" ]] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_12() { # args head=h1 rule="4.5.3.12" desc="sshd_config: MaxAuthTries is '4'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(sshd -T | grep maxauthtries | rev | awk '{print $1}' | rev) if [ "$val" -gt "4" ] then res=NOK else res=OK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_13() { # args head=h1 rule="4.5.3.13" desc="sshd_config: PermitUserEnvironment is 'no'" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(grep "^PermitUserEnvironment[[:blank:]]" /etc/ssh/sshd_config | rev | cut -d' ' -f1 | rev) if [[ "$val" == "no" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_14() { # args head=h1 rule="4.5.3.14" desc="sshd_config: Use Conditional exception(s)." res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(/usr/bin/egrep -cp "^Match " /etc/ssh/sshd_config) if [[ "$val" -eq "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_15() { # args head=h1 rule="4.5.3.15" desc="sshd_config, ssh_config: KexAlgorithms" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | grep -v '^#' | awk '{print $1}')" | grep '^kexalgorithms' | tr ',' '\n' | egrep -c "diffie-hellman-group1-sha1|diffie-hellman-group14-sha1|diffie-hellman-group-exchange-sha1") if [[ "$val" -eq "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_16() { # args head=h1 rule="4.5.3.16" desc="sshd_config, ssh_config: Ciphers" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') cat > $tempo << EOF aes128-ctr,aes192-ctr,aes256-ctr,chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com EOF cat $tempo | tr ',' '\n' | sort -u > $tempo.1 sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | grep -v '^#' | awk '{print $1}')" | grep ciphers | cut -d' ' -f2- | tr ',' '\n' | sort -u > $tempo val=$(sdiff -sw 80 $tempo $tempo.1 | wc -l | awk '{print $1}') if [[ "$val" -eq "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_17() { # args head=h1 rule="4.5.3.17" desc="sshd_config, ssh_config: MACs - Message Authtification Codes" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') # List of Weak algorithms cat > $tempo << EOF hmac-md5,hmac-md5-96,hmac-ripemd160,hmac-sha1,hmac-sha1-96,umac-64@openssh.com,umac-128@openssh.com,hmac-md5-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com EOF cat $tempo | tr ',' '\n' | sort -u > $tempo.1 sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | grep -v '^#' | awk '{print $1}')" | grep macs | cut -d' ' -f2- | tr ',' ' \n' | sort -u | sed 's/$/;/g' > $tempo val=0 for mac in $(cat $tempo.1) do val1=$(grep -c "^${mac};" $tempo) (( val = val + val1 )) done if [[ "$val" -eq "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_5_3_18() { # args head=h1 rule="4.5.3.18" desc="sshd_config, ssh_config: ReKeyLimit" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(sshd -T -C user=root -C host="$(hostname)" -C addr="$(grep $(hostname) /etc/hosts | grep -v '^#' | awk '{print $1}')" | grep rekeylimit | cut -d' ' -f2- | tr -s ' ' | tr ' ' '\n' | sort -u | tail -1) if [[ "$val" != "0" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res } #----------------------------------------- check_section_4_6_5() { # args head=h1 rule="4.6.5" desc="Unattended terminal session timeout is 900 seconds (or less)" res="" desc1=$(echo $desc | tr -s ' ' | sed 's/\ /|/g') val=$(echo `egrep -c "TMOUT|TIMEOUT" /etc/profile` `readonly | /usr/bin/egrep -c -e "TMOUT|TIMEOUT"` | tr ' ' '\n' | sed '/^$/d' | sort | tail -1) if [[ "$val" -gt "2" ]] then res=OK else res=NOK fi print_output $head $rule $desc1 $res }