【问题标题】:Why does SetSUID not work for shell script?为什么 SetSUID 不适用于 shell 脚本?
【发布时间】:2021-11-11 23:08:28
【问题描述】:

我正在尝试为 linux 上的普通用户创建一个执行程序,并设置了 SUID 位,因此作为参数传递给程序的任何命令都可以在 root 权限下执行。但是,当我尝试将其实现为 bash 脚本时,这不起作用,在 C 中实现时它可以工作。我想知道我对 shell 脚本做错了什么。代码如下

Shell 脚本:

#! /bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 <Command String>"
exit 1
fi
$@
#Also tried this, same result
#exec $@

执行:

root#: chmod 755 exec.sh 
root#: chmod u+s exec.sh
root#: ll exec.sh
-rwsr-xr-x 1 root root 75 Sep 19 16:55 exec.sh

regular_user$: ./exec.sh whoami
regular_user

C 程序:

#include <stdlib.h>
#include <stdio.h>
int main ( int argc, char *argv[] )
{
if ( argc < 2 ) {
    printf( "Usage: %s <Command String>\n", argv[0] );
    return 1;
}
else
{
    argv[argc]=NULL;
    //setuid(0);  //Works without these
    //setgid(0);
    int exit=execvp(argv[1], argv+1);
    return exit;
}
}

执行:

root#: gcc exec.c -o exec.obj
root#: chmod 755 exec.obj
root#: chmod u+s exec.obj
root#: ll exec.obj
-rwsr-xr-x 1 root root 6979 Sep 19 17:03 exec.obj

regular_user$: ./exec.obj whoami
root

两个文件具有相同的权限

-rwsr-xr-x 1 root root 75 Sep 19 16:55 exec.sh
-rwsr-xr-x 1 root root 6979 Sep 19 17:03 exec.obj

【问题讨论】:

  • sudo 有什么问题? ;)
  • 方法不对,应该配置sudo或者使用super
  • 实际上我们有很多带有 ldap auth 和 ldap sudo 组的 linux 服务器,但是这个特定的服务器运行一个 oracle 数据库,我们需要将其锁定,所以我需要一个简单的 hack 来让 DBA 运行有时以 root 身份执行命令。
  • 您可以在该机器上拥有一个特殊的/etc/sudoers,或者安装super 并让您的DBA 使用它。
  • 我决定将 sudo 与本地 sudoers 文件一起使用,我也得到了为什么它没有询问的答案。谢谢大家。

标签: linux bash shell


【解决方案1】:

它记录在execve(2)

Linux 会忽略脚本上的 set-user-ID 和 set-group-ID 位。

IIRC,setuid 脚本将是一个重大的安全漏洞

this question

您可以配置 sudo 以避免询问密码 - 请参阅 sudoers(5)(或使用 super

您还可以编写一个简单的 C 程序来包装您的 shell 脚本,并将其设置为 setuid。

【讨论】:

  • 解决方法:使用sudo
  • 我决定使用 sudo 因为它允许更细粒度的控制,但是我只是想知道为什么 suid 方法不起作用。感谢您的回答。
【解决方案2】:

试试

regular_user$: sudo "./exec.sh whoami"

【讨论】:

  • 请详细说明答案。
【解决方案3】:

原因由 RedHat https://access.redhat.com/solutions/124693 解释:

在执行具有 setuid 位的 shell 脚本时(例如,rwsr-xr-x 的权限),脚本以执行它们的用户身份运行,而不是以拥有它们的用户身份运行。这与二进制文件(例如 /usr/bin/passwd)的 setuid 处理方式相反,二进制文件以拥有它们的用户身份运行,而不管哪个用户执行它们。

为了解决这个问题,我编写了一个脚本实用程序,它将脚本调用转换为本地二进制文件:

#!/bin/bash

# https://access.redhat.com/site/solutions/124693

if [ $# != 1 ]; then
    echo "Please, provide script file name." >&2
    exit 1
fi

if [ ${EUID} != 0 ]; then
    echo "Only root can run this script." >&2
    exit 1
fi

SCRIPT_FILE=$1

if [ ! -f "${SCRIPT_FILE}" ]; then
    echo "Script file not found." >&2
    exit 1
fi

SCRIPT_BASE_FILE=$(basename ${SCRIPT_FILE})

C_TEMPLATE=$(cat << DELIMITER
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    char *cwd;
    char exe_file[PATH_MAX];
    char script_file[PATH_MAX];

    readlink("/proc/self/exe", exe_file, PATH_MAX);
    cwd = dirname(exe_file);
    sprintf(script_file, "%s/${SCRIPT_BASE_FILE}", cwd);

    setuid(0);
    system(script_file);
    return 0;
}
DELIMITER
)

C_FILE="${SCRIPT_FILE}.c"
EXE_FILE="${SCRIPT_FILE}.x"

   echo "${C_TEMPLATE}" > "${C_FILE}" \
&& gcc "${C_FILE}" -o "${EXE_FILE}" \
&& chown root:root "${EXE_FILE}" \
&& chmod 4755 "${EXE_FILE}" \
&& rm "${C_FILE}" \
&& echo "Setuid script executable created as \"${EXE_FILE}\"."

【讨论】:

    猜你喜欢
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2014-11-05
    • 2015-11-13
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多