diff options
Diffstat (limited to 'progs/quicktest.sh')
-rwxr-xr-x | progs/quicktest.sh | 149 |
1 files changed, 129 insertions, 20 deletions
diff --git a/progs/quicktest.sh b/progs/quicktest.sh index e8b2c8e..6aa2598 100755 --- a/progs/quicktest.sh +++ b/progs/quicktest.sh @@ -44,9 +44,15 @@ pass_capsh () { pass_capsh --print +# Validate that PATH expansion works +PATH=$(/bin/pwd)/junk:$(/bin/pwd) capsh == == == --modes +if [ $? -ne 0 ]; then + echo "Failed to execute capsh consecutively for capability manipulation" + exit 1 +fi # Make a local non-setuid-0 version of capsh and call it privileged -cp ./capsh ./privileged && chmod -s ./privileged +cp ./tcapsh-static ./privileged && /bin/chmod -s ./privileged if [ $? -ne 0 ]; then echo "Failed to copy capsh for capability manipulation" exit 1 @@ -64,21 +70,37 @@ if [ $? -ne 0 ]; then exit 1 fi +# validate libcap modes: +pass_capsh --inh=cap_chown --mode=PURE1E --print --inmode=PURE1E +pass_capsh --mode=NOPRIV --print --inmode=NOPRIV +pass_capsh --mode=PURE1E --print --mode=NOPRIV --inmode=NOPRIV +fail_capsh --mode=NOPRIV --print --mode=PURE1E +fail_capsh --user=nobody --mode=NOPRIV --print -- ./privileged + +# simple IAB setting (no ambient) in pure1e mode. +pass_capsh --mode=PURE1E --iab='!%cap_chown,cap_sys_admin' + # Explore keep_caps support pass_capsh --keep=0 --keep=1 --keep=0 --keep=1 --print -rm -f tcapsh -cp capsh tcapsh -chown root.root tcapsh -chmod u+s tcapsh -ls -l tcapsh +/bin/rm -f tcapsh +/bin/cp tcapsh-static tcapsh +/bin/chown root.root tcapsh +/bin/chmod u+s tcapsh +/bin/ls -l tcapsh -# leverage keep caps maintain capabilities accross a change of uid +# leverage keep caps to maintain capabilities accross a change of euid # from setuid root to capable luser (as per wireshark/dumpcap 0.99.7) -pass_capsh --uid=500 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --uid=500 --caps=\"cap_net_raw,cap_net_admin=pie\" --print" +# This test is subtle. It is testing that a change to self, dropping +# euid=0 back to that of the luser keeps capabilities. +pass_capsh --uid=1 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --print --uid=1 --print --caps=\"cap_net_raw,cap_net_admin=pie\" --print" + +# this test is a change of user to a new user, note we need to raise +# the cap_setuid capability (libcap has a function for that) in this case. +pass_capsh --uid=1 -- -c "./tcapsh --caps=\"cap_net_raw,cap_net_admin=ip cap_setuid=p\" --print --cap-uid=2 --print --caps=\"cap_net_raw,cap_net_admin=pie\" --print" # This fails, on 2.6.24, but shouldn't -pass_capsh --uid=500 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --uid=500 --forkfor=10 --caps= --print --killit=9 --print" +pass_capsh --uid=1 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --uid=1 --forkfor=10 --caps= --print --killit=9 --print" # only continue with these if --secbits is supported ./capsh --secbits=0x2f > /dev/null 2>&1 @@ -98,7 +120,7 @@ fail_capsh --secbits=32 --keep=1 --keep=0 --print pass_capsh --secbits=10 --keep=0 --keep=1 --print fail_capsh --secbits=47 -- -c "./tcapsh --uid=$nouid" -rm -f tcapsh +/bin/rm -f tcapsh # Suppress uid=0 privilege fail_capsh --secbits=47 --print -- -c "./capsh --uid=$nouid" @@ -115,12 +137,10 @@ fail_capsh --drop=cap_setuid --secbits=0x2f --print -- -c "./privileged --uid=$n # Note, the bounding set (edited with --drop) only limits p # capabilities, not i's. pass_capsh --secbits=47 --inh=cap_setuid,cap_setgid --drop=cap_setuid \ - --uid=500 --print -- -c "./privileged --uid=$nouid" - -rm -f ./privileged + --uid=1 --print -- -c "./privileged --uid=$nouid" # test that we do not support capabilities on setuid shell-scripts -cat > hack.sh <<EOF +/bin/cat > hack.sh <<EOF #!/bin/bash /usr/bin/id mypid=\$\$ @@ -134,20 +154,109 @@ else fi exit 0 EOF -chmod +xs hack.sh -./capsh --uid=500 --inh=none --print -- ./hack.sh +/bin/chmod +xs hack.sh +./capsh --uid=1 --inh=none --print -- ./hack.sh status=$? -rm -f ./hack.sh +/bin/rm -f ./hack.sh if [ $status -ne 0 ]; then echo "shell scripts can have capabilities (bug)" exit 1 fi -# Max lockdown +# Max lockdown (ie., pure capability model as POSIX.1e intended). +secbits=0x2f +if ./capsh --has-ambient ; then + secbits="0xef --noamb" +fi pass_capsh --keep=1 --uid=$nouid --caps=cap_setpcap=ep \ - --drop=all --secbits=0x2f --caps= --print + --drop=all --secbits=$secbits --caps= --print # Verify we can chroot pass_capsh --chroot=$(/bin/pwd) -pass_capsh --chroot=$(/bin/pwd) == +pass_capsh -- -c "./tcapsh-static --chroot=$(/bin/pwd) ==" fail_capsh --chroot=$(/bin/pwd) -- -c "echo oops" + +./capsh --has-ambient +if [ $? -eq 0 ]; then + echo "test ambient capabilities" + + # Ambient capabilities (any file can inherit capabilities) + pass_capsh --noamb + + # test that shell scripts can inherit through ambient capabilities + /bin/cat > hack.sh <<EOF +#!/bin/bash +/usr/bin/id +mypid=\$\$ +caps=\$(./getpcaps \$mypid 2>&1 | /usr/bin/cut -d: -f2) +if [ "\$caps" != " = cap_setuid+i" ]; then + echo "Shell script got [\$caps]" + exit 0 +fi +ls -l \$0 +echo "no capabilities [\$caps] for this shell script" +exit 1 +EOF + /bin/chmod +x hack.sh + pass_capsh --keep=1 --uid=$nouid --inh=cap_setuid --addamb=cap_setuid -- ./hack.sh + + /bin/rm -f hack.sh + + # Next force the privileged binary to have an empty capability set. + # This is sort of the opposite of privileged - it should ensure that + # the file can never aquire privilege by the ambient method. + ./setcap = ./privileged + fail_capsh --keep=1 --uid=$nouid --inh=cap_setuid --addamb=cap_setuid -- -c "./privileged --print --uid=1" + + # finally remove the capability from the privileged binary and try again. + ./setcap -r ./privileged + pass_capsh --keep=1 --uid=$nouid --inh=cap_setuid --addamb=cap_setuid -- -c "./privileged --print --uid=1" + + # validate IAB setting with an ambient capability + pass_capsh --iab='!%cap_chown,^cap_setpcap,cap_sys_admin' + fail_capsh --mode=PURE1E --iab='!%cap_chown,^cap_sys_admin' +fi +/bin/rm -f ./privileged + +echo "testing namespaced file caps" + +# nsprivileged capsh will have an ns rootid value (this is +# the same setup as an earlier test but with a ns file cap). +rm -f nsprivileged +cp ./tcapsh-static ./nsprivileged && /bin/chmod -s ./nsprivileged +./setcap -n 1 all=ep ./nsprivileged +if [ $? -eq 0 ]; then + ./getcap -n ./nsprivileged | fgrep "[rootid=1]" + if [ $? -ne 0 ]; then + echo "FAILED setting ns rootid on file" + exit 1 + fi + # since this is a ns file cap and not a regular one, it should not + # lead to a privilege escalation outside of the namespace it + # refers to. We suppress uid=0 privilege and confirm this + # nsprivileged binary does not have the power to change uid. + fail_capsh --secbits=$secbits --print -- -c "./nsprivileged --uid=$nouid" +else + echo "ns file caps not supported - skipping test" +fi +rm -f nsprivileged + +# If the build tree compiled the Go cap package. +if [ -f ../go/compare-cap ]; then + cp ../go/compare-cap . + LD_LIBRARY_PATH=../libcap ./compare-cap + if [ $? -ne 0 ]; then + echo "FAILED to execute go binary" + exit 1 + fi + LD_LIBRARY_PATH=../libcap ./compare-cap 2>&1 | grep "skipping file cap tests" + if [ $? -eq 0 ]; then + echo "FAILED not engaging file cap tests" + fi + echo "PASSED" +else + echo "no Go support compiled, so skipping Go tests" +fi +rm -f compare-cap + +echo "ALL TESTS PASSED!" |