плагин политики безопасности sudo по умолчанию (default sudo security policy plugin)
Безопасность (Security)
Limitations of the
'!' operator
It is generally not effective to 'subtract' commands from ALL
using
the '!' operator. A user can trivially circumvent this by copying
the desired command to a different name and then executing that.
For example:
bill ALL = ALL, !SU, !SHELLS
Doesn't really prevent bill
from running the commands listed in SU
or SHELLS since he can simply copy those commands to a different
name, or use a shell escape from an editor or other program.
Therefore, these kind of restrictions should be considered advisory
at best (and reinforced by policy).
In general, if a user has sudo ALL
there is nothing to prevent them
from creating their own program that gives them a root shell (or
making their own copy of a shell) regardless of any '!' elements in
the user specification.
Security implications of
fast_glob
If the fast_glob option is in use, it is not possible to reliably
negate commands where the path name includes globbing (aka
wildcard) characters. This is because the C library's fnmatch(3)
function cannot resolve relative paths. While this is typically
only an inconvenience for rules that grant privileges, it can
result in a security issue for rules that subtract or revoke
privileges.
For example, given the following sudoers file entry:
john ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\
/usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
User john
can still run /usr/bin/passwd root if fast_glob is
enabled by changing to /usr/bin and running ./passwd root instead.
Preventing shell escapes
Once sudo
executes a program, that program is free to do whatever
it pleases, including run other programs. This can be a security
issue since it is not uncommon for a program to allow shell
escapes, which lets a user bypass sudo
's access control and
logging. Common programs that permit shell escapes include shells
(obviously), editors, paginators, mail and terminal programs.
There are four basic approaches to this problem:
restrict Avoid giving users access to commands that allow the user
to run arbitrary commands. Many editors have a
restricted mode where shell escapes are disabled, though
sudoedit
is a better solution to running editors via
sudo
. Due to the large number of programs that offer
shell escapes, restricting users to the set of programs
that do not is often unworkable.
intercept
Many systems that support shared libraries have the
ability to override default library functions by pointing
an environment variable (usually LD_PRELOAD) to an
alternate shared library. On such systems, sudo
's
intercept functionality can be used to transparently
intercept an attempt to run a new command, allow or deny
it based on sudoers rules, and log the result. For
example, this can be used to restrict the commands run
from within a privileged shell. Note, however, that this
applies only to dynamically-linked executables.
Statically-linked executables and executables running
under binary emulation are not affected. Also, most
shells support built-in commands and the ability to read
or write sensitive files that cannot be intercepted by
sudo
.
Currently, sudo
's intercept functionality only works for
programs that use the execve
() system call to run the new
command. This may be expanded in a future release of
sudo
. Because most dynamic loaders ignore LD_PRELOAD (or
the equivalent) when running set-user-ID and set-group-ID
programs, sudoers
will not permit such programs to be run
in intercept mode.
The intercept feature is known to work on Solaris, *BSD,
Linux, macOS, HP-UX 11.x and AIX 5.3 and above. It
should be supported on most operating systems that
support the LD_PRELOAD environment variable. Check your
operating system's manual pages for the dynamic linker
(usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to
see if LD_PRELOAD is supported.
To enable intercept mode on a per-command basis, use the
INTERCEPT tag as documented in the User Specification
section above. Here is that example again:
chuck research = INTERCEPT: ALL
This allows user chuck
to run any command on the machine
'research' in intercept mode. Any commands run via shell
escapes will be validated and logged by sudo
. If you are
unsure whether or not your system is capable of
supporting intercept, you can always just try it out and
check whether or not external commands run via a shell
are logged when intercept is enabled.
log There are two separate but related ways to log additional
commands. The first is to enable I/O logging using the
log_output flag. This will log the command's output but
will not create an event log entry when the additional
command is run. The second is to enable the log_children
flag in sudoers which will create an event log entry
every time a new command is run. If I/O logging is also
enabled, the log entry will include a time offset into
the I/O log to indicate when the command was run. This
offset can be passed to the sudoreplay(8) utility to
replay the I/O log at the exact moment when the command
was run. The log_children flag uses the same mechanism
as intercept (see above) and has the same limitations.
noexec sudo
's noexec functionality can be used to prevent a
program run by sudo
from executing any other programs.
On most systems, it uses the same mechanism as intercept
(see above) and thus the same caveats apply. The noexec
functionality is capable of blocking execution of
commands run via the execl
(), execle
(), execlp
(),
exect
(), execv
(), execve
(), execveat
(), execvP
(),
execvp
(), execvpe
(), fexecve
(), popen
(), posix_spawn
(),
posix_spawnp
(), system
(), and wordexp
() functions. On
Linux, a seccomp
() filter is used to implement noexec.
On Solaris 10 and higher, noexec uses Solaris privileges
instead of the LD_PRELOAD environment variable.
To enable noexec for a command, use the NOEXEC tag as
documented in the User Specification section above. Here
is that example again:
aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
This allows user aaron
to run /usr/bin/more and
/usr/bin/vi with noexec enabled. This will prevent those
two commands from executing other commands (such as a
shell). If you are unsure whether or not your system is
capable of supporting noexec you can always just try it
out and check whether shell escapes work when noexec is
enabled.
Note that restricting shell escapes is not a panacea. Programs
running as root are still capable of many potentially hazardous
operations (such as changing or overwriting files) that could lead
to unintended privilege escalation. In the specific case of an
editor, a safer approach is to give the user permission to run
sudoedit
(see below).
Secure editing
The sudoers
plugin includes sudoedit
support which allows users to
securely edit files with the editor of their choice. As sudoedit
is a built-in command, it must be specified in the sudoers file
without a leading path. However, it may take command line
arguments just as a normal command does. Wildcards used in
sudoedit command line arguments are expected to be path names, so a
forward slash ('/') will not be matched by a wildcard.
Unlike other sudo
commands, the editor is run with the permissions
of the invoking user and with the environment unmodified. More
information may be found in the description of the -e
option in
sudo(8).
For example, to allow user operator to edit the 'message of the
day' file:
operator sudoedit /etc/motd
The operator user then runs sudoedit
as follows:
$ sudoedit /etc/motd
The editor will run as the operator user, not root, on a temporary
copy of /etc/motd. After the file has been edited, /etc/motd will
be updated with the contents of the temporary copy.
Users should never be granted sudoedit
permission to edit a file
that resides in a directory the user has write access to, either
directly or via a wildcard. If the user has write access to the
directory it is possible to replace the legitimate file with a link
to another file, allowing the editing of arbitrary files. To
prevent this, starting with version 1.8.16, symbolic links will not
be followed in writable directories and sudoedit
will refuse to
edit a file located in a writable directory unless the
sudoedit_checkdir option has been disabled or the invoking user is
root. Additionally, in version 1.8.15 and higher, sudoedit
will
refuse to open a symbolic link unless either the sudoedit_follow
option is enabled or the sudoedit command is prefixed with the
FOLLOW tag in the sudoers file.
Time stamp file checks
sudoers
will check the ownership of its time stamp directory
(/run/sudo/ts by default) and ignore the directory's contents if it
is not owned by root or if it is writable by a user other than
root. Older versions of sudo
stored time stamp files in /tmp; this
is no longer recommended as it may be possible for a user to create
the time stamp themselves on systems that allow unprivileged users
to change the ownership of files they create.
While the time stamp directory should be cleared at reboot time,
not all systems contain a /run or /var/run directory. To avoid
potential problems, sudoers
will ignore time stamp files that date
from before the machine booted on systems where the boot time is
available.
Some systems with graphical desktop environments allow unprivileged
users to change the system clock. Since sudoers
relies on the
system clock for time stamp validation, it may be possible on such
systems for a user to run sudo
for longer than timestamp_timeout by
setting the clock back. To combat this, sudoers
uses a monotonic
clock (which never moves backwards) for its time stamps if the
system supports it.
sudoers
will not honor time stamps set far in the future. Time
stamps with a date greater than current_time + 2 * TIMEOUT will be
ignored and sudoers
will log and complain.
If the timestamp_type option is set to 'tty', the time stamp record
includes the device number of the terminal the user authenticated
with. This provides per-terminal granularity but time stamp
records may still outlive the user's session.
Unless the timestamp_type option is set to 'global', the time stamp
record also includes the session ID of the process that last
authenticated. This prevents processes in different terminal
sessions from using the same time stamp record. On systems where a
process's start time can be queried, the start time of the session
leader is recorded in the time stamp record. If no terminal is
present or the timestamp_type option is set to 'ppid', the start
time of the parent process is used instead. In most cases this
will prevent a time stamp record from being re-used without the
user entering a password when logging out and back in again.