#!/bin/bash # test02_pkgsecurity -- @package@ test (rpm security checks) # Copyright (C) 2008,2012 Davide Madrisan [ -z "$BASH" ] || [ ${BASH_VERSION:0:1} -lt 2 ] && echo $"this script requires bash version 2 or better" >&2 && exit 1 me=("test02_pkgsecurity" "@version@" "@date@") [ -r @libdir@/libmsgmng.lib ] || { echo "$me: "$"library not found"": @libdir@/libmsgmng.lib" 1>&2 exit 1; } . @libdir@/libmsgmng.lib [ -r @libdir@/libtranslate.lib ] || { echo "$me: "$"library not found"": @libdir@/libtranslate.lib" 1>&2 exit 1; } . @libdir@/libtranslate.lib notify.debug $"loading"": \`test02_pkgsecurity'..." # check if all the needed tools are available for tool in file find getopt grep objdump sed; do [ "$(type -p $tool)" ] || notify.error $"utility not found"": \`$tool'" done function alltests() { # FIXME: add to 'po' file notify.note " ${NOTE}"$"performing security checks""${NORM}""..." TEMP=`LC_ALL=C getopt \ -o i:t: --long infofile:,tmpdir: \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || return 1 eval set -- "$TEMP" while :; do case "$1" in -i|--infofile) rpminfofile="$2" shift ;; -t|--tmpdir) tmpextractdir="$2" shift ;; --) shift; break ;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error" ;; esac shift done [ "$rpminfofile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--infofile)" [ -r "$rpminfofile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"cannot read"" \`$rpminfofile'" . $rpminfofile [ "$tmpextractdir" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--tmpdir)" [ -d "$tmpextractdir" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"no such file or directory"" \`$tmpextractdir'" function security.filecheckrpath() { # $1: file to check # RPATH /usr/lib/.:/usr/lib/qt3/lib:/usr/lib:/usr/X11R6/lib objdump -p $1 2>/dev/null | \ sed -n '/RPATH/{s/.* \(.*\)/\1:/p}' | \ while read -d: path; do # try to discard false positive warnings [[ "${allowed_libdirs}:" =~ ${path}: ]] || echo -n "$path " done } local total_issues=0 test.skip $test_number || { notify.note "$(test.num2str). ${NOTE}"\ $"checking for RPATH vulnerabilities""${NORM}..." let "i = 0" for pck in ${rpmpkg_name[@]}; do pushd $tmpextractdir/$i >/dev/null # find ELF binaries (ELF 32-bit LSB executable) # and libs (ELF 32-bit LSB shared object) for f in $(find -mindepth 2 -perm /111 -type f); do if [[ "$(file $f | grep " ELF ")" ]]; then rpath="$(security.filecheckrpath $f)" if [ "$rpath" ]; then notify.warning "${NORM}${pck##*/} --> ${f/./}" notify.note "RPATH: $rpath" let "total_issues += 1" fi fi done popd >/dev/null let "i += 1" done; } test_number=$(($test_number + 1)) test.skip $test_number || { notify.note "$(test.num2str). ${NOTE}"\ $"checking for setuid binaries""${NORM}..." let "i = 0" for pck in ${rpmpkg_name[@]}; do pushd $tmpextractdir/$i >/dev/null for f in $(find -mindepth 2 -perm /111 -type f 2>/dev/null); do if [[ "$(LC_ALL=C file $f | grep " setuid ")" ]]; then notify.warning "${NORM}${pck##*/} --> ${f/./}" let "total_issues += 1" fi done popd >/dev/null let "i += 1" done; } test_number=$(($test_number + 1)) test.skip $test_number || { notify.note "$(test.num2str). ${NOTE}"\ $"checking for setgid directories""${NORM}..." let "i = 0" for pck in ${rpmpkg_name[@]}; do pushd $tmpextractdir/$i >/dev/null for d in $(find -mindepth 2 -perm -2000 -type d 2>/dev/null); do notify.warning "${NORM}${pck##*/} --> ${d/./}" let "total_issues += 1" done popd >/dev/null let "i += 1" done; } test_number=$(($test_number + 1)) # checking for unsecure use of $$ as random source in shell scripts test.skip $test_number || { notify.note "$(test.num2str). ${NOTE}"\ $"checking for unsecure use of \`\$\$' in shell and perl scripts""${NORM}..." vulnerable=0 let "i = 0" for pck in ${rpmpkg_name[@]}; do pushd $tmpextractdir/$i >/dev/null for f in $(find -mindepth 1 -perm /111 -type f); do # we are interesting only in shell scripts [[ "$(file $f | grep "shell script\|perl script")" ]] || continue # check for string like: # - tmp=/tmp/zfoo.$$ # - gzip -cdfq "$2" > /tmp/"$F".$$ [[ \ -n "$(grep $f -m1 -s -rl -e"[^[:space:]]*=.*\$\$")" || -n "$(grep $f -m1 -s -rl -e">[[:space:]]*.*[[:space:]]*[^[:space:]]*\$\$")" ]] && let "vulnerable = 1" && { notify.warning "${NOTE}${pck##*/}${NORM}" notify.note $"\ seems to be affected"": \`${NOTE}${f/./}${NORM}'" let "total_issues += 1"; } done popd >/dev/null let "i += 1" done [[ $vulnerable -eq 1 ]] && notify.note "\ ----------------------------- ${NOTE}"$"Hint for bash scripts (\`mktemp' required)"":${NORM} tmpdir=\`mktemp -d /tmp/.XXXXXX\` || { echo \"Cannot create directory \\\`\$tmpdir'. Aborting.\" >&2; exit 1; } trap 'ret=\$?; rm -rf \$tmpdir && exit \$ret' 0 trap '(exit $?); exit' 1 2 13 15 tmpfile=\`env TMPDIR=\"\" mktemp -p \$tmpdir tmpfile.XXXXXX\` || { echo \"Cannot create temporary file \\\`\$tmpfile'. Aborting.\" >&2; exit 1; } ${NOTE}"$"Hint for perl scripts"":${NORM} use File::Temp qw/ tempfile /; (\$fh,\$file) = tempfile ('.XXXXXX'); -----------------------------"; } test_number=$(($test_number + 1)) notify.note " --> "$"${NOTE}Security checks: ${#rpmpkg_name[@]} \ package(s) checked: ${NORM}${WARN}$total_issues${NORM}${NOTE} warning(s).${NORM}"" " }