PK0*_*001 25 bash root sudo shell-script
我是这里的新手,也是 bash/linux 的新手。
我的老师给了我一项作业,只允许在您“真正”是 root 而不是在使用 sudo 时运行脚本。经过两个小时的搜索和尝试,我开始认为他在欺骗我。只允许 root 很容易,但如何排除使用 sudo 运行它的用户?
这就是我所拥有的:
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script."
exit
fi
Run Code Online (Sandbox Code Playgroud)
Ark*_*zyk 23
我能想到的唯一方法是检查SUDO_*sudo 设置的环境变量之一:
#!/usr/bin/env sh
if [ "$(id -u)" -eq 0 ]
then
if [ -n "$SUDO_USER" ]
then
printf "This script has to run as root (not sudo)\n" >&2
exit 1
fi
printf "OK, script run as root (not sudo)\n"
else
printf "This script has to run as root\n" >&2
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
请注意,这个解决方案当然不是面向未来的,因为您无法阻止任何人在运行脚本之前设置变量:
$ su
Password:
# SUDO_USER=whatever ./root.sh
This script has to run as root (not sudo)
# ./root.sh
OK, script run as root (not sudo)
Run Code Online (Sandbox Code Playgroud)
Jef*_*ler 19
另一种选择是检查祖父进程名称是否为“sudo”:
#!/bin/sh
if [ "$(id -u)" -eq 0 ]
then
if [ $(ps -o comm= -p $(ps -o ppid= -p $$)) = "sudo" ]
then
echo Running under sudo
else
echo Running as root and not via sudo
fi
else
echo Not running as root
fi
Run Code Online (Sandbox Code Playgroud)
lao*_*lux 13
有关哪个用户登录的信息在 中可用/proc/self/loginuid。由于评论而编辑 :该文件似乎并不存在于所有系统上。我进行了测试,它在 Centos 6、Fedora 32、Fedora 33 和 Ubuntu 20.04 上都可用,所有这些都在标准的 x86_64 设置中。
如果我们以用户身份登录,然后使用sudo或su成为 root,这不会改变/proc/self/loginuid,它将是一些非零值。如果我们直接以 root 身份登录,那么cat /proc/self/loginuid将返回0. 请注意,此文件不能修改,即使是 root 也不能这样做。 由于 Stéphane Chazelas 的评论而进行编辑 :Root 可以使用echo 0 > /proc/self/loginuid. 但是,这可以通过设置来防止auditctl --loginuid-immutable。
检查真正根(如果auditctl --loginuid-immutable设置)的脚本可能看起来像
#!/bin/bash
loginuid=$(cat /proc/self/loginuid)
echo $loginuid
if [[ $loginuid -ne 0 ]]; then
echo "You did not log in as root."
exit
fi
Run Code Online (Sandbox Code Playgroud)
sudo在rootbash 脚本中使用?不幸的是,没有抵抗的方式......请仔细阅读最后一段
一旦您授予某人 root 访问权限,他们就可以做任何事情,包括编辑您的脚本!!
例如,如果用户点击sudo su -,则变量SUDO_*不再存在......
pstreesudo在整个当前树中搜索存在的更简单方法似乎使用pstree:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pstree -s $$ | grep -q '\bsudo\b' && die "Can't be run under sudo"
Run Code Online (Sandbox Code Playgroud)
ps而已,你可以遍历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
Run Code Online (Sandbox Code Playgroud)
sudo如果 sudo 命令被重命名或复制,那么不是查找命令名称,而是在整个父树中查找UID。所以脚本与以前的相同,但UID >= 1000在父树中搜索:
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
Run Code Online (Sandbox Code Playgroud)
正确地说,避免使用固定的静态数据,使用UID_MINfrom /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
Run Code Online (Sandbox Code Playgroud)
sudo无论如何使用执行此操作的解决方法但这一切都有些脆弱:
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pstree -s $$ | grep -q '\bsudo\b' && die "Can't be run under sudo"
Run Code Online (Sandbox Code Playgroud)
现在打Ctrl+ a,然后d被分离。键入exit或点击Ctrl+d以在用户模式下返回...
然后简单地:
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
Run Code Online (Sandbox Code Playgroud)
现在,您将登录到root 登录会话。没有任何 sudo 的痕迹。
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
Run Code Online (Sandbox Code Playgroud)
正如chepner正确评论的那样:sudo 是为了提供对特定工具的特定访问权限:
sudo 不需要它为您提供 root 访问权限;这只是每个人都熟悉的默认行为。sudo 可以配置为只允许你做非常具体的事情,包括根本没有获得 root 访问权限 – chepner
在使用脆弱的解决方法之前,请注意正确配置它们!
看:
apropos sudo
Run Code Online (Sandbox Code Playgroud)
并仔细阅读
man sudo.conf
man sudoers
Run Code Online (Sandbox Code Playgroud)
logname看看正确的Stéphane Chazelas 的答案!这可能是家庭作业的最佳答案!
同样,很多解决方法,例如:echo 0 > /proc/self/loginuid...
/proc/self/loginuid下的Linux请阅读有趣的laolux 对此的回答!
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."
Run Code Online (Sandbox Code Playgroud)
(此语法避免分叉!)
但无论如何
cron用于启动特殊screen会话的条目root。(cron并且screen不是做这样的事情的唯一方法!只是我想到的第一个。)