Avoid sudo
in root
bash script?
Preamble: Care sharing root account!!
Unfortunely, there is no resistant way... Please read carefuly upto last paragraph
Once you give root access to someone, they could do anything, including editing your script!!
For sample, if user hit sudo su -
, then variables SUDO_*
doesn't exist anymore...
First quick way using pstree
So simplier way to search for sudo
presence in whole current tree, seem to use pstree
:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pstree -s $$ | grep -q '\bsudo\b' && die "Can't be run under sudo"
With ps
only, you could loop over ps ho ppid
:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pid=$$
while read pid name foo < <(ps ho ppid,cmd $pid) && ((pid>1));do
[ "$name" = "sudo" ] && die "Can't be run under sudo"
done
Regarding comment about renamed sudo
If sudo command is renamed or copied, then instead of looking for command name, look for UID in whole parent tree. So script is same than previous, but searching for UID >= 1000
in parent tree:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pid=$$
while read pid uid < <(ps ho ppid,uid $pid) && ((pid>1));do
((uid>999)) && die "Can't be run under sudo"
done
Because we are speaking about Un*x
To be correct, avoid using fixed statical datas, use of UID_MIN
from /etc/login.defs
:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
while read fld val;do
case $fld in UID_MIN ) UIDMIN=$val ;break ;; esac
done </etc/login.defs
((UIDMIN)) || die Getting UID_MIN.
pid=$$
while read pid uid < <(ps ho ppid,uid $pid) && ((pid>1));do
(( uid >= UIDMIN )) && die "Can't be run under sudo"
done
Workaround for executing this by using sudo
anyway
But all this is someting fragile:
$ sudo su -
# screen -D -R # apt install screen if not installed
Now hit Ctrl + a , then d to be detached. Type exit
or hit Ctrl + d to return in user mode...
Then simply:
$ sudo screen -x
Now, you'll be logged in a root login session. No trace of any sudo.
# ps $PPID
PID TTY STAT TIME COMMAND
26367 ? Ss 0:00 SCREEN -D -R
# ps ho ppid $PPID
1
# set | grep SUDO
# <-- nothing here!
Conclusion
As chepner rightly commented: sudo is drawn to give specifics access to specifics tools:
Nothing about sudo requires it to give you root access; that's just the default behavior everyone is familiar with. sudo can be configured to allow you to do only very specific things, including not gain root access at all – chepner
Care to configure them correctly, before using fragile workaround!
See:
apropos sudo
And read carefully
man sudo.conf
man sudoers
Regarding logname
Have a look at correct Stéphane Chazelas's answer! This could be the best answer for a homework!!
Again, lot of workaround, like: echo 0 > /proc/self/loginuid
...
About /proc/self/loginuid
under Linux
Please read interesting laolux's answer about this!
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
read lUid </proc/self/loginuid || die "Can't access procfile"
((lUid)) && die "You must be logged as root."
( This syntax avoid forks! )
But anyway
- script could be copied and edited
- depending on config/kernel, this kernel entry could be spoofed
- Sudoer could create
cron
entry for initiating special screen
session as root
. (cron
and screen
are not the only way for doing things like this! Just the first coming to my mind. )
sudo
user from removing the restriction from the script once you have put it in place? There is no difference between the root user logged in from a console and the root user accessing the system viasudo
. The foolproof solution woud be to simply uninstallsudo
.sudo
requires it to give you root access; that's just the default behavior everyone is familiar with.sudo
can be configured to allow you to do only very specific things, including not gain root access at all.