c55acfc48b
Signed-off-by: Davide Madrisan <davide.madrisan@gmail.com>
189 lines
5.9 KiB
Bash
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}""
|
|
"
|
|
}
|