autospec/tests/test02_pkgsecurity.in
Davide Madrisan c55acfc48b Release 1.16.5
Signed-off-by: Davide Madrisan <davide.madrisan@gmail.com>
2014-12-30 21:30:11 +01:00

189 lines
5.9 KiB
Bash

#!/bin/bash
# test02_pkgsecurity -- @package@ test (rpm security checks)
# Copyright (C) 2008,2012,2014 Davide Madrisan <davide.madrisan@gmail.com>
[ -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/<script_name>.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 ('<script_name>.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}""
"
}