如何在shell脚本中放弃root特权?


14

OpenVPN中的“ --up”选项通常用于路由等。因此,在OpenVPN放弃root特权以无人运行的情况下进行处理。但是,我正在调用需要以非特权用户身份运行的shell脚本。

我怎么做?我研究了Drop Process Privileges,特别是多项式和tylerl的答案,但是我不知道如何实现。我在Centos 6.5中工作,并且suid被阻止为“ chmod u + s”和“ setuid()”。

有一个OpenVPN插件(“ openvpn-down-root.so”),该插件使“ --down”选项调用的脚本能够以root用户身份运行。可能存在等效项,例如“ openvpn-up-user.so”,但我没有找到它。

编辑0

根据Nikola Kotur的回答,我已经安装了Ian Meyer的runit-rpm。尽管chpst命令在终端中有效,但在up脚本中,它失败并显示“找不到命令”。起作用的是“ sudo chpst”以及设置适当的显示和语言。请参阅为什么我的终端无法正确输出unicode字符?鉴于此,up脚本需要以下四行:

LANG="en_US.UTF-8"; export LANG
GDM_LANG="en_US.UTF-8"; export GDM_LANG
DISPLAY=:0; export DISPLAY
sudo chpst -u user -U user /home/user/unprivileged.sh &

编辑1

根据0xC0000022L的评论,我发现“ sudo -u用户”和“ sudo chpst -u用户-U用户”一样有效:

LANG="en_US.UTF-8"; export LANG
GDM_LANG="en_US.UTF-8"; export GDM_LANG
DISPLAY=:0; export DISPLAY
sudo -u user /home/user/unprivileged.sh &

我将研究man sudoers并更新是否/当我独自一个人工作时更新。


@ user66229留下的评论:“我可以建议您浏览sourceforge.net/p/openvpn/mailman并订阅您认为最合适的列表。”
slm

@ user66229谢谢。但是我不相信这是一个特定于OpenVPN的问题。您为什么这么认为呢?
mirimir 2014年

Answers:



11

只覆盖runit和sudo会导致很多错误。实际上,有诸如runit之类的一整套工具集,以及用于实现此目的的广泛工具选择,它们的设计目的是:

  • Daniel J. Bernstein的daemontools具有setuidgid

    setuidgid用户/home/user/unprivileged.sh
  • 亚当·桑普森(Adam Sampson)的freedt有setuidgid

    setuidgid用户/home/user/unprivileged.sh
  • Bruce Guenter的daemontools-encore具有setuidgid

    setuidgid用户/home/user/unprivileged.sh
  • Gerrit Pape的特权有chpst

    chpst -u用户/home/user/unprivileged.sh
  • 韦恩·马歇尔(Wayne Marshall)的表演有runuid

    runuid用户/home/user/unprivileged.sh
  • 洛朗·贝科特(Laurent Bercot)的s6具有s6-setuidgid

    s6-setuidgid用户/home/user/unprivileged.sh
  • 我的鼻子有setuidgid

    setuidgid用户/home/user/unprivileged.sh

他们不会混入添加特权的不同任务,也永远不会陷入交互模式。

您的上涨,对问题多一点你忘记有sbin,以及bin在你的PATH,顺便说一句。

进一步阅读


3

删除特权并运行其他脚本的脚本(但在这里我只是使其自身运行):

#!/bin/sh

id=`id -u`
safeuser="nobody"

if [ $id = "0" ]
then
         # we're root. dangerous!
        sudo -u $safeuser $0
else
    echo "I'm not root"
    id
fi

例:

root@n3:/tmp/x# id
uid=0(root) gid=0(root) группы=0(root)
root@n3:/tmp/x# ./drop.sh
I'm not root
uid=65534(nobody) gid=65534(nogroup) группы=65534(nogroup)

虽然对某些命令使用“ sudo -u用户”,但它不能为我的目的提供足够的用户环境。而且,尽管“ su -l用户”在终端中可以正常工作,但在脚本中却没有任何作用。我想这是一项安全功能。因此,似乎我只剩下安装runit了。
mirimir

1
@mirimir:为什么?/etc/sudoers允许非常具体地说明可以将哪些环境变量传达给运行它的程序sudo,依此类推。man sudoers。坦白说,无论sudo是仅用于sudo su -或切换用户上下文的人,都不知道该程序的背后是什么,以及您可以为单个程序,用户,主机等锁定多少东西……
0xC0000022L 2014年

@ 0xC0000022L谢谢。我又看了一下sudo。是的,“ sudo -u用户”以及显示和语言也可以使用。
mirimir 2014年

1
说到危险-你不能信任$0; 调用者可以将脚本设置$0为实际上他们想要的任何形式。并使用更多的报价。
Charles Duffy

2
...如果您的脚本$0/directory/name with spaces/script(请记住,即使用户使用的of exec -a somename yourscript调用,用户也可以在自己拥有的位置创建任意符号链接),那么您将获得和并作为单独的参数传递给命令。yourscript$0somenamesudo -u nobody /directory/name with spaceswithspaces
Charles Duffy

1

关于什么:

sudo -Eu <user> <command>

您在先前的评论中抱怨了环境,因此您也可以比较输出之间的差异:

sudo -u <user> printenv
sudo -Eu <user> printenv

1

在Linux上,您可以使用runusersetpriv如果不需要PAM会话(均来自util-linux):

runuser -u USER [--] COMMAND [ARGUMENTS...]

setpriv --reuid=1000 --regid=1000 --init-groups COMMAND [ARGUMENTS...]  # Like su/runuser/sudo
setpriv --reuid=1000 --regid=1000 --clear-groups COMMAND [ARGUMENTS...]  # Like daemontools setuid(8)

su手册页:

su主要用于非特权用户,对于特权用户(例如,由root执行的脚本),推荐的解决方案是使用不需要身份验证的非set-user-ID命令runuser(1),并提供单独的PAM配置。如果根本不需要PAM会话,那么推荐的解决方案是使用命令setpriv(1)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.