New upstream version 1.6+git20170904.00e0d54

This commit is contained in:
Arnaud Rebillout
2026-09-07 21:32:45 +07:00
parent f386a7dc27
commit af74cbb8d3
2 changed files with 531 additions and 90 deletions
+74 -8
View File
@@ -1,13 +1,79 @@
2010-12-30 unix-privesc-check trunk
* Bug fix: Cleaned up a typo
* Added support for fscaps
* Updated CHANGELOG
-- Tim Brown <timb@nth-dimension.org.uk>
2010-11-09 unix-privesc-check trunk
* Bug fix: False positive if svn.simple directory is empty
-- <pentestmonkey@pentestmonkey.net>
2010-11-04 unix-privesc-check trunk
* Added unique issue numbers. Should help to generate reports
-- <pentestmonkey@pentestmonkey.net>
2010-04-17 unix-privesc-check trunk
* Bug fix: Now checks HP-UX swap permissions correctly
* Bug fix: Cleaned up a few typos
-- Tim Brown <timb@nth-dimension.org.uk>
2010-09-27 unix-privesc-check trunk
* Added check for cleartext subversion passwords in home directory
-- <pentestmonkey@pentestmonkey.net>
2010-01-06 unix-privesc-check trunk
* Added support for exploit mitigations (HP-UX and Solaris)
* Checks if shadow and passwd are writable, thanks jdv
* Checks for SetUID shell scripts which might be racey
* Improved NX and SSP checks (Linux only)
* Bug fix: Cleaned up a few typos
-- Tim Brown <timb@nth-dimension.org.uk>
2009-09-23 unix-privesc-check trunk
* Bug fix: Cron jobs starting with '(' parsed properly
* Checks perms on Java classpath
-- <pentestmonkey@pentestmonkey.net>
2009-09-06 unix-privesc-check trunk
* Added MMAP allows map to 0 exploit mitigation (Linux ATM)
* Added SELinux exploit mitigation (Linux only)
-- Tim Brown <timb@nth-dimension.org.uk>
2009-07-30 unix-privesc-check v1.5
* Initial AIX support added
* Check for exploit mitigations (Linux only ATM)
* Brain dumped some more interesting things to check for into TODOs
* Bug fix: Fixed typos in comments
* Added SSP exploit mitigation (Linux only ATM)
-- Tim Brown <timb@nth-dimension.org.uk>
2008-11-23 unix-privesc-check v1.4 2008-11-23 unix-privesc-check v1.4
* Added check of file perms of shared libraries used by SUID programs. * Added check of file perms of shared libraries used by SUID programs
* Tidied output slightly. * Tidied output slightly
2008-11-09 unix-privesc-check v1.3 2008-11-09 unix-privesc-check v1.3
* Bug fix: Parts of the script only worked with /bin/bash and not /bin/sh * Bug fix: Parts of the script only worked with /bin/bash and not /bin/sh
* Bug fix: Fixed typos in reporting for privescs via cron. * Bug fix: Fixed typos in reporting for privescs via cron
2008-07-06 unix-privesc-check v1.2 2008-07-06 unix-privesc-check v1.2
@@ -19,9 +85,9 @@
should now be on one line so you can grep for 'WARNING' and still should now be on one line so you can grep for 'WARNING' and still
understand the results understand the results
* Check of file perms on open file handles of running processes * Check of file perms on open file handles of running processes
* Check for running SSH agent. Lists keys if possible. * Check for running SSH agent. Lists keys if possible
* Check for public and private SSH keys in home directories. * Check for public and private SSH keys in home directories
* Check for running GPG agent. * Check for running GPG agent
* Check for cron jobs in /var/spool/cron/tabs * Check for cron jobs in /var/spool/cron/tabs
* Extra non-priv check for local postgres trusts * Extra non-priv check for local postgres trusts
* Bug fix: lanscan now used on HPUX to get interface names * Bug fix: lanscan now used on HPUX to get interface names
@@ -30,8 +96,8 @@
2008-04-17 unix-privesc-check v1.1 2008-04-17 unix-privesc-check v1.1
* Added check for accounts with no password in /etc/passwd * Added check for accounts with no password in /etc/passwd
* Record some basic info about the host (hostname, uname -a, interface IPs) * Record some basic info about the host (hostname, uname -a, interface IPs)
2008-02-01 unix-privesc-check v1.0 2008-02-01 unix-privesc-check v1.0
+456 -81
View File
@@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
# unix-privesc-check - Checks Unix system for simple privilege escalations # unix-privesc-check - Checks Unix system for simple privilege escalations
# Copyright (C) 2008 pentestmonkey@pentestmonkey.net # Copyright (C) 2008 pentestmonkey@pentestmonkey.net
# Copyright (C) 2009 timb@nth-dimension.org.uk
# #
# #
# License # License
@@ -34,9 +35,9 @@
# Auditing tool to check for weak file permissions and other problems that # Auditing tool to check for weak file permissions and other problems that
# may allow local attackers to escalate privileges. # may allow local attackers to escalate privileges.
# #
# It is intended to be run by security auditors and pentetration testers # It is intended to be run by security auditors and penetration testers
# against systems they have been engaged to assess, and also by system # against systems they have been engaged to assess, and also by system
# admnisitrators who want to check for "obvious" misconfigurations. It # administrators who want to check for "obvious" misconfigurations. It
# can even be run as a cron job so you can check regularly for misconfigurations # can even be run as a cron job so you can check regularly for misconfigurations
# that might be introduced. # that might be introduced.
# #
@@ -52,13 +53,17 @@
# - Check /proc/pid/cmdline for absolute path names. Check security of these (e.g. /etc/snmp/snmpd.conf) # - Check /proc/pid/cmdline for absolute path names. Check security of these (e.g. /etc/snmp/snmpd.conf)
# - Check everything in root's path - how to find root's path? # - Check everything in root's path - how to find root's path?
# - /proc/pid/maps, smaps are readable and lists some shared objects. We should check these. # - /proc/pid/maps, smaps are readable and lists some shared objects. We should check these.
# - We should also check whether libraries are in writable address space
# - AIX/Solaris executable stack
# - Is firewall DMA enabled?
# - Loadable kernel modules?
# - /proc/pid/fd contain symlinks to all open files (but you can't see other people FDs) # - /proc/pid/fd contain symlinks to all open files (but you can't see other people FDs)
# - check for trust relationships in /etc/hosts.equiv # - check for trust relationships in /etc/hosts.equiv
# - NFS imports / exports / automounter # - NFS imports / exports / automounter
# - Insecure stuff in /etc/fstab (e.g. allowing users to mount file systems) # - Insecure stuff in /etc/fstab (e.g. allowing users to mount file systems)
# - Inspecting people's PATH. tricky. maybe read from /proc/pid/environ, .bashrc, /etc/profile, .bash_profile # - Inspecting people's PATH. tricky. maybe read from /proc/pid/environ, .bashrc, /etc/profile, .bash_profile
# - Check if /etc/init.d/* scripts are readable. Advise user to audit them if they are. # - Check if /etc/init.d/* scripts are readable. Advise user to audit them if they are.
# - .exrc? # - .exrc? (partial support added)
# - X11 trusts, apache passwd files, mysql trusts? # - X11 trusts, apache passwd files, mysql trusts?
# - Daemons configured in an insecure way: tftpd, sadmind, rexd # - Daemons configured in an insecure way: tftpd, sadmind, rexd
# - World writable dirs aren't as bad if the sticky bit is set. Check for this before reporting vulns. # - World writable dirs aren't as bad if the sticky bit is set. Check for this before reporting vulns.
@@ -66,6 +71,7 @@
# - Do a better job of parsing cron lines - search for full paths # - Do a better job of parsing cron lines - search for full paths
# - Maybe LDPATHs from /etc/env.d # - Maybe LDPATHs from /etc/env.d
# - Check if ldd, ld.so.conf changes have broken this script on non-linux systems. # - Check if ldd, ld.so.conf changes have broken this script on non-linux systems.
# - ld.so.conf has an equivelent at least on Solaris
# - Avoid check certain paths e.g. /-/_ clearly isn't a real directory. # - Avoid check certain paths e.g. /-/_ clearly isn't a real directory.
# - create some sort of readable report # - create some sort of readable report
# - indicate when it's likely a result is a false positive and when it's not. # - indicate when it's likely a result is a false positive and when it's not.
@@ -77,10 +83,19 @@
# - We check some files / dirs multiple times. Slow. Can we implement a cache? # - We check some files / dirs multiple times. Slow. Can we implement a cache?
# - grep for PRIVATE KEY to find private ssh and ssl keys. Where to grep? # - grep for PRIVATE KEY to find private ssh and ssl keys. Where to grep?
# - check SGID programs # - check SGID programs
# - Get rid of the awk, command-to-parse-output-from | while read parta partb partc is much better
# - HPUX TCB?
# - caps on processes
VERSION="1.4" VERSION="1.6"
HOME_DIR_FILES=".netrc .ssh/id_rsa .ssh/id_dsa .rhosts .shosts .my.cnf .ssh/authorized_keys .bash_history .sh_history .forward" SVNVERSION="$Revision$" # Don't change this line. Auto-updated.
CONFIG_FILES="/etc/passwd /etc/group /etc/master.passwd /etc/inittab /etc/inetd.conf /etc/xinetd.con /etc/xinetd.d/* /etc/contab /etc/fstab /etc/profile /etc/sudoers" SVNVNUM=`echo $SVNVERSION | sed 's/[^0-9]//g'`
if [ -n $SVNVNUM ]; then
VERSION="$VERSION-svn-$SVNVNUM"
fi
HOME_DIR_FILES=".exrc .netrc .ssh/id_rsa .ssh/id_dsa .rhosts .shosts .my.cnf .ssh/authorized_keys .bash_history .sh_history .forward"
CONFIG_FILES="/etc/passwd /etc/group /etc/master.passwd /etc/inittab /etc/inetd.conf /etc/xinetd.conf /etc/xinetd.d/* /etc/crontab /etc/fstab /etc/profile /etc/sudoers /etc/hosts.equiv /etc/shosts.equiv"
PGDIRS="/usr/local/pgsql/data ~postgres/postgresql/data ~postgres/data ~pgsql/data ~pgsql/pgsql/data /var/lib/postgresql/data /etc/postgresql/8.2/main /var/lib/pgsql/data" PGDIRS="/usr/local/pgsql/data ~postgres/postgresql/data ~postgres/data ~pgsql/data ~pgsql/pgsql/data /var/lib/postgresql/data /etc/postgresql/8.2/main /var/lib/pgsql/data"
get_owner () { get_owner () {
@@ -159,7 +174,11 @@ check_called_programs () {
# Check if file is text or not # Check if file is text or not
IS_TEXT=`file "$CCP_FILE" | grep -i text` IS_TEXT=`file "$CCP_FILE" | grep -i text`
IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'` if [ $OS = "aix" ]; then
IS_DYNBIN=`file "$CCP_FILE" | grep -i 'object module'`
else
IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'`
fi
# Process shell scripts (would also work on config files that reference other files) # Process shell scripts (would also work on config files that reference other files)
if [ ! -z "$IS_TEXT" ]; then if [ ! -z "$IS_TEXT" ]; then
@@ -173,7 +192,7 @@ check_called_programs () {
# Process dynamically linked binaries # Process dynamically linked binaries
if [ ! -z "$IS_DYNBIN" ]; then if [ ! -z "$IS_DYNBIN" ]; then
CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' ' | cut -f 1 -d '('`
for CALLED_FILE in $CALLED_FILES; do for CALLED_FILE in $CALLED_FILES; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
done done
@@ -187,6 +206,24 @@ check_called_programs () {
fi fi
} }
# Parse any full paths from $1 (config files, progs, dirs).
# Check the permissions on each of these.
check_called_programs_suid_sgid () {
CCP_FILE=$1
is_suid $CCP_FILE # sets $IS_SUID_RETURN
if [ "$IS_SUID_RETURN" -eq 1 ]; then
check_called_programs_suid $CCP_FILE
fi
is_sgid $CCP_FILE # sets $IS_SGID_RETURN
if [ "$IS_SGID_RETURN" -eq 1 ]; then
check_called_programs_sgid $CCP_FILE
fi
}
# Parse any full paths from $1 (config files, progs, dirs). # Parse any full paths from $1 (config files, progs, dirs).
# Check the permissions on each of these. # Check the permissions on each of these.
check_called_programs_suid () { check_called_programs_suid () {
@@ -216,7 +253,7 @@ check_called_programs_suid () {
CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u` CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`
for CALLED_FILE in $CALLED_FILES; do for CALLED_FILE in $CALLED_FILES; do
# echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms." # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms."
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done done
else else
# Process dynamically linked binaries # Process dynamically linked binaries
@@ -224,7 +261,7 @@ check_called_programs_suid () {
CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '`
for CALLED_FILE in $CALLED_FILES; do for CALLED_FILE in $CALLED_FILES; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done done
# Skip the slow check if we're in quick mode # Skip the slow check if we're in quick mode
@@ -235,20 +272,127 @@ check_called_programs_suid () {
# Strings binary to look for hard-coded config files # Strings binary to look for hard-coded config files
# or other programs that might be called. # or other programs that might be called.
for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done done
fi fi
fi fi
} }
# Check if $1 can be changed by users who are not $2 # Parse any full paths from $1 (config files, progs, dirs).
# Check the permissions on each of these.
check_called_programs_sgid () {
CCP_FILE=$1
CCP_PATH=$2 # optional
get_group $CCP_FILE; CCP_GROUP=$GET_GROUP_RETURN
CCP_MESSAGE_STACK="$CCP_FILE is SGID $CCP_GROUP."
LS=`ls -l $CCP_FILE`
echo "Checking SGID-$CCP_GROUP program $CCP_FILE: $LS"
# Don't check perms of executable itself
# check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH"
# Check if file is text or not
IS_TEXT=`file "$CCP_FILE" | grep -i text`
IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'`
# Process shell scripts (would also work on config files that reference other files)
if [ ! -z "$IS_TEXT" ]; then
# Skip the slow check if we're in quick mode
if [ "$MODE" = "standard" ]; then
return 0;
fi
# Parse full paths from file - ignoring commented lines
CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`
for CALLED_FILE in $CALLED_FILES; do
# echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms."
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done
else
# Process dynamically linked binaries
if [ ! -z "$IS_DYNBIN" ]; then
CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '`
for CALLED_FILE in $CALLED_FILES; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done
# Skip the slow check if we're in quick mode
if [ "$MODE" = "standard" ]; then
return 0;
fi
# Strings binary to look for hard-coded config files
# or other programs that might be called.
for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" root "$CCP_PATH"
done
fi
fi
}
# Parse any full paths from $1 (config files, progs, dirs).
# Check the permissions on each of these.
check_called_programs_fscaps () {
CCP_FILE=$1
CCP_PATH=$2 # optional
CCP_MESSAGE_STACK="$CCP_FILE has fscaps."
LS=`ls -l $CCP_FILE`
echo "Checking fscaps program $CCP_FILE: $LS"
# Don't check perms of executable itself
# check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_PATH"
# Check if file is text or not
IS_TEXT=`file "$CCP_FILE" | grep -i text`
IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'`
# Process shell scripts (would also work on config files that reference other files)
if [ ! -z "$IS_TEXT" ]; then
# Skip the slow check if we're in quick mode
if [ "$MODE" = "standard" ]; then
return 0;
fi
# Parse full paths from file - ignoring commented lines
CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`
for CALLED_FILE in $CALLED_FILES; do
# echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms."
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "root" "$CCP_PATH"
done
else
# Process dynamically linked binaries
if [ ! -z "$IS_DYNBIN" ]; then
CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '`
for CALLED_FILE in $CALLED_FILES; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "root" "$CCP_PATH"
done
# Skip the slow check if we're in quick mode
if [ "$MODE" = "standard" ]; then
return 0;
fi
# Strings binary to look for hard-coded config files
# or other programs that might be called.
for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do
check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "root" "$CCP_PATH"
done
fi
fi
}
# Check if $2 can be changed by users who are not $3
check_perms () { check_perms () {
CP_MESSAGE_STACK=$1 CP_MESSAGE_STACK=$1
CHECK_PERMS_FILE=$2 CHECK_PERMS_FILE=$2
CHECK_PERMS_USER=$3 CHECK_PERMS_USER=$3
CHECK_PERMS_PATH=$4 # optional CHECK_PERMS_PATH=$4 # optional
if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -d "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -d "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ] && [ ! -c "$CHECK_PERMS_FILE" ]; then
CHECK_PERMS_FOUND=0 CHECK_PERMS_FOUND=0
if [ ! -z "$CHECK_PERMS_PATH" ]; then if [ ! -z "$CHECK_PERMS_PATH" ]; then
# Look for it in the supplied path # Look for it in the supplied path
@@ -287,7 +431,7 @@ check_read_perms () {
CHECK_PERMS_FILE=$2 CHECK_PERMS_FILE=$2
CHECK_PERMS_USER=$3 CHECK_PERMS_USER=$3
if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ] && [ ! -c "$CHECK_PERMS_FILE" ]; then
echo "ERROR: File $CHECK_PERMS_FILE doesn't exist" echo "ERROR: File $CHECK_PERMS_FILE doesn't exist"
return 0 return 0
fi fi
@@ -302,7 +446,7 @@ perms_secure_read () {
PERMS_SECURE_FILE=$2 PERMS_SECURE_FILE=$2
PERMS_SECURE_USER=$3 PERMS_SECURE_USER=$3
if [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -d "$PERMS_SECURE_FILE" ]; then if [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -c "$PERMS_SECURE_FILE" ]; then
echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping."
return 0 return 0
fi fi
@@ -322,7 +466,7 @@ perms_secure () {
PERMS_SECURE_FILE=$2 PERMS_SECURE_FILE=$2
PERMS_SECURE_USER=$3 PERMS_SECURE_USER=$3
if [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -b "$PERMS_SECURE_FILE" ]; then if [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -c "$PERMS_SECURE_FILE" ]; then
# echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." # echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping."
return 0 return 0
fi fi
@@ -346,7 +490,7 @@ only_user_can_write () {
# can always grant themselves write access # can always grant themselves write access
get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN
if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then
echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can write to $O_FILE" echo "[UPC001] WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can write to $O_FILE"
fi fi
} }
@@ -361,11 +505,33 @@ group_can_write () {
# check the group actually has some members other than $O_USER # check the group actually has some members other than $O_USER
group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0
if [ "$OTHER_MEMBERS" = "1" ]; then if [ "$OTHER_MEMBERS" = "1" ]; then
echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can write to $O_FILE" echo "[UPC002] WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can write to $O_FILE"
fi fi
fi fi
} }
is_suid () {
O_FILE=$1
P=`ls -lLd $O_FILE | cut -c 4`
if [ "$P" = "s" ]; then
IS_SUID_RETURN=1
else
IS_SUID_RETURN=0
fi
}
is_sgid () {
O_FILE=$1
P=`ls -lLd $O_FILE | cut -c 7`
if [ "$P" = "s" ]; then
IS_SGID_RETURN=1
else
IS_SGID_RETURN=0
fi
}
group_has_other_members () { group_has_other_members () {
G_GROUP=$1 G_GROUP=$1
G_USER=$2 G_USER=$2
@@ -410,9 +576,9 @@ world_can_write () {
if [ "$P" = "w" ]; then if [ "$P" = "w" ]; then
if [ "$S" = "t" ]; then if [ "$S" = "t" ]; then
echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE (but sticky bit set)" echo "[UPC003] WARNING: $O_MESSAGE_STACK World write is set for $O_FILE (but sticky bit set)"
else else
echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE" echo "[UPC004] WARNING: $O_MESSAGE_STACK World write is set for $O_FILE"
fi fi
fi fi
} }
@@ -426,7 +592,7 @@ only_user_can_read () {
# can always grant themselves read access # can always grant themselves read access
get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN
if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then
echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can read $O_FILE" echo "[UPC005] WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can read $O_FILE"
fi fi
} }
@@ -441,7 +607,7 @@ group_can_read () {
# check the group actually has some members other than $O_USER # check the group actually has some members other than $O_USER
group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0
if [ "$OTHER_MEMBERS" = "1" ]; then if [ "$OTHER_MEMBERS" = "1" ]; then
echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can read $O_FILE" echo "[UPC006] WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can read $O_FILE"
fi fi
fi fi
} }
@@ -453,7 +619,7 @@ world_can_read () {
P=`ls -lLd $O_FILE | cut -c 8` P=`ls -lLd $O_FILE | cut -c 8`
if [ "$P" = "w" ]; then if [ "$P" = "w" ]; then
echo "WARNING: $O_MESSAGE_STACK World read is set for $O_FILE" echo "[UPC007] WARNING: $O_MESSAGE_STACK World read is set for $O_FILE"
fi fi
} }
@@ -474,6 +640,9 @@ elif [ -x /usr/sbin/sam -o -x /usr/bin/sam ]; then
elif [ -f /etc/master.passwd ]; then elif [ -f /etc/master.passwd ]; then
OS="bsd" OS="bsd"
SHADOW="/etc/master.passwd" SHADOW="/etc/master.passwd"
elif [ -f /etc/security/user ]; then
OS="aix"
SHADOW="/etc/security/passwd"
else else
OS="linux" OS="linux"
SHADOW="/etc/shadow" SHADOW="/etc/shadow"
@@ -504,7 +673,7 @@ section "Recording uname"
uname -a uname -a
section "Recording Interface IP addresses" section "Recording Interface IP addresses"
if [ $OS = 'hpux' ]; then if [ "$OS" = "hpux" ]; then
for IFACE in `lanscan | grep x | awk '{print $5}' 2>/dev/null`; do for IFACE in `lanscan | grep x | awk '{print $5}' 2>/dev/null`; do
ifconfig $IFACE 2>/dev/null ifconfig $IFACE 2>/dev/null
done done
@@ -515,31 +684,58 @@ fi
section "Checking if external authentication is allowed in /etc/passwd" section "Checking if external authentication is allowed in /etc/passwd"
FLAG=`grep '^+:' /etc/passwd` FLAG=`grep '^+:' /etc/passwd`
if [ -n "$FLAG" ]; then if [ -n "$FLAG" ]; then
echo "WARNING: /etc/passwd allows external authentcation:" echo "[UPC008] WARNING: /etc/passwd allows external authentcation:"
grep '^+:' /etc/passwd grep '^+' /etc/passwd
EXT_AUTH=1 EXT_AUTH=1
else else
echo "No +:... line found in /etc/passwd" echo "No +:... line found in /etc/passwd"
fi fi
section "Checking nsswitch.conf for addition authentication methods" section "Checking nsswitch.conf/netsvc.conf for addition authentication methods"
if [ -r "/etc/nsswitch.conf" ]; then if [ "$OS" = "aix" ]; then
NIS=`grep '^passwd' /etc/nsswitch.conf | grep 'nis'` if [ -r "/etc/netsvc.conf" ]; then
if [ -n "$NIS" ]; then # ldap_nis Uses LDAP NIS services for resolving names
echo "WARNING: NIS is used for authentication on this system" # nis4 Uses NIS services for resolving only IPv4 addresses
EXT_AUTH=1 # nis6 Uses NIS services for resolving only IPv6 addresses
fi # nis+4 Uses NIS plus services for resolving only IPv4 addresses
LDAP=`grep '^passwd' /etc/nsswitch.conf | grep 'ldap'` # nis+6 Uses NIS plus services for resolving only IPv6 addresses
if [ -n "$LDAP" ]; then # ldap4 Uses LDAP services for resolving only IPv4 addresses
echo "WARNING: LDAP is used for authentication on this system" # ldap6 Uses LDAP services for resolving only IPv6 addresses
EXT_AUTH=1 # ldap_nis4 Uses NIS LDAP services for resolving only IPv4 addresses
fi # ldap_nis6 Uses NIS LDAP services for resolving only IPv6 addresses
# ldap Uses LDAP services for resolving names
if [ -z "$NIS" ] && [ -z "$LDAP" ]; then NIS=`grep '^host' /etc/netsvc.conf | grep 'nis'`
echo "Neither LDAP nor NIS are used for authentication" if [ -n "$NIS" ]; then
echo "[UPC009] WARNING: NIS is used for authentication on this system"
EXT_AUTH=1
fi
LDAP=`grep '^host' /etc/netsvc.conf | grep 'ldap'`
if [ -n "$LDAP" ]; then
echo "[UPC010] WARNING: LDAP is used for authentication on this system"
EXT_AUTH=1
fi
else
echo "ERROR: File /etc/netsvc.conf isn't readable. Skipping checks."
fi fi
else else
echo "ERROR: File /etc/nsswitch.conf isn't readable. Skipping checks." if [ -r "/etc/nsswitch.conf" ]; then
NIS=`grep '^passwd' /etc/nsswitch.conf | grep 'nis'`
if [ -n "$NIS" ]; then
echo "[UPC011] WARNING: NIS is used for authentication on this system"
EXT_AUTH=1
fi
LDAP=`grep '^passwd' /etc/nsswitch.conf | grep 'ldap'`
if [ -n "$LDAP" ]; then
echo "[UPC012] WARNING: LDAP is used for authentication on this system"
EXT_AUTH=1
fi
if [ -z "$NIS" ] && [ -z "$LDAP" ]; then
echo "Neither LDAP nor NIS are used for authentication"
fi
else
echo "ERROR: File /etc/nsswitch.conf isn't readable. Skipping checks."
fi
fi fi
# Check important config files aren't writable # Check important config files aren't writable
@@ -551,13 +747,19 @@ for FILE in $CONFIG_FILES; do
done done
section "Checking if $SHADOW is readable" section "Checking if $SHADOW is readable"
check_read_perms "/etc/shadow holds authentication data" $SHADOW root check_read_perms "$SHADOW holds authentication data" $SHADOW root
section "Checking if $SHADOW is writable"
check_perms "$SHADOW can be written to" $SHADOW root
section "Checking if /etc/passwd is writable"
check_perms "/etc/passwd can be written to" /etc/passwd root
section "Checking for password hashes in /etc/passwd" section "Checking for password hashes in /etc/passwd"
FLAG=`grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#'` FLAG=`grep -v '^[^:]*:[!x\*]*:' /etc/passwd | grep -v '^#'`
if [ -n "$FLAG" ]; then if [ -n "$FLAG" ]; then
echo "WARNING: There seem to be some password hashes in /etc/passwd" echo "[UPC013] WARNING: There seem to be some password hashes in /etc/passwd"
grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#' grep -v '^[^:]*:[!x\*]*:' /etc/passwd | grep -v '^#'
EXT_AUTH=1 EXT_AUTH=1
else else
echo "No password hashes found in /etc/passwd" echo "No password hashes found in /etc/passwd"
@@ -569,7 +771,7 @@ section "Checking account settings"
if [ -r "/etc/passwd" ]; then if [ -r "/etc/passwd" ]; then
OPEN=`grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"` OPEN=`grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"`
if [ -n "$OPEN" ]; then if [ -n "$OPEN" ]; then
echo "WARNING: The following accounts have no password:" echo "[UPC014] WARNING: The following accounts have no password:"
grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":" grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"
fi fi
fi fi
@@ -581,7 +783,7 @@ if [ -r "$SHADOW" ]; then
USER=`echo "$LINE" | awk '{print $1}'` USER=`echo "$LINE" | awk '{print $1}'`
STATUS=`echo "$LINE" | awk '{print $2}'` STATUS=`echo "$LINE" | awk '{print $2}'`
if [ "$STATUS" = "NP" ]; then if [ "$STATUS" = "NP" ]; then
echo "WARNING: User $USER doesn't have a password" echo "[UPC015] WARNING: User $USER doesn't have a password"
fi fi
done done
elif [ "$OS" = "solaris" ]; then elif [ "$OS" = "solaris" ]; then
@@ -590,7 +792,7 @@ if [ -r "$SHADOW" ]; then
USER=`echo "$LINE" | awk '{print $1}'` USER=`echo "$LINE" | awk '{print $1}'`
STATUS=`echo "$LINE" | awk '{print $2}'` STATUS=`echo "$LINE" | awk '{print $2}'`
if [ "$STATUS" = "NP" ]; then if [ "$STATUS" = "NP" ]; then
echo "WARNING: User $USER doesn't have a password" echo "[UPC016] WARNING: User $USER doesn't have a password"
fi fi
done done
fi fi
@@ -620,7 +822,7 @@ if [ -f "/etc/sudoers" ] && [ -r "/etc/sudoers" ]; then
echo "Checking if sudo is configured" echo "Checking if sudo is configured"
SUDO_USERS=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep -v '^[ \t]*Default' | grep =` SUDO_USERS=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep -v '^[ \t]*Default' | grep =`
if [ ! -z "$SUDO_USERS" ]; then if [ ! -z "$SUDO_USERS" ]; then
echo "WARNING: Sudo is configured. Manually check nothing unsafe is allowed:" echo "[UPC017] WARNING: Sudo is configured. Manually check nothing unsafe is allowed:"
grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep = | grep -v '^[ \t]*Default' grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep = | grep -v '^[ \t]*Default'
fi fi
@@ -628,7 +830,7 @@ if [ -f "/etc/sudoers" ] && [ -r "/etc/sudoers" ]; then
echo "Checking sudo users need a password" echo "Checking sudo users need a password"
SUDO_NOPASSWD=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD` SUDO_NOPASSWD=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD`
if [ ! -z "$SUDO_NOPASSWD" ]; then if [ ! -z "$SUDO_NOPASSWD" ]; then
echo "WARNING: Some users can use sudo without a password:" echo "[UPC018] WARNING: Some users can use sudo without a password:"
grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD
fi fi
else else
@@ -636,10 +838,19 @@ else
fi fi
section "Checking permissions on swap file(s)" section "Checking permissions on swap file(s)"
for SWAP in `swapon -s | grep -v '^Filename' | cut -f 1 -d ' '`; do if [ "$OS" = "hpux" ]; then
check_perms "$SWAP is used for swap space." $SWAP root for SWAP in `swapinfo| grep -v '^dev' | awk '{print $9}'`; do
check_read_perms "$SWAP is used for swap space." $SWAP root check_perms "$SWAP is used for swap space." $SWAP root
done check_read_perms "$SWAP is used for swap space." $SWAP root
done
else
if [ "$OS" != "aix" ]; then
for SWAP in `swapon -s | grep -v '^Filename' | cut -f 1 -d ' '`; do
check_perms "$SWAP is used for swap space." $SWAP root
check_read_perms "$SWAP is used for swap space." $SWAP root
done
fi
fi
section "Checking programs run from inittab" section "Checking programs run from inittab"
if [ -f "/etc/inittab" ] && [ -r "/etc/inittab" ]; then if [ -f "/etc/inittab" ] && [ -r "/etc/inittab" ]; then
@@ -658,24 +869,24 @@ for DIR in $PGDIRS; do
AUTH=`echo "$LINE" | awk '{print $NF}'` AUTH=`echo "$LINE" | awk '{print $NF}'`
if [ "$AUTH" = "trust" ]; then if [ "$AUTH" = "trust" ]; then
PGTRUST=1 PGTRUST=1
echo "WARNING: Postgres trust configured in $DIR/pg_hba.conf: $LINE" echo "[UPC019] WARNING: Postgres trust configured in $DIR/pg_hba.conf: $LINE"
fi fi
done done
fi fi
done done
PGVER1=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` PGVER1=`psql -w -U postgres template1 -c 'select version()' 2>/dev/null | grep version`
if [ -n "$PGVER1" ]; then if [ -n "$PGVER1" ]; then
PGTRUST=1 PGTRUST=1
echo "WARNING: Can connect to local postgres database as \"postgres\" without a password" echo "[UPC020] WARNING: Can connect to local postgres database as \"postgres\" without a password"
fi fi
PGVER2=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` PGVER2=`psql -w -U pgsql template1 -c 'select version()' 2>/dev/null | grep version`
if [ -n "$PGVER2" ]; then if [ -n "$PGVER2" ]; then
PGTRUST=1 PGTRUST=1
echo "WARNING: Can connect to local postgres database as \"pgsql\" without a password" echo "[UPC021] WARNING: Can connect to local postgres database as \"pgsql\" without a password"
fi fi
if [ -z "$PGTRUST" ]; then if [ -z "$PGTRUST" ]; then
@@ -711,6 +922,12 @@ elif [ "$OS" = "solaris" ]; then
check_perms "$DEVICE is a mounted file system." $DEVICE root check_perms "$DEVICE is a mounted file system." $DEVICE root
fi fi
done done
NFS=`mount -v | grep -i ' nfs '`
if [ -n "$NFS" ]; then
echo "[UPC022] WARNING: This system is an NFS client. Check for nosuid and nodev options."
mount -v | grep -i NFS
fi
elif [ "$OS" = "hpux" ]; then elif [ "$OS" = "hpux" ]; then
mount | while read LINE mount | while read LINE
do do
@@ -724,9 +941,15 @@ elif [ "$OS" = "hpux" ]; then
NFS=`mount | grep NFS` NFS=`mount | grep NFS`
if [ -n "$NFS" ]; then if [ -n "$NFS" ]; then
echo "WARNING: This system is an NFS client. Check for nosuid and nodev options." echo "[UPC022] WARNING: This system is an NFS client. Check for nosuid and nodev options."
mount | grep NFS mount | grep NFS
fi fi
elif [ "$OS" = "aix" ]; then
mount | grep jfs2 | while read DEVICE LINE
do
echo "Checking device $DEVICE"
check_perms "$DEVICE is a mounted file system." $DEVICE root
done
fi fi
# Check cron jobs if they're readable # Check cron jobs if they're readable
@@ -769,7 +992,7 @@ if [ -f "/etc/crontab" ] && [ -r "/etc/crontab" ]; then
do do
echo "Processing crontab entry: $LINE" echo "Processing crontab entry: $LINE"
USER=`echo "$LINE" | awk '{print $6}'` USER=`echo "$LINE" | awk '{print $6}'`
PROG=`echo "$LINE" | awk '{print $7}'` PROG=`echo "$LINE" | sed 's/(//' | awk '{print $7}'`
check_called_programs "$PROG is run from crontab as $USER." $PROG $USER $MYPATH check_called_programs "$PROG is run from crontab as $USER." $PROG $USER $MYPATH
done done
else else
@@ -812,7 +1035,7 @@ if [ -d "/var/spool/cron/crontabs" ]; then
grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE
do do
echo "Processing crontab entry: $LINE" echo "Processing crontab entry: $LINE"
PROG=`echo "$LINE" | awk '{print $6}'` PROG=`echo "$LINE" | sed 's/(//' | awk '{print $6}'`
check_called_programs "$PROG is run via cron as $USER." "$PROG" $USER check_called_programs "$PROG is run via cron as $USER." "$PROG" $USER
done done
else else
@@ -840,7 +1063,7 @@ if [ -d "/var/spool/cron/tabs" ]; then
grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE
do do
echo "Processing crontab entry: $LINE" echo "Processing crontab entry: $LINE"
PROG=`echo "$LINE" | awk '{print $6}'` PROG=`echo "$LINE" | sed 's/(//' | awk '{print $6}'`
check_called_programs "$PROG is run from cron as $USER." $PROG $USER $MYPATH check_called_programs "$PROG is run from cron as $USER." $PROG $USER $MYPATH
done done
else else
@@ -923,17 +1146,47 @@ do
done done
done done
section "Checking SUID programs" section "Checking SUID/SGID programs"
if [ "$MODE" = "detailed" ]; then if [ "$MODE" = "detailed" ]; then
for FILE in `find / -type f -perm -04000 2>/dev/null`; do for FILE in `find / -type f -perm -04000 -o -type f -perm -02000 2>/dev/null`; do
check_called_programs_suid $FILE check_called_programs_suid_sgid $FILE
SUIDDCRIPT=`file $FILE | grep script`
if [ -n "$SUIDSCRIPT" ]; then
echo "[UPC023] WARNING: SetUID/SetGID shell script, may be vulnerable to race attacks"
fi
done done
else else
echo "Skipping checks of SUID programs (it's slow!). Run again in 'detailed' mode." echo "Skipping checks of SUID/SGID programs (it's slow!). Run again in 'detailed' mode."
fi fi
section "Checking fscaps programs"
if [ "$OS" = "linux" -a -x /sbin/getcap ]; then
if [ "$MODE" = "detailed" ]; then
for FILE in `find / -type f -perm +0011 -exec /sbin/getcap {} \; 2>/dev/null | grep "=" | awk '{print $1}'`; do
/sbin/getcap $FILE
check_called_programs_fscaps $FILE
FSCAPSSCRIPT=`file $FILE | grep script`
if [ -n "$FSCAPSSCRIPT" ]; then
echo "[UPC043] WARNING: fscaps shell script, may be vulnerable to race attacks"
fi
done
else
echo "Skipping checks of fscaps programs (it's slow!). Run again in 'detailed' mode."
fi
fi
# Check for cleartext subversion passwords
section "Checking for cleartext subversion passwords in home directories"
for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
if [ -d "$HOMEDIR/.subversion/auth/svn.simple" ]; then
for FILE in $HOMEDIR/.subversion/auth/svn.simple/*; do
echo "[UPC024] WARNING: Cleartext subversion passsword file: $FILE"
done
fi
done
# Check for private SSH keys in home directories # Check for private SSH keys in home directories
section "Checking for Private SSH Keys home directories" section "Checking for Private SSH Keys in home directories"
for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
if [ -d "$HOMEDIR/.ssh" ]; then if [ -d "$HOMEDIR/.ssh" ]; then
PRIV_KEYS=`grep -l 'BEGIN [RD]SA PRIVATE KEY' $HOMEDIR/.ssh/* 2>/dev/null` PRIV_KEYS=`grep -l 'BEGIN [RD]SA PRIVATE KEY' $HOMEDIR/.ssh/* 2>/dev/null`
@@ -941,9 +1194,9 @@ for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
for KEY in $PRIV_KEYS; do for KEY in $PRIV_KEYS; do
ENC_KEY=`grep -l 'ENCRYPTED' "$KEY" 2>/dev/null` ENC_KEY=`grep -l 'ENCRYPTED' "$KEY" 2>/dev/null`
if [ -n "$ENC_KEY" ]; then if [ -n "$ENC_KEY" ]; then
echo "WARNING: Encrypted Private SSH Key Found in $KEY" echo "[UPC025] WARNING: Encrypted private SSH key found in $KEY"
else else
echo "WARNING: Unencrypted Private SSH Key Found in $KEY" echo "[UPC026] WARNING: Unencrypted private SSH key found in $KEY"
fi fi
done done
fi fi
@@ -951,28 +1204,38 @@ for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
done done
# Check for public SSH keys in home directories # Check for public SSH keys in home directories
section "Checking for Public SSH Keys home directories" section "Checking for Public SSH Keys in home directories"
for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
if [ -r "$HOMEDIR/.ssh/authorized_keys" ]; then if [ -r "$HOMEDIR/.ssh/authorized_keys" ]; then
KEYS=`grep '^ssh-' $HOMEDIR/.ssh/authorized_keys 2>/dev/null` KEYS=`grep '^ssh-' $HOMEDIR/.ssh/authorized_keys 2>/dev/null`
if [ -n "$KEYS" ]; then if [ -n "$KEYS" ]; then
echo "WARNING: Public SSH Key Found in $HOMEDIR/.ssh/authorized_keys" echo "[UPC027] WARNING: Public SSH Key Found in $HOMEDIR/.ssh/authorized_keys"
fi fi
fi fi
done done
section "Checking classpath permissions for Java processes"
ps -ef | grep -i '\-classpath' | grep -v grep | while read LINE
do
U=`echo $LINE | awk '{print $1}'`
CLASSPATH=`echo $LINE | sed 's/.*classpath //' | sed 's/ .*//'`
for P in `echo $CLASSPATH | sed 's/:/ /g'`; do
check_perms "$P is in the classpath for a java process run by $U." "$P" $U
done
done
# Check for any SSH agents running on the box # Check for any SSH agents running on the box
section "Checking for SSH agents" section "Checking for SSH agents"
AGENTS=`ps -ef | grep ssh-agent | grep -v grep` AGENTS=`ps -ef | grep ssh-agent | grep -v grep`
if [ -n "$AGENTS" ]; then if [ -n "$AGENTS" ]; then
echo "WARNING: There are SSH agents running on this system:" echo "[UPC028] WARNING: There are SSH agents running on this system:"
ps -ef | grep ssh-agent | grep -v grep ps -ef | grep ssh-agent | grep -v grep
# for PID in `ps aux | grep ssh-agent | grep -v grep | awk '{print $2}'`; do # for PID in `ps aux | grep ssh-agent | grep -v grep | awk '{print $2}'`; do
for SOCK in `ls /tmp/ssh-*/agent.* 2>/dev/null`; do for SOCK in `ls /tmp/ssh-*/agent.* 2>/dev/null`; do
SSH_AUTH_SOCK=$SOCK; export SSH_AUTH_SOCK SSH_AUTH_SOCK=$SOCK; export SSH_AUTH_SOCK
AGENT_KEYS=`ssh-add -l | grep -v 'agent has no identities.' 2>/dev/null` AGENT_KEYS=`ssh-add -l | grep -v 'agent has no identities.' 2>/dev/null`
if [ -n "$AGENT_KEYS" ]; then if [ -n "$AGENT_KEYS" ]; then
echo "WARNING: SSH Agent has keys loaded [SSH_AUTH_SOCK=$SSH_AUTH_SOCK]" echo "[UPC029] WARNING: SSH Agent has keys loaded [SSH_AUTH_SOCK=$SSH_AUTH_SOCK]"
ssh-add -l ssh-add -l
fi fi
done done
@@ -984,7 +1247,7 @@ fi
section "Checking for GPG agents" section "Checking for GPG agents"
AGENTS=`ps -ef | grep gpg-agent | grep -v grep` AGENTS=`ps -ef | grep gpg-agent | grep -v grep`
if [ -n "$AGENTS" ]; then if [ -n "$AGENTS" ]; then
echo "WARNING: There are GPG agents running on this system:" echo "[UPC030] WARNING: There are GPG agents running on this system:"
ps aux | grep gpg-agent | grep -v grep ps aux | grep gpg-agent | grep -v grep
else else
echo "No GPG agents found" echo "No GPG agents found"
@@ -1007,7 +1270,7 @@ for DIR in /etc/init.d /etc/rc.d /usr/local/etc/rc.d; do
done done
section "Checking if running programs are writable" section "Checking if running programs are writable"
if [ $OS = "solaris" ]; then if [ "$OS" = "solaris" ]; then
# use the output of ps command # use the output of ps command
ps -ef -o user,comm | while read LINE ps -ef -o user,comm | while read LINE
do do
@@ -1015,7 +1278,15 @@ if [ $OS = "solaris" ]; then
PROG=`echo "$LINE" | awk '{print $2}'` PROG=`echo "$LINE" | awk '{print $2}'`
check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER"
done done
elif [ $OS = "bsd" ]; then elif [ "$OS" = "aix" ]; then
# use the output of ps command
ps -ef -o user,comm | while read LINE
do
USER=`echo "$LINE" | awk '{print $1}'`
PROG=`echo "$LINE" | awk '{print $2}'`
check_called_programs "`which $PROG` is currently running as $USER." "`which $PROG`" "$USER"
done
elif [ "$OS" = "bsd" ]; then
# use the output of ps command # use the output of ps command
ps aux | while read LINE ps aux | while read LINE
do do
@@ -1023,7 +1294,7 @@ elif [ $OS = "bsd" ]; then
PROG=`echo "$LINE" | awk '{print $11}'` PROG=`echo "$LINE" | awk '{print $11}'`
check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER"
done done
elif [ $OS = "hpux" ]; then elif [ "$OS" = "hpux" ]; then
# use the output of ps command # use the output of ps command
ps -ef | while read LINE ps -ef | while read LINE
do do
@@ -1037,7 +1308,7 @@ elif [ $OS = "hpux" ]; then
check_called_programs "$PROG is currently running as $USER." "$PROG2" "$USER" check_called_programs "$PROG is currently running as $USER." "$PROG2" "$USER"
fi fi
done done
elif [ $OS = "linux" ]; then elif [ "$OS" = "linux" ]; then
# use the /proc file system # use the /proc file system
for PROCDIR in /proc/[0-9]*; do for PROCDIR in /proc/[0-9]*; do
unset PROGPATH unset PROGPATH
@@ -1073,7 +1344,7 @@ elif [ $OS = "linux" ]; then
check_called_programs "$PROGPATH is currently running as $OWNER." $PROGPATH $OWNER check_called_programs "$PROGPATH is currently running as $OWNER." $PROGPATH $OWNER
fi fi
if [ "$MODE" == "detailed" ]; then if [ "$MODE" = "detailed" ]; then
for FILE in $PROCDIR/fd/*; do for FILE in $PROCDIR/fd/*; do
F=`echo "$FILE" | sed 's/^.*\///'` F=`echo "$FILE" | sed 's/^.*\///'`
if [ "$F" = "*" ]; then if [ "$F" = "*" ]; then
@@ -1084,3 +1355,107 @@ elif [ $OS = "linux" ]; then
fi fi
done done
fi fi
section "Checking exploit mitigation"
if [ "$MODE" = "detailed" ]; then
if [ "$OS" = "solaris" ]; then
NX=`grep noexec_user_stack /etc/system | grep -v _log | grep 1`
if [ -z "$NX" ]; then
echo "[UPC031] WARNING: No NX"
fi
NXLOG=`grep noexec_user_stack_log /etc/system | grep 1`
if [ -z "$NXLOG" ]; then
echo "[UPC032] WARNING: No NX logging"
fi
AUDIT=`grep c2audit:audit_load /etc/system | grep 1`
if [ -z "$AUDIT" ]; then
echo "[UPC033] WARNING: Auditing not enabled"
fi
fi
if [ "$OS" = "aix" ]; then
false
fi
if [ "$OS" = "hpux" ]; then
NX=`kmtune -q executable_stack | grep executable_stack | awk '{print $2}'`
if [ "$NX" -eq 1 ]; then
echo "[UPC034] WARNING: No NX"
elif [ "$NX" -eq 2 ]; then
echo "[UPC035] WARNING: NX set to logging only"
fi
fi
if [ "$OS" = "linux" ]; then
ASLR=`sysctl kernel.randomize_va_space | awk '{print $3}'`
if [ "$ASLR" -eq 0 ]; then
echo "[UPC036] WARNING: No ASLR"
elif [ "$ASLR" -eq 1 ]; then
echo "[UPC037] WARNING: Conservative ASLR"
fi
MMAP=`cat /proc/sys/vm/mmap_min_addr`
if [ "$MMAP" -eq 0 -o "$MMAP" = "" ]; then
echo "[UPC038] WARNING: mmap allows map to 0"
fi
if [ ! -f /selinux/enforce ]; then
echo "[UPC039] WARNING: SELinux does not enforce"
fi
for PROCDIR in /proc/[0-9]*; do
unset PROGPATH
PID=`echo $PROCDIR | cut -f 3 -d /`
echo ------------------------
echo "PID: $PID"
if [ -d "$PROCDIR" ]; then
if [ -r "$PROCDIR/exe" ]; then
PROGPATH=`ls -l "$PROCDIR/exe" 2>&1 | sed 's/ (deleted)//' | awk '{print $NF}'`
else
if [ -r "$PROCDIR/cmdline" ]; then
P=`cat $PROCDIR/cmdline | tr "\0" = | cut -f 1 -d = | grep '^/'`
if [ -z "$P" ]; then
echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
else
PROGPATH=$P
fi
else
echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
continue
fi
fi
else
echo "ERROR: Can't find full path of running process. Process has gone."
continue
fi
if [ -n "$PROGPATH" ]; then
echo "Program path: $PROGPATH"
NX=`grep stack $PROCDIR/maps | grep -v "rw-"`
if [ -n "$NX" ]; then
echo "[UPC040] WARNING: NX not enabled"
fi
SSP=`objdump -D $PROCDIR/exe | grep stack_chk`
if [ -z "$SSP" ]; then
echo "[UPC041] WARNING: SSP not enabled"
fi
fi
done
find / \( -perm -u+s -o -perm -g+s \) -type f | while read PROGPATH; do
echo "Program path: $PROGPATH"
ls -la $PROGPATH
SSP=`objdump -D $PROGPATH | grep stack_chk`
if [ -z "$SSP" ]; then
echo "[UPC042] WARNING: SSP not enabled"
fi
done
find / -type f -exec /sbin/getcap {} \; 2>/dev/null | grep "=" | awk '{print $1}' | while read PROGPATH; do
echo "Program path: $PROGPATH"
/sbin/getcap $PROGPATH
SSP=`objdump -D $PROGPATH | grep stack_chk`
if [ -z "$SSP" ]; then
echo "[UPC042] WARNING: SSP not enabled"
fi
done
fi
fi