AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 719003
Accepted
bicyclesonthemoon
bicyclesonthemoon
Asked: 2022-09-29 01:13:24 +0800 CST2022-09-29 01:13:24 +0800 CST 2022-09-29 01:13:24 +0800 CST

从 C 程序的 AWK 脚本调用 cat 时,SETUID 无效

  • 772

考虑以下说明我的问题的简化示例。
服务器的操作系统是 Debian 11 armhf。

我们在目录中/botm/test/:

drwx------ 2 b b 4096 Sep 27 19:27 hide
-rwsr-xr-x 1 b b 8260 Sep 27 19:54 test1
-rwsr-xr-x 1 b b 8264 Sep 27 19:58 test2
-rw-r--r-- 1 b b   56 Sep 27 19:52 test1.awk
-rw-r--r-- 1 b b  172 Sep 27 19:54 test1.c
-rw-r--r-- 1 b b  186 Sep 27 19:58 test2.c

可以看出,只有所有者b才能访问该目录/botm/test/hide。

我们现在是用户test
我们无法访问该文件/botm/test/hide/test.txt:

$ cat hide/test.txt
cat: hide/test.txt: Permission denied

好的。程序设置test1了test2SETUID 位。
所以即使我们是用户test,我们也可以像用户一样运行这些程序b。

首先,test2.c:

/* test2.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
  int r;
  r = execl("/usr/bin/cat","/usr/bin/cat","/botm/test/hide/test.txt", (char *)0);
  printf("%d\n",r);
  return r;
}
$ ./test2
hidden content
$ 

正如预期的那样,它有效。

现在, test1.c, test1.awk:

/* test1.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
  int r;
  r = execl("/usr/bin/mawk","/usr/bin/mawk","-f","/botm/test/test1.awk", (char *)0);
  printf("%d\n",r);
  return r;
}
# test1.awk
BEGIN {
  system("cat /botm/test/hide/test.txt");
};
$ ./test1
cat: /botm/test/hide/test.txt: Permission denied
$

令人惊讶的是,这不起作用。

我的期望:
如果我运行test1具有 SETUID 的程序,那么它应该像 user 一样运行b。
因此,如果程序调用/usr/bin/mawk,那么它也应该以 user 身份运行b。
因此,如果 awk 脚本随后调用cat,那么cat也应该以用户身份运行b。
因此cat应该能够访问/botm/test/hide/test.txt仅对 user 可用的内容b。
但这不会发生。

现在有一些真实的背景。
以上只是一个简化的例子。我有一个包含多个 C 和 AWK 程序的项目。从 C 程序调用 AWK 程序来处理一些文本并生成一些输出。这包括有时调用cat或其他系统工具。其中一些程序作为用户从 Apache 服务器运行,该用户www-data无权(也不应该拥有)这些程序创建的某些临时文件。这就是使用SETUID 的原因。这种工作流程在这个项目中被大量使用(从 2014 年开始)。

我现在将它从我的旧服务器(它工作的地方)移动到一个新的服务器(它不起作用的地方)。将项目更改为不依赖此机制将是一个非常大的重新设计,我现在不想这样做。

为什么当 C 程序(带有 SETUID)调用调用系统工具(cat,...)的 AWK 脚本时,SETUID 不被保留?
怎么做才能再次保存?
在以前版本的系统上它可以工作。

编辑添加:

我验证了 AWK 程序仍然可以访问隐藏文件,只有调用的东西system()没有。

所以我发现这种行为的原因是在使用system()(或getline使用管道)时mawk调用sh执行命令。
AWK 没有exec或类似的东西。

sh除非使用-p.
这是新的行为。这部分man sh在我的旧服务器上不存在:

           -p priviliged    Do not attempt to reset effective uid if it does not match uid. This is not set by default to help avoid incorrect usage by
                            setuid root programs via system(3) or popen(3).

因此,要使我的程序再次运行,我必须至少实现以下其中一项:

  • 默认情况下/usr/bin/sh不删除SETUID。
  • 使用for时使用makemawk或其他兼容的 AWK 解释器-p/usr/bin/shsystem()
  • 找到从 AWK 运行程序的不同方式
  • 重新设计所有程序以不依赖于此。例如,在 C、Perl 或 Python 中执行它们,它们确实具有不依赖于sh.

重新设计整个项目(以及其他一些也使用此工作流程的项目)将花费我目前没有的精力和时间,因此我真的需要以某种方式恢复完整的 SETUID 功能。

实际上,可以在 AWK 程序中轻松重新创建 的功能,但在我的项目中cat也可以调用其他工具: , , , , , , . 在大多数情况下,不使用 SETUID 调用它们是不可接受的。system()[ -fcatcpmkdirmvsleepwget

awk acl
  • 1 1 个回答
  • 54 Views

1 个回答

  • Voted
  1. Best Answer
    bicyclesonthemoon
    2022-09-29T13:14:37+08:002022-09-29T13:14:37+08:00

    在对类似问题的回答中:
    https
    ://unix.stackexchange.com/a/565254/543092 有一个建议可以使用setresuid()。

    因为在我的项目中,AWK 脚本总是从 C 程序中调用,这是我可以使用的解决方案。

    我做这样的事情:

    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    int main(int argc, char **argv)
    {
        uid_t euid;
        int r;
        euid = geteuid();
        r = setreuid(euid, euid);
        if (r != 0)
            return (r = errno);
        r = execl("/usr/bin/mawk","/usr/bin/mawk","-f","/botm/test/test1.awk", (char *)0);
        printf("%d\n",r);
    }
    

    这样“伪装”就完成了,并且sh不会知道之前有一个SETUID。一切正常。

    这是一个更好的解决方案,而不是sh总是表现得好像有-p. 如果我知道自己在做什么,它将保留我的 SETUID。

    我使用setreuid()而不是setresuid()那里建议的,因为:

    • setreuid()足够的
    • setresuid()是一个 GNU 扩展。
    • 2

相关问题

  • 根据第一个逗号之前的匹配删除重复行数

  • 在另一个文件之后逐行追加行

  • 如何删除两行之间的单行

  • 重新排列字母并比较两个单词

  • 多行文件洗牌

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve