【问题标题】:How to restrict write access to a Linux directory by process attributes?如何通过进程属性限制对 Linux 目录的写访问?
【发布时间】:2012-09-29 02:50:53
【问题描述】:

我们遇到了这样一种情况,将日志目录的写访问权限限制为用户进程的特定子集是有利的。这些特定进程(例如,telnet 等)已被我们修改,以便在发生重大用户操作(如远程连接等)时生成日志记录。我们不希望用户通过复制和编辑现有日志记录来手动创建这些记录。

syslog 接近但仍允许用户生成虚假记录,SELinux 似乎是合理的,但作为无法管理的野兽而享有可怕的名声。

感谢任何见解。

【问题讨论】:

    标签: c linux security permissions


    【解决方案1】:

    以 root 身份运行本地日志记录守护程序。让它监听一个 Unix 域套接字(通常是 /var/run/my-logger.socket 或类似的)。

    编写一个简单的日志库,其中事件消息通过 Unix 域套接字发送到本地运行的守护进程。对于每个事件,还通过辅助消息发送流程凭据。详情请见man 7 unix

    当本地日志守护程序接收到消息时,它会检查辅助消息,如果没有,则丢弃该消息。凭据的uidgid 准确地告诉谁在运行发送日志请求的进程;这些都是由内核自己验证的,所以它们不能被欺骗(除非你有 root 权限)。

    聪明的地方来了:守护进程还检查凭据中的PID,并根据其值/proc/PID/exe。它是发送消息的进程正在执行的实际进程二进制文件的符号链接,这是用户无法伪造的。为了能够伪造消息,他们必须用自己的二进制文件覆盖实际的二进制文件,这需要 root 权限。

    (可能存在竞争条件:用户可能会制作一个执行相同操作的特殊程序,并立即exec()sa 他们知道允许的二进制文件。为了避免这种竞争,您可能需要让守护程序在之后响应检查凭据,并且日志记录客户端发送另一条消息(带有凭据),因此守护程序可以验证凭据仍然相同,并且/proc/PID/exe 符号链接没有更改。我个人会使用它来检查消息的真实性(通过记录器使用随机cookie请求事件确认,并让请求者用校验和和cookie响应事件校验和是否正确。包含随机cookie应该使得之前不可能将确认填充到套接字队列中exec().)

    使用pid,您还可以进行进一步检查。例如,您可以通过跟踪父级来跟踪进程父级以查看人类用户如何连接,直到您检测到通过 ssh 或控制台登录。这有点乏味,因为您需要解析 /proc/PID/stat/proc/PID/status 文件,并且不可移植。 OSX 和 BSD 有一个 sysctl 调用,可用于查找父进程 ID,因此您可以通过编写特定于平台的 parent_process_of(pid_t pid) 函数使其可移植。

    这种方法将确保您的日志记录守护进程确切知道 1) 日志记录请求来自哪个可执行文件,以及 2) 哪个用户(以及如何连接,如果您进行进程跟踪)运行了该命令。

    由于本地日志守护程序以 root 身份运行,它可以将事件记录到仅限 root 目录中的文件,和/或将消息转发到远程计算机。

    显然,这并不完全是轻量级的,但假设您每秒处理的事件少于十二个,那么日志记录开销应该完全可以忽略不计。

    【讨论】:

    • 使用守护进程有点重量级,我们使用 setuid 二进制文件检查 /proc/$PPID/exe 以确保日志记录请求仅来自我们有限的应用程序二进制文件子集
    • @GearoidMurphy:如果您使用相同的策略(使用 socketpair() 创建一个 Unix 域套接字,该套接字由描述符 3 中的 setuid 二进制文件继承),那么您完全可以。否则,你就有问题了。 PPID 幸存下来 exec()。这意味着,如果用户编写了一个 fork 的程序,执行任何允许的系统二进制文件,并且子进程等待 /proc/PPID/exe 更改然后执行 setuid 记录器二进制文件,则记录器二进制文件将认为该事件来自系统二进制文件.修复是一次对话(记录这个。这个?是的),凭证通过和检查两次。
    • 我不同意你的评价,一旦exec发生,控制权完全转移到系统二进制,父进程不能包含子进程的属性,也就是说,你的回答很详细,很接近最后的方法,所以你得到答案:)
    • @GearoidMurphy:考虑一个简单的程序,fork()s 是一个孩子。子进程中的PPID == 原始进程的PID。原始进程exec()s 是一个有效的系统二进制文件。它的PID 保持不变。子进程等到它看到/proc/PPID/exe 更改为指向系统二进制文件,然后exec()s 是setuid 记录器二进制文件。 (它甚至可以向父级发送SIGSTOPSIGTSTP 以暂停它。)您的记录器二进制文件看到/proc/PPID/exe 指向一个有效的系统二进制文件,并接受该事件。您是否需要一个完全执行此操作的示例程序,以便您可以测试/验证?
    【解决方案2】:

    通常有两种方法可以做到这一点。一,以root 运行这些进程并对目录进行写保护(主要出于历史目的而提及)。然后除了root之外没有人可以在那里写。第二个也是更安全的方法是将它们作为另一个用户(不是root)运行,并授予该用户(但没有其他人)对日志目录的写入权限。

    【讨论】:

    • 是的,我应该在答案中提到这一点,第一种方式基本上是出于历史原因提到的。在人们意识到设置 suid root/以 root 身份运行东西是一个坏主意之前,人们就是这样做的。
    • 我们使用了 suid 方法,但基于 /proc/$PPID/exe 限制了日志记录请求
    【解决方案3】:

    我们采用的方法是使用 setuid 二进制文件来允许对日志目录进行写访问,该二进制文件可由所有用户执行,但仅当父进程路径由 /proc 定义时才允许写入日志记录/$PPID/exe 匹配我们放置在系统上的修改后的二进制路径的子集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 2023-03-29
      • 1970-01-01
      • 2014-04-24
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多