Uploaded image for project: 'ZABBIX FEATURE REQUESTS'
  1. ZABBIX FEATURE REQUESTS
  2. ZBXNEXT-195

Proposal: Privilege separation for ZABBIX agent

    XMLWordPrintable

    Details

    • Type: Change Request
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Agent (G)
    • Environment:
      UNIX-like operating systems

      Description

      The following is open for discussion. I would be glad to implement this and send patches
      for ZABBIX 1.8 and/or trunk and/or head, because I need the functionality provided by
      the implementation of this proposal and don't want to maintain this "out of tree". I also
      think that this might be useful for all users of ZABBIX who are monitoring log files.

      1. Purpose

      ZABBIX agent usually runs as an unprivileged user, which is a good thing to do. Alas,
      on UNIX systems, often log files are owned by a dedicated user (most likely, root) and
      have strict file permissions on them to prevent other users from reading these files.
      This makes it virtually impossible to practically monitor log files with ZABBIX without
      a rather large configuration change on all monitored hosts (i.e. touch file ownerships
      and permissions for all log files monitored).

      Privilege separation for ZABBIX agent aims to provide a simple, effective and proven
      mechanism to make log file monitoring within ZABBIX more usable.

      2. How it works

      Before ZABBIX agent drops it privileges to "zabbix" user, a special process will be
      forked and steadily run in the background, much like other agent pollers do. This
      process will not drop privileges and continue to run with super-user privileges.

      This process will not communicate with the network or other processes than the ZABBIX
      agent, and even this communication will be very restricted.

      Basically, the privileged process works in the following way:

      • Receive a request from ZABBIX agent to open a given file, i.e. /var/log/messages
      • Verify that the file is in a white list (new configuration parameter necessary)
      • Open the file with O_RDONLY flag to get a file descriptor
      • Pass this file descriptor back to ZABBIX agent
      • Close file descriptor (will stay open in the unprivileged parent process)

      It is then the responsibility of the unprivileged ZABBIX agent to work with and close this
      file descriptor accordingly, so it will not leak. Reading and processing the data from the
      log file will also be handled in the unprivileged process.

      The code running as UID 0 is kept as minimal as possible and consists only of a very few
      lines.

      3. The interface

      The communication between the unprivileged Agent and the privileged process will be
      performed via a socketpair(2) of type AF_LOCAL.

      The ZABBIX agent can use new API functions for file operations, e.g.:

      int zbx_priv_open(int priv_fd, const char *path, int mode)
      int zbx_priv_stat(int priv_fd, const char *path, struct stat *buf)
      int zbx_priv_lstat(int priv_fd, const char *path, struct stat *buf)

      The new functions try to mimic the behaviour of the original functions, returning error
      codes and setting errno just like the originals. The design goal is to make it possible
      to use the new functions as drop-in replacement - the only thing that needs to be taken
      care of ist the new first argument, priv_fd, which specifies the file descriptor to use
      for communicating with the privileged process.

      The changes in existing agent code will be as unintrusive as possible.

      4. Whitelist

      For security purposes, there should be a new configuration parameter which defines the
      file patterns allowed to be openened by the privileged process. This is to prevent a
      malicious GUI user to have ZABBIX agent return lines from "secret" files, e.g. /etc/shadow
      or private SSL keys.

      This pattern could be defined, for example, with:

      LogfileWhitelist = /var/log/*

      The privileged process will then match the filename given with each request against this
      whitelist, using shell globbing patterns (above example would match /var/log/messages and
      /var/log/mysql/mysqld.log but not /var/spool/cron/...). Multiple patterns can be given,
      delimeted by comma (",").

      Maybe a blacklist (LogfileBlacklist) configuration option would be a complimentary option,
      to disallow access to certain locations instead of using a white list, at the users
      choice.
      It is yet to be decided whether it is a good idea to use realpath(3) inside the privileged
      code to sanitize the given paths. On one hand, we must prevent that a malicious user can
      circumvent the white- or blacklist by using e.g. /var/log/../../etc/shadow as path or using
      symbolic links (e.g. /tmp/foo -> /etc/shadow). realpath(3) could be a remedy, but it has
      shown security flaws in the path in certain implementations.

      We could:

      • Check whether the path is a symbolic link and deny access if it is
      • Check whether the path contains /.. somewhere and deny access if it is

      This would be the most simplistic approach, maybe not as good as a check with realpath().

      5. Extendibility

      The privsep protocol can easily be extended to provide more privileged functions to the
      ZABBIX agent in a sane and secure way.

      For example, it could be used for data collection that requires root privileges (e.g. some
      stuff in /proc etc).

      6. Compatibility

      The code has been tested on Linux and BSD (Open-, Net- and FreeBSD). It will not work on
      non-UNIX-like OS (like Windows), and should work on most UNIX derivates that more or less
      comply to the POSIX standard (providing socketpair(2), select(2) and sendmsg(2)).

      Alas, I have no access to "big-iron" UNIX-derivates such as HP-UX, AIX or Solaris that
      have a compiler environment so I cannot test it on those platforms.

      7. Making it optional

      7.1 At compile-time

      A new option to configure should be introduced, namely --enable-privsep. When not specified,
      the privilege separation code will not be compiled and the zbx_priv_*() functions will act
      simply as wrappers around zbx_open() etc.

      7.2 At run-time

      Similar to OpenSSH's sshd, a new configuration item "UsePrivilegeSeperation" should be
      introduced which takes a boolean argument to define whether the agent should make use of
      the privsep feature (only available if compiled with --enable-privsep, of course).

      8. Open issues

      8.1 logrt[] items

      It will not be possible to use this with items of type logrt[] due to the use of opendir(3).
      I currently see no way to privsep opendir(), but one could emulate it using getdirentries(2).
      This would imply a rather intrusive change to process_logrt() in logfiles.c of ZABBIX agent.

      8.2 Testing

      As written above, I only have limited access to more "exotic" platforms (from the OSS point
      of view). As such, I can only test the code on Linux (RHEL/Centos, Ubuntu/Debian) and Open-
      BSD (probably Free- and NetBSD as well).

      Looking forward to any input and constructive criticism.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              jfischer J. Fischer
              Votes:
              7 Vote for this issue
              Watchers:
              7 Start watching this issue

                Dates

                Created:
                Updated: