如果我运行一个sudo
命令,它会要求我输入密码,但是在接下来的几分钟的终端会话中,它会允许我运行sudo
命令而不要求我输入密码,因为它会缓存我被允许的信息。
这很方便,而且我发现它相当方便,所以我不想通过每次都要求输入密码而不是缓存来解决这个问题。
但我最近发现一些相当令人担忧的事情,例如如果我创建一个这样的小脚本:
#!/bin/bash
sudo rm -rf /
在我执行任何sudo
命令之前,我在终端中以普通用户身份执行它,然后一切正常,并且按预期工作,它会提示我输入sudo
密码。但是,如果我要sudo
在执行此脚本之前运行命令没有 sudo
它会缓存sudo
该会话中几分钟内不应要求输入密码的命令,然后即使我没有授予脚本sudo
权限,它也不会提示我输入密码,并且脚本将被允许执行sudo
它想要的任何命令。
现在我不是那种在不知道脚本内容的情况下执行许多脚本的人,但有时我必须从受信任位置获取的脚本安装东西,但我不确定脚本中是否没有任何不好的东西,所以我希望它不会劫持sudo
授予我的终端会话的能力。
所以我的问题是,是否可以让我能够运行sudo
命令,它会为我缓存它,但如果我运行一个脚本不是sudo
脚本不能劫持该功能吗?我知道我执行脚本基本上与我按照脚本中的顺序执行命令相同,但是有没有办法巧妙地让它以略有不同的方式运行,或者对我sudo
运行的脚本进行限制?
但实际上,我没有运行的任何东西都不sudo
应该能够运行sudo
。包括命令。如果他们只是劫持了缓存的能力,那就是……
我正在运行带有 GNOME 3.18 的 Ubuntu GNOME 15.10。
我对如何做到这一点有一个建议,但我不知道这样做的实用性:我是否可以这样做,当我执行一个命令并开始运行它时,它会将其记录到一个文件中(就像对所有终端命令所做的那样,尽管可能有点太晚了 - 使用该history
命令)然后在sudo
运行时它会检查我是否在终端中执行了该命令(通过使用我执行时记录的日志),如果没有,则假定这不是我执行的,所以它会提示我输入密码?
答案1
你可以运行
sudo -k
在您运行脚本之前。它将清除缓存的凭据,然后下次sudo
将再次询问您的密码。
这是实现您想要做的事情的一种方法(我认为)。
将您的 sudo 移到其他地方:
mv /usr/bin/sudo /usr/bin/sudo_real
将以下内容放入
usr/bin/sudo
:#!/bin/bash -i # Allows 'sudo' to be run with cached credentials from the command line, # but clears the cache if run from within a script. # Get the last command executed manually from the history LAST_COMMAND=`history | tail -n 1 | cut -c 8-` if [[ "${LAST_COMMAND}" == "sudo "* ]]; then # The last command was 'sudo' - i.e. the user ran sudo sudo_real "$@" else # The last command was NOT sudo - so this sudo was called from within a script. # Force the cached credentials to be cleared. sudo_real -k "$@" fi
创建新的
/usr/bin/sudo
可执行文件:chmod a+x /usr/bin/sudo
sudo
通过将其放入以下位置,从 shell 运行 bash 时更新 bash 历史记录的别名~/.bashrc
:alias sudo="history -a;sudo"
现在,当您运行它时,sudo ...
它会将放入sudo ...
bash 历史记录中,并且脚本会找到它并运行sudo_real
。但是当另一个脚本运行时sudo
,它将不会出现在历史记录中,并且它会调用sudo_real -k
。
我认为这是非常危险的,我个人宁愿承担风险,或者对我不信任的脚本使用新的 shell :-)
答案2
我对这个问题的立场是这样的:如果你不确定在你的凭据尚未超时的情况下是否可以以 root 权限运行应用程序,那么只需完全禁用超时,将其设置为 0。具体来说,你需要在你的/etc/sudoers
文件中进行以下设置:
Defaults timestamp_timeout=0
手册页定义它如下:
timestamp_timeout
Number of minutes that can elapse before sudo will ask
for a passwd again. The timeout may include a frac‐
tional component if minute granularity is insufficient,
for example 2.5. The default is 15. Set this to 0 to
always prompt for a password. If set to a value less
than 0 the user's time stamp will never expire. This
can be used to allow users to create or delete their
own time stamps via “sudo -v” and “sudo -k” respec‐
tively.
但是,如果你想要谨慎,你可以在.bashrc
sudo_check()
{
real_path="$( realpath $1 )"
file "$real_path" | grep -q -i script
if [ $? -eq 0 ]; then
grep -q 'sudo' "$real_path" && \
{ echo '>>> ALERT: Its a script that requests sudo';
echo ' resetting sudo timestamp';
echo 'please rerun with sudo appended ';
}
sudo -k
else
sudo "$@"
fi
}
此函数将检查脚本是否包含对的调用sudo
并提醒您。下面是我在脚本上运行该函数的示例(这是我的登录屏幕背景更换器顺便一提 )
$ sudo_check sergrep/chgreeterbg.sh
>>> ALERT: Its a script that requests sudo
resetting sudo timestamp
答案3
如何区分脚本和可执行二进制命令?
当然,你可以考虑定义一个名为的函数sudo
,在运行实际的二进制文件之前进行健全性检查,但是
- 由于脚本可以有任何名称,那么如果脚本的名称为 会怎么样
ls
?因此检查类似这样的扩展名.sh
不会有帮助 - 另外,将 shebang 读作脚本的第一行也无济于事,因为脚本可以在没有 shebang 的情况下运行
我认为,如果您对此过于偏执,您可以考虑通过创建别名来完全禁用密码缓存,例如:
alias sudo='sudo -k'
并将其放入你的~/.bashrc
。
答案4
如果您的版本至少为 1.8.21 sudo
,则需要将其设置timestamp_type
为ppid
,而不是默认的tty
。
默认情况下,sudo 将在每个终端上“缓存凭据”。此设置将sudo
仅在调用过程相同时才重用它们。您运行的任何脚本都将具有与您的 shell 不同的 PID,并且将无法使用您的授权。
sudoers
具体来说,您的文件中需要包含以下行:
Defaults timestamp_type=ppid
更多详情请参阅手动的。