简体   繁体   English

如何通过进程属性限制对Linux目录的写访问?

[英]How to restrict write access to a Linux directory by process attributes?

We've got a situation where it would be advantageous to limit write access to a logging directory to a specific subset of user processes. 我们遇到的情况是,将日志记录目录的写访问权限限制为特定的用户进程子集是有利的。 These particular processes (say, for example, telnet and the like) have been modified by us to generate a logging record whenever a significant user action takes place (like a remote connection, etc). 我们已经修改了这些特定的进程(例如,telnet等),以便在发生重要的用户操作时生成日志记录(如远程连接等)。 What we do not want is for the user to manually create these records by copying and editing existing logging records. 我们不想要的是用户通过复制和编辑现有的日志记录来手动创建这些记录。

syslog comes close but still allows the user to generate spurious records, SELinux seems plausible but has a terrible reputation of being an unmanageable beast. syslog接近但仍然允许用户生成虚假记录, SELinux似乎看似合理,但作为一个无法管理的野兽有一个可怕的声誉。

Any insight is appreciated. 任何见解都表示赞赏。

Run a local logging daemon as root. 以root身份运行本地日志记录守护程序。 Have it listen on an Unix domain socket (typically /var/run/my-logger.socket or similar). 让它监听Unix域套接字(通常是/var/run/my-logger.socket或类似的)。

Write a simple logging library, where event messages are sent to the locally running daemon via the Unix domain socket. 编写一个简单的日志记录库,通过Unix域套接字将事件消息发送到本地运行的守护程序。 With each event, also send the process credentials via an ancillary message. 对于每个事件,还通过辅助消息发送进程凭据。 See man 7 unix for details. 有关详细信息,请参阅man 7 unix

When the local logging daemon receives a message, it checks for the ancillary message, and if none, discards the message. 当本地日志记录守护程序收到消息时,它会检查辅助消息,如果没有,则丢弃该消息。 The uid and gid of the credentials tell exactly who is running the process that has sent the logging request; 凭证的uidgid确切地告诉谁正在运行已发送记录请求的进程; these are verified by the kernel itself, so they cannot be spoofed (unless you have root privileges). 这些都是由内核本身验证的,所以它们不能被欺骗(除非你有root权限)。

Here comes the clever bit: the daemon also checks the PID in the credentials, and based on its value, /proc/PID/exe . 这里有一个聪明的位:守护进程还检查凭证中的PID ,并根据其值/proc/PID/exe It is a symlink to the actual process binary being executed by the process that send the message, something the user cannot fake. 它是由发送消息的进程执行的实际进程二进制文件的符号链接,用户无法伪造。 To be able to fake a message, they'd have to overwrite the actual binaries with their own, and that should require root privileges. 为了能够伪造消息,他们必须用自己的二进制覆盖实际的二进制文件,这应该需要root权限。

(There is a possible race condition: a user may craft a special program that does the same, and immediately exec() sa binary they know to be allowed. To avoid that race, you may need to have the daemon respond after checking the credentials, and the logging client send another message (with credentials), so the daemon can verify the credentials are still the same, and the /proc/PID/exe symlink has not changed. I would personally use this to check the message veracity (by the logger asking for confirmation for the event, with a random cookie, and have the requester respond with both the checksum and the cookie whether the event checksum is correct. Including the random cookie should make it impossible to stuff the confirmation in the socket queue before exec() .) (可能存在竞争条件:用户可能会制作一个执行相同操作的特殊程序,并且立即exec()是他们知道允许的二进制文件。为避免该竞争,您可能需要在检查凭据后让守护程序响应,并且日志记录客户端发送另一条消息(带有凭据),因此守护程序可以验证凭据是否仍然相同,并且/proc/PID/exe符号链接没有更改。我个人会使用它来检查消息的真实性(通过记录器要求对事件进行确认,使用随机cookie,并让请求者用校验和和cookie响应事件校验和是否正确。包括随机cookie应该使得无法将确认填入套接字队列之前exec() 。)

With the pid you can do also further checks. 使用pid您还可以进一步检查。 For example, you can trace the process parentage to see how the human user has connected by tracking parents till you detect a login via ssh or console. 例如,您可以跟踪进程父级以通过跟踪父级来查看人类用户如何连接,直到您通过ssh或控制台检测到登录。 It's a bit tedious, since you'll need to parse /proc/PID/stat or /proc/PID/status files, and nonportable. 这有点单调乏味,因为您需要解析/proc/PID/stat/proc/PID/status文件,并且不可移植。 OSX and BSDs have a sysctl call you can use to find out the parent process ID, so you can make it portable by writing a platform-specific parent_process_of(pid_t pid) function. OSX和BSD有一个sysctl调用,您可以使用它来查找父进程ID,因此您可以通过编写特定于平台的parent_process_of(pid_t pid)函数使其可移植。

This approach will make sure your logging daemon knows exactly 1) which executable the logging request came from, and 2) which user (and how connected, if you do the process tracing) ran the command. 这种方法将确保您的日志记录守护程序确切地知道1)日志记录请求来自哪个可执行文件,以及2)哪个用户(以及如何执行进程跟踪时如何连接)运行该命令。

As the local logging daemon is running as root, it can log the events to file(s) in a root-only directory, and/or forward the messages to a remote machine. 当本地日志记录守护程序以root身份运行时,它可以将事件记录到仅root目录中的文件,和/或将消息转发到远程计算机。

Obviously, this is not exactly lightweight, but assuming you have less than a dozen events per second, the logging overhead should be completely neglible. 显然,这不是完全轻量级的,但假设每秒事件少于十几个,那么日志记录开销应该完全可以忽略不计。

Generally there's two ways of doing this. 通常有两种方法可以做到这一点。 One, run these processes as root and write protect the directory (mentioned mainly for historical purposes). 一,以root身份运行这些进程并写保护目录(主要用于历史目的)。 Then no one but root can write there. 那么除了root之外没有人可以在那里写。 The second, and more secure is to run them as another user (not root ) and give that user, but no one else, write access to the log directory. 第二个,更安全的是将它们作为另一个用户(不是root )运行,并为该用户提供写入访问日志目录的权限。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM