diff options
Diffstat (limited to 'meta-security/recipes-security/redhat-security/files/rpm-chksec.sh')
-rw-r--r-- | meta-security/recipes-security/redhat-security/files/rpm-chksec.sh | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh b/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh new file mode 100644 index 000000000..a0e8bb1a5 --- /dev/null +++ b/meta-security/recipes-security/redhat-security/files/rpm-chksec.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# rpm-chksec +# +# Copyright (c) 2011-2013 Steve Grubb. ALL RIGHTS RESERVED. +# sgrubb@redhat.com +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Given an rpm, it will look at each file to check that its compiled with +# the intended flags to make it more secure. Things that are green are OK. +# Anything in yellow could be better but is passable. Anything in red needs +# attention. +# +# If the --all option is given, it will generate a list of rpms and then +# summarize the rpm's state. For yes, then all files are in the expected +# state. Just one file not compiled with the right flags can turn the +# answer to no. Re-run passing that package (instead of --all) for the details. +# +# To save to file: ./rpm-chksec | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee output.txt + +VERSION="0.5.2" + +usage () { + echo "rpm-chksec [--version|--all|<rpmname>...]" + if [ ! -x /usr/bin/filecap ] ; then + echo "You need to install libcap-ng-utils to test capabilities" + fi + if [ $EUID != 0 ] ; then + echo "You might need to be root to read some files" + fi + exit 0 +} + +if [ "$1" = "--help" -o $# -eq 0 ] ; then + usage +fi +if [ "$1" = "--version" ] ; then + echo "rpm-chksec $VERSION" + exit 0 +fi +if [ "$1" = "--all" ] ; then + MODE="all" +else + MODE="single" +fi + +do_one () { +if ! rpm -q $1 >/dev/null 2>&1 ; then + if [ "$MODE" = "single" ] ; then + echo "$1 is not installed" + exit 1 + else + echo "not installed" + return + fi +fi +files=`rpm -ql $1` + +# Look for daemons, need this for later... +DAEMON="" +for f in $files +do + if [ ! -f "$f" ] ; then + continue + fi + if [ `echo "$f" | grep '\/etc\/rc.d\/init.d'` ] ; then + n=`basename "$f"` + t=`which "$n" 2>/dev/null` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + t=`which "$n"d 2>/dev/null` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + t=`cat "$f" 2>/dev/null | grep 'bin' | grep 'exit 5' | grep -v '\$'` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + if [ "$MODE" = "single" ] ; then + echo "Can't find the executable in $f but daemon rules would apply" + fi + elif [ `echo "$f" | grep '\/lib\/systemd\/'` ] ; then + t=`cat "$f" | grep -i '^ExecStart=' | tr '=' ' ' | awk '{ print $2 }'` + if [ x"$t" != "x" ] ; then + DAEMON="$DAEMON $t" + continue + fi + fi +done + +# Prevent garbled output when doing --all. +skip_current=0 + +for f in $files +do + if [ ! -f "$f" ] ; then + continue + fi + # Some packages have files with ~ in them. This avoids it. + if ! echo "$f" | grep '^/' >/dev/null ; then + continue + fi + if [ ! -r "$f" ] && [ $EUID != 0 ] ; then + if [ $MODE = "single" ] ; then + echo "Please re-test $f as the root user" + else + # Don't print results. + skip_current=1 + echo "Please re-test $1 as the root user" + fi + continue + fi + if ! file "$f" | grep -qw 'ELF'; then + continue + fi + RELRO="no" + if readelf -l "$f" 2>/dev/null | grep -q 'GNU_RELRO'; then + RELRO="partial" + fi + if readelf -d "$f" 2>/dev/null | grep -q 'BIND_NOW'; then + RELRO="full" + fi + PIE="no" + if readelf -h "$f" 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then + PIE="DSO" + if readelf -d "$f" 2>/dev/null | grep -q '(DEBUG)'; then + PIE="yes" + fi + fi + APP="" + if [ x"$DAEMON" != "x" ] ; then + for d in $DAEMON + do + if [ "$f" = "$d" ] ; then + APP="daemon" + break + fi + done + fi + if [ x"$APP" = "x" ] ; then + # See if this is a library or a setuid app + if [ `echo "$f" | grep '\/lib' | grep '\.so'` ] ; then + APP="library" + elif [ `find "$f" -perm -004000 -type f -print` ] ; then + APP="setuid" + elif [ `find "$f" -perm -002000 -type f -print` ] ; then + APP="setgid" + elif [ -x /usr/bin/filecap ] && [ `filecap "$f" 2> /dev/null | wc -w` -gt 0 ] ; then + APP="setcap" + else + syms1=`/usr/bin/readelf -s "$f" 2>/dev/null | egrep ' connect@.*GLIBC| listen@.*GLIBC| accept@.*GLIBC|accept4@.*GLIBC'` + syms2=`/usr/bin/readelf -s "$f" 2>/dev/null | egrep ' getaddrinfo@.*GLIBC| getnameinfo@.*GLIBC| getservent@.*GLIBC| getservbyname@.*GLIBC| getservbyport@.*GLIBC|gethostbyname@.*GLIBC| gethostbyname2@.*GLIBC| gethostbyaddr@.*GLIBC| gethostbyaddr2@.*GLIBC'` + if [ x"$syms1" != "x" ] ; then + if [ x"$syms2" != "x" ] ; then + APP="network-ip" + else + APP="network-local" + fi + fi + fi + fi + if [ x"$APP" = "x" ] ; then + APP="exec" + fi + + # OK, ready for the output + if [ "$MODE" = "single" ] ; then + printf "%-56s %-10s " "$f" $APP + if [ "$APP" = "daemon" -o "$APP" = "setuid" -o "$APP" = "setgid" -o "$APP" = "setcap" -o "$APP" = "network-ip" -o "$APP" = "network-local" ] ; then + if [ "$RELRO" = "full" ] ; then + printf "\033[32m%-7s\033[m " $RELRO + elif [ "$RELRO" = "partial" ] ; then + printf "\033[33m%-7s\033[m " $RELRO + else + printf "\033[31m%-7s\033[m " $RELRO + fi + if [ "$PIE" = "yes" ] ; then + printf "\033[32m%-4s\033[m" $PIE + else + printf "\033[31m%-4s\033[m" $PIE + fi + elif [ "$APP" = "library" ] ; then + if [ "$RELRO" = "full" -o "$RELRO" = "partial" ] ; then + printf "\033[32m%-7s\033[m " $RELRO + else + printf "\033[31m%-7s\033[m " $RELRO + fi + printf "\033[32m%-4s\033[m" $PIE + else + # $APP = exec - we want partial relro + if [ "$RELRO" = "no" ] ; then + printf "\033[31m%-7s\033[m " $RELRO + else + printf "\033[32m%-7s\033[m " $RELRO + fi + printf "\033[32m%-4s\033[m" $PIE + fi + echo + else + if [ "$APP" = "daemon" -o "$APP" = "setuid" -o "$APP" = "setgid" -o "$APP" = "setcap" -o "$APP" = "network-ip" -o "$APP" = "network-local" ] ; then + if [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + if [ "$PIE" = "no" ] ; then + PIE_SUM="no" + APP_SUM="$APP" + fi + elif [ "$APP" = "library" ] ; then + if [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + # $APP = exec - must have partial or full relro + elif [ "$RELRO" = "no" ] ; then + RELRO_SUM="no" + APP_SUM="$APP" + fi + fi +done +} + +if [ "$MODE" = "single" ] ; then + printf "%-56s %-10s %-7s %-4s" "FILE" "TYPE" "RELRO" "PIE" + echo + for i; do + f=$(basename $1) + # Strip the .rpm extension, if present. + do_one ${f%%.rpm} + shift + done + exit 0 +fi + +# Skip the kernel as its special +packages=`rpm -qa | egrep -v 'kernel.|debuginfo.|.noarch|gpg-pubkey' | sort` +printf "%-50s %-5s %-4s %-14s" "PACKAGE" "RELRO" "PIE" "CLASS" +echo +for p in $packages +do + RELRO_SUM="yes" + PIE_SUM="yes" + APP_SUM="" + printf "%-50s " $p + do_one $p + if [[ $skip_current -eq 1 ]] ; then + continue + fi + if [ "$RELRO_SUM" = "yes" ] ; then + printf "\033[32m%-5s\033[m " "$RELRO_SUM" + else + printf "\033[31m%-5s\033[m " "$RELRO_SUM" + fi + if [ "$PIE_SUM" = "yes" ] ; then + printf "\033[32m%-4s\033[m" "$PIE_SUM" + if [ "$RELRO_SUM" = "no" ] ; then + printf " %-14s" "$APP_SUM" + fi + else + if [ "$APP_SUM" = "network-local" ] ; then + printf "\033[33m%-4s\033[m %-14s" "$PIE_SUM" "$APP_SUM" + else + printf "\033[31m%-4s\033[m %-14s" "$PIE_SUM" "$APP_SUM" + fi + fi + echo +done +exit 0 + + |