【问题标题】:Shell script - Sudo-permissions lost over timeShell 脚本 - Sudo 权限随着时间的推移而丢失
【发布时间】:2011-08-17 12:42:00
【问题描述】:

我制作了一个简单的 bash 脚本,它需要在整个脚本中保持超级用户权限。不幸的是,但可以理解的是,当sleep 发生时,脚本会失去其sudo-eleved 权限。对我不好:

sudo echo "I am sudo!" # Asks for passwords
sleep(60)
sudo echo "I am sudo!" # Need to enter password again.

我曾考虑将sleep 替换为保持sudo 活动的while 循环,但我很确定有更好的选项可让sudo-permissions 保留在整个脚本中?

谢谢

【问题讨论】:

  • 为什么不让用户运行sudo

标签: bash shell ubuntu sudo


【解决方案1】:

sudo 的灵活性被广泛低估了。这会导致非常糟糕的做法(例如sudo su - canon-ball 手术方法)。

更好的方法是专门允许您打算允许的命令不使用密码

phill = NOPASSWD: /bin/ls, /usr/bin/lprm

您可以选择为特定主机上的特定用户执行此操作,该主机以特定管理员用户身份运行。您甚至可以阻止用户将 shell 转义符作为参数传递。您可以使 sudo 阻止启动的程序动态执行进一步的应用程序等。您将需要read the man-page for sudoers (and be sure to read the procedures for editing this special file!)

这里有一点小事,(from here):

User_Alias     OPERATORS = joe, mike, jude
Runas_Alias    OP = root, operator
Host_Alias     OFNET = 10.1.2.0/255.255.255.0
Cmnd_Alias     PRINTING = /usr/sbin/lpc, /usr/bin/lprm

OPERATORS ALL=ALL
#The users in the OPERATORS group can run any command from any terminal.

linus ALL=(OP) ALL
# The user linus can run any command from any terminal as any user in the OP group (root or operator).

user2 OFNET=(ALL) ALL
# user user2 may run any command from any machine in the OFNET network, as any user.

user3 ALL= PRINTING
# user user3 may run lpc and lprm from any machine.

go2linux ALL=(ALL) ALL
# user go2linux may run any command from any machine acting as any user. (like Ubuntu)

 If you want not to be asked for a password use this form
go2linux ALL=(ALL) ALL NO PASSWD: ALL

【讨论】:

    【解决方案2】:

    严格在脚本中工作(而不是编辑 sudoers 文件或通过 sudo ./script.sh 调用脚本),这是我认为最干净的方法。

    startsudo() {
        sudo -v
        ( while true; do sudo -v; sleep 50; done; ) &
        SUDO_PID="$!"
        trap stopsudo SIGINT SIGTERM
    }
    stopsudo() {
        kill "$SUDO_PID"
        trap - SIGINT SIGTERM
        sudo -k
    }
    

    基本上,这定义了一对用于启用和禁用 sudo 模式的函数。在运行使用 sudo 的代码之前调用 startsudo 会使用 sudo 进行身份验证,派生一个后台 sudo 刷新循环,保存循环的 PID,并设置一个信号陷阱以在按下 Ctrl+C 时停止 sudo 模式。调用 stopsudo 会终止循环,清除信号陷阱,并使之前使用 sudo 的身份验证无效。

    将这些函数复制到您的脚本后,像这样使用它们。

    startsudo
    echo "Sudo mode is active."
    # whatever you want to do with sudo
    stopsudo
    

    我要感谢 @karl 内联 sudo-refreshing 循环的简单性,感谢 @sehe 指出如果没有正常终止循环,应该使用信号陷阱来终止循环。这两个想法都改进了my btrfs backup script,它使用 sudo-refreshing 循环来避免在子卷的备份时间超过 sudo 的超时时间后重新提示用户。

    【讨论】:

      【解决方案3】:

      您可以通过添加到 /etc/sudoers 来调整此超时时间

      Defaults timestamp_timeout=#Number of minutes
      

      但运行起来要容易得多

      sudo ./worker.sh
      

      【讨论】:

        【解决方案4】:

        这里有一个解决方法:

        sudo echo "I am sudo!" # Asks for passwords
        ( while true; do sudo -v; sleep 40; done ) &   # update the user's timestamp
        sudoPID=$!
        # ...
        sleep(60)
        sudo echo "I am sudo!" # Need to enter password again.
        kill -TERM $sudoPID
        sudo -k  # invalidate the user's timestamp at end of script (does not require a password)
        

        【讨论】:

        • 如果你打算这样破解它,至少要确保 kill 和 sudo -k 在你的脚本中注册为信号陷阱。这要求存在较大的安全漏洞。 (使用 Ctrl-C 中止脚本,sudo 默默地无限期地保持活动状态)
        【解决方案5】:

        这是我的方式:

        #!/bin/sh
        echo "Working..."
        # add you pass
        echo "yourpass" >> file.pass ;sleep 5 
        # Check if root
        if [ `cat file.pass | sudo -S su root -c whoami` != "root" ]; then
        echo "Not running as root. Exiting..."
        sleep 2
        echo "Cleaning..."
        sleep 1
        srm file.pass
        echo "Cleaned"
        exit 0
        else
        echo "Running as root. Good"
        sleep 2
        # and run any sudo with
        cat file.pass | sudo -S su root -c ls #<any command>
        fi
        
        sleep 5
        echo `cat file.pass | sudo -S su root -c whoami` "say bay bay"
        # if pass no longer need
        srm file.pass
        echo "End session :)"
        exit 0
        

        【讨论】:

        • 这看起来像是一个有效的答案,但将用户的密码保存到文件中似乎相当不安全。另外,srm 命令有什么作用?我的 Linux 发行版没有它。
        【解决方案6】:

        一次性获得root权限:

        sudo su -
        # What I need to do with root 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-17
          • 2014-02-04
          • 1970-01-01
          • 2019-11-17
          • 2021-12-24
          • 2021-07-22
          • 1970-01-01
          相关资源
          最近更新 更多