From cea08e9d74b99e929989f1a43c2cde3d936a2b4f Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Mon, 6 Aug 2012 18:28:07 -0400 Subject: [PATCH] Got the initial restricted file list setup; some things are missing because they may expose a security hole, and they need a further, more detailed wrapper (like mount, find, etc etc), because they expose both harmless read-only, and extremely damaging write functions. --- client/bin/disco-fs-mount | 67 ++++++------ client/bin/disco-fs-unmount | 22 ++-- client/etc/restricted.d/base.bin.d | 64 +++++++++++ client/etc/restricted.d/base.usr.bin.d | 146 +++++++++++++++++++++++++ 4 files changed, 252 insertions(+), 47 deletions(-) create mode 100644 client/etc/restricted.d/base.bin.d create mode 100644 client/etc/restricted.d/base.usr.bin.d diff --git a/client/bin/disco-fs-mount b/client/bin/disco-fs-mount index 11bd470..ad774a7 100755 --- a/client/bin/disco-fs-mount +++ b/client/bin/disco-fs-mount @@ -12,14 +12,15 @@ fi # Cleanup old junk rm -rf ${DISCOROOT}/scratchfs rm -rf ${DISCOROOT}/restricted/* +rm -rf ${DISCOROOT}/munge/* # Prepare all the mountpoint directories mkdir -p ${DISCOROOT}/chroot -mkdir -p ${DISCOROOT}/execs/bin -mkdir -p ${DISCOROOT}/proc/proc -mkdir -p ${DISCOROOT}/sysfs/sys +#mkdir -p ${DISCOROOT}/proc/proc +#mkdir -p ${DISCOROOT}/sysfs/sys mkdir -p ${DISCOROOT}/rootfs mkdir -p ${DISCOROOT}/scratchfs +mkdir -p ${DISCOROOT}/munge mkdir -p ${DISCOROOT}/dev/dev mkdir -p ${DISCOROOT}/restricted/bin @@ -28,35 +29,34 @@ mkdir -p ${DISCOROOT}/restricted/bin mkdir -p ${DISCOCFG}/restricted.d for file in $(cat ${DISCOCFG}/restricted.d/* 2>/dev/null | grep -v "^#") do - mkdir -p ${DISCOROOT}/restricted/bin$(echo $file | dirname $file) - ln -s $file ${DISCOROOT}/restricted/bin/$file + if [ ! -e ${DISCOROOT}/restricted/bin/$(basename $file) ]; then + ln -s $file ${DISCOROOT}/restricted/bin/$(basename $file) + fi done # Setup some more restricted execution stuff, but only if we actually have $NOOP if [ "$NOOP" != "" ]; then + # Munge up /etc/profile + mkdir -p ${DISCOROOT}/munge/etc + cp /etc/profile ${DISCOROOT}/munge/etc/profile + echo "export PATH=${DISCOROOT}/restricted/bin" >> ${DISCOROOT}/munge/etc/profile + + # Make default wrapper + echo -e "#!/bin/bash\necho \"info: Would execute \$0 \$@\"" > ${DISCOROOT}/restricted/bin/_disco_restricted_cmd + chmod +x ${DISCOROOT}/restricted/bin/_disco_restricted_cmd + + # Now link everything to the default wrapper for dir in $(echo $PATH | sed s/":"/" "/g) do for file in ${dir}/* do - if [ "$file" != "/bin/bash" ] && [ -x $file ] && [ ! -x ${DISCOROOT}/restricted${file} ] ; then - mkdir -p $(dirname ${DISCOROOT}/restricted/${file}) - echo -e "#!/bin/bash\necho \"info: Would execute \$0 \$@\"" > ${DISCOROOT}/restricted${file} - chmod +x ${DISCOROOT}/restricted${file} + FNAME=$(basename $file) + if [ "$FNAME" != "bash" ] && [ -x $file ] && [ ! -x ${DISCOROOT}/restricted/bin/$FNAME ] ; then + ln -s ${DISCOROOT}/restricted/bin/_disco_restricted_cmd ${DISCOROOT}/restricted/bin/${FNAME} fi done done - # Here we play a pretty lame trick on the user. /bin/bash will always exist - # (unfortunately), but we can force everything else to our rbash wrapper, - # forcing restricted execution. The user can get around this by calling - # /bin/bash directly, but that's on the user. TNMP, RTFM! - #ln -s /bin/bash ${DISCOROOT}/restricted/bin/rbash - #for dir in /usr/bin /usr/local/bin /usr/sbin; - #do - # mkdir -p ${DISCOROOT}/restricted/${dir} - # echo "#!/bin/bash --restricted\neval \$@" > ${DISCOROOT}/restricted/${dir}/bash - # chmod +x ${DISCOROOT}/restricted/${dir}/bash - #done fi # We need SOME special files in /dev like /dev/null, so make them here @@ -69,26 +69,25 @@ chmod 666 ${DISCOROOT}/dev/dev/null mount --bind -o ro / ${DISCOROOT}/rootfs 2>&1 | grep -v "seems to be mounted read-write" mount -o remount,ro ${DISCOROOT}/rootfs +# Setup filesystem layers. The read/write ones go on the top, with scratchfs ALWAYS on top. +FSLAYERS="${DISCOROOT}/scratchfs=rw" +FSLAYERS="${FSLAYERS}:${DISCOROOT}/munge=ro" +FSLAYERS="${FSLAYERS}:${DISCOROOT}/dev=rw" +#FSLAYERS="${FSLAYERS}:${DISCOROOT}/proc=ro" +#FSLAYERS="${FSLAYERS}:${DISCOROOT}/sysfs=ro" +FSLAYERS="${FSLAYERS}:${DISCOROOT}/rootfs=ro" + +# Union +unionfs -o cow,dev,dirs=$FSLAYERS ${DISCOROOT}/chroot + # Duplicate /proc and /sys if they already exist mount | grep " on /proc" >/dev/null 2>&1 if [ $? -eq 0 ]; then - mount -t proc -o ro none ${DISCOROOT}/proc/proc + mount -t proc -o ro none ${DISCOROOT}/chroot/proc fi mount | grep " on /sys" >/dev/null 2>&1 if [ $? -eq 0 ]; then - mount -t sysfs -o ro none ${DISCOROOT}/sysfs/sys + mount -t sysfs -o ro none ${DISCOROOT}/chroot/sys fi -# Setup filesystem layers. The read/write ones go on the top, with scratchfs ALWAYS on top. -FSLAYERS="${DISCOROOT}/scratchfs=rw" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/dev=rw" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/restricted=ro" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/execs=ro" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/proc=ro" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/sysfs=ro" -FSLAYERS="${FSLAYERS}:${DISCOROOT}/rootfs=ro" - -# Here we go -unionfs -o cow,dev,dirs=$FSLAYERS ${DISCOROOT}/chroot - exit 0 \ No newline at end of file diff --git a/client/bin/disco-fs-unmount b/client/bin/disco-fs-unmount index 37f364d..40d715a 100755 --- a/client/bin/disco-fs-unmount +++ b/client/bin/disco-fs-unmount @@ -10,25 +10,21 @@ fi umount ${DISCOROOT}/chroot umount ${DISCOROOT}/proc/proc - -#Unmount the proc/sys mirrors if they were mounted -mount | grep " on /${DISCOROOT}/proc/proc" >/dev/null 2>&1 -if [ $? -eq 0 ]; then - mount -t proc -o ro none ${DISCOROOT}/proc/proc - mount -t sysfs -o ro none ${DISCOROOT}/sysfs/sys -fi -mount | grep " on /${DISCOROOT}/sysfs/sys" >/dev/null 2>&1 -if [ $? -eq 0 ]; then - mount -t sysfs -o ro none ${DISCOROOT}/sysfs/sys -fi - -umount ${DISCOROOT}/sysfs/sys umount ${DISCOROOT}/rootfs mount | grep $DISCOROOT > /dev/null 2>&1 if [ $? -eq 0 ]; then # Sometimes required umount ${DISCOROOT}/rootfs fi +#Unmount the proc/sys mirrors if they were mounted +mount | grep " on ${DISCOROOT}/proc/proc" >/dev/null 2>&1 +if [ $? -eq 0 ]; then + mount -t proc -o ro none ${DISCOROOT}/proc/proc +fi +mount | grep " on ${DISCOROOT}/sysfs/sys" >/dev/null 2>&1 +if [ $? -eq 0 ]; then + mount -t sysfs -o ro none ${DISCOROOT}/sysfs/sys +fi rm -rf ${DISCOROOT}/scratchfs/* ${DISCOROOT}/scratchfs/.unionfs rm -rf ${DISCOROOT}/dev/* diff --git a/client/etc/restricted.d/base.bin.d b/client/etc/restricted.d/base.bin.d new file mode 100644 index 0000000..d9cf38f --- /dev/null +++ b/client/etc/restricted.d/base.bin.d @@ -0,0 +1,64 @@ +/bin/arch +/bin/basename +/bin/cat +/bin/chgrp +/bin/chmod +/bin/chown +/bin/cp +/bin/cpio +/bin/cut +/bin/dash +/bin/date +/bin/dd +/bin/df +/bin/dmesg +/bin/dnsdomainname +/bin/domainname +/bin/dumpkeys +/bin/echo +/bin/ed +/bin/egrep +/bin/false +/bin/fgrep +/bin/findmnt +/bin/grep +/bin/gtar +/bin/gunzip +/bin/gzip +/bin/hostname +/bin/ipcalc +/bin/keyctl +/bin/link +/bin/ln +/bin/loadkeys +/bin/ls +/bin/lsblk +/bin/mkdir +/bin/mknod +/bin/mktemp +/bin/mv +/bin/netstat +/bin/nisdomainname +/bin/ping +/bin/ping6 +/bin/ps +/bin/pwd +/bin/readlink +/bin/rm +/bin/rmdir +/bin/sed +/bin/sleep +/bin/sort +/bin/sync +/bin/tar +/bin/touch +/bin/tracepath +/bin/tracepath6 +/bin/traceroute +/bin/traceroute6 +/bin/true +/bin/uname +/bin/unlink +/bin/usleep +/bin/ypdomainname +/bin/zcat diff --git a/client/etc/restricted.d/base.usr.bin.d b/client/etc/restricted.d/base.usr.bin.d new file mode 100644 index 0000000..209e9eb --- /dev/null +++ b/client/etc/restricted.d/base.usr.bin.d @@ -0,0 +1,146 @@ +/usr/bin/attr +/usr/bin/base64 +/usr/bin/bashbug-32 +/usr/bin/bc +/usr/bin/bunzip2 +/usr/bin/bzcat +/usr/bin/bzcmp +/usr/bin/bzdiff +/usr/bin/bzgrep +/usr/bin/bzip2 +/usr/bin/bzip2recover +/usr/bin/bzless +/usr/bin/bzmore +/usr/bin/chacl +/usr/bin/chage +/usr/bin/chattr +/usr/bin/chcon +/usr/bin/chfn +/usr/bin/chvt +/usr/bin/clear +/usr/bin/cmp +/usr/bin/crontab +/usr/bin/cut +/usr/bin/diff +/usr/bin/diff3 +/usr/bin/dig +/usr/bin/dir +/usr/bin/dircolors +/usr/bin/dirname +/usr/bin/du +/usr/bin/expand +/usr/bin/expr +/usr/bin/file +/usr/bin/find-repos-of-install +/usr/bin/fmt +/usr/bin/fold +/usr/bin/free +/usr/bin/funzip +/usr/bin/getent +/usr/bin/getfacl +/usr/bin/getfattr +/usr/bin/gethostip +/usr/bin/getkeycodes +/usr/bin/getopt +/usr/bin/gpasswd +/usr/bin/gpg +/usr/bin/gpg2 +/usr/bin/gpgconf +/usr/bin/gpg-error +/usr/bin/gpgkey2ssh +/usr/bin/groups +/usr/bin/gunzip +/usr/bin/gzip +/usr/bin/head +/usr/bin/hexdump +/usr/bin/host +/usr/bin/hostid +/usr/bin/iconv +/usr/bin/id +/usr/bin/install +/usr/bin/install-catalog +/usr/bin/iostat +/usr/bin/join +/usr/bin/last +/usr/bin/lastlog +/usr/bin/locale +/usr/bin/localedef +/usr/bin/locate +/usr/bin/logger +/usr/bin/lsattr +/usr/bin/lscpu +/usr/bin/lsusb +/usr/bin/md5sum +/usr/bin/mkfifo +/usr/bin/mkisofs +/usr/bin/needs-restarting +/usr/bin/nslookup +/usr/bin/ntpstat +/usr/bin/openssl +/usr/bin/passwd +/usr/bin/paste +/usr/bin/pidstat +/usr/bin/pr +/usr/bin/printenv +/usr/bin/printf +/usr/bin/pstree +/usr/bin/quota +/usr/bin/rdate +/usr/bin/readelf +/usr/bin/readlink +/usr/bin/rename +/usr/bin/rpm2cpio +/usr/bin/rpmdb +/usr/bin/rpmdumpheader +/usr/bin/rpmquery +/usr/bin/rpmsign +/usr/bin/rpmverify +/usr/bin/rsync +/usr/bin/scp +/usr/bin/script +/usr/bin/scriptreplay +/usr/bin/seq +/usr/bin/sha1sum +/usr/bin/sha224sum +/usr/bin/sha256sum +/usr/bin/sha384sum +/usr/bin/sha512sum +/usr/bin/showkey +/usr/bin/shred +/usr/bin/shuf +/usr/bin/size +/usr/bin/split +/usr/bin/sqlite3 +/usr/bin/ssh-keygen +/usr/bin/stat +/usr/bin/sum +/usr/bin/tac +/usr/bin/tail +/usr/bin/tailf +/usr/bin/tee +/usr/bin/test +/usr/bin/tr +/usr/bin/tree +/usr/bin/truncate +/usr/bin/tsort +/usr/bin/tty +/usr/bin/ul +/usr/bin/unexpand +/usr/bin/uniq +/usr/bin/unlzma +/usr/bin/unzip +/usr/bin/unzipsfx +/usr/bin/updatedb +/usr/bin/uptime +/usr/bin/users +/usr/bin/uuidgen +/usr/bin/vmstat +/usr/bin/w +/usr/bin/wc +/usr/bin/whatis +/usr/bin/whereis +/usr/bin/which +/usr/bin/who +/usr/bin/whoami +/usr/bin/wnck-urgency-monitor +/usr/bin/zip