argv[0]
), are under the control of the user, you should not trust argv[0]
to point to your program. If you use the command line to re-execute your own application or tool, for example, a malicious user might have substituted a different app for argv[0]
. If you then pass that to a function that uses the first argument as the name of the program to run, you are now executing the attacker’s code with your privileges.fork
). Therefore, if you have a handle on a file, network socket, shared memory, or other resource that’s pointed to by a file descriptor and you fork off a child process, you must be careful to either close the file descriptor or you must make sure that the child process cannot be tampered with. Otherwise, a malicious user can use the subprocess to tamper with the resources referenced by the file descriptors. execve
system call), use the fcntl
system call to set the close-on-exec flag. You must set this flag individually for each file descriptor; there’s no way to set it for all.LD_LIBRARY_PATH
, DYLD_LIBRARY_PATH
are often misused, causing unwanted side effects.MallocLogFile
CF_CHARSET_PATH
PERLLIB
, PERL5LIB
, PERL5OPT
setrlimit
system call to limit the consumption of system resources by a process. For example, you can set the largest size of file the process can create, the maximum amount of CPU time the process can consume, and the maximum amount of physical memory a process may use. These process limits are inherited by child processes.setrlimit
to alter these limits, it can cause operations to fail when they ordinarily would not have failed. For example, a vulnerability was reported for a version of Linux that made it possible for an attacker, by decreasing the maximum file size, to limit the size of the /etc/passwd
and /etc/shadow
files. Then, the next time a utility accessed one of these files, it truncated the file, resulting in a loss of data and denial of service. [CVE-2002-0762]installer
command requires administrative privileges; see the installer
manual page). However, if you have the application configure itself, or check whether configuration is needed when it starts up, then you don’t need to run as root at all.ps
command, which displays information about processes that have controlling terminals. Originally, BSD used the setgid
bit to run the ps
command with a group ID of kmem
, which gave it privileges to read kernel memory. More recent implementations of the ps
command use the sysctl
utility to read the information it needs, removing the requirement that ps
run with any special privileges.launchd
daemon (see launchd). It is easier to use launchd
to launch a daemon and easier to communicate with a daemon than it is to fork your own privileged process. authopen
command to read, create, or update a file (see authopen).setuid
and setgid
bits for the executable file, and sets the owner and group of the file to the privilege level it needs (often with the root
user and the wheel
group). Then when the user runs that tool, it runs with the elevated privileges of the tool’s owner and group rather than with the privileges of the user who executed it. This technique is strongly discouraged because the user has the ability to manipulate the execution environment by creating additional file descriptors, changing environment variables, and so on, making it relatively difficult to do in a safe way.setuid
, setgid
, and related routines to make sure they succeeded. Otherwise you might still be running with elevated privileges when you think you have dropped privileges.setuid
function sets the real and effective user IDs and the saved user ID of the current process to a specified value. The setuid
function is the most confusing of the UID-setting system calls. Not only does the permission required to use this call differ among different UNIX-based systems, but the action of the call differs among different operating systems and even between privileged and unprivileged processes. If you are trying to set the effective UID, you should use the seteuid
function instead.setreuid
function modifies the real UID and effective UID, and in some cases, the saved UID. The permission required to use this call differs among different UNIX-based systems, and the rule by which the saved UID is modified is complicated. For this function as well, if your intent is to set the effective UID, you should use the seteuid
function instead.seteuid
function sets the effective UID, leaving the real UID and saved UID unchanged. In macOS, the effective user ID may be set to the value of the real user ID or of the saved set-user-ID. (In some UNIX-based systems, this function allows you to set the EUID to any of the real UID, saved UID, or EUID.) Of the functions available on macOS that set the effective UID, the seteuid
function is the least confusing and the least likely to be misused.setgid
function acts similarly to the setuid
function, except that it sets group IDs rather than user IDs. It suffers from the same shortcomings as the setuid
function; use the setegid
function instead. setregid
function acts similarly to the setreuid
function, with the same shortcomings; use the setegid
function instead. setegid
function sets the effective GID. This function is the preferred call to use if you want to set the EGID. setuid
and related commands, see Setuid Demystified by Chen, Wagner, and Dean (Proceedings of the 11th USENIX Security Symposium, 2002), available at http://www.usenix.org/publications/library/proceedings/sec02/full_papers/chen/chen.pdf and the manual pages for setuid
, setreuid
, setregid
, and setgroups
. The setuid(2)
manual page includes information about seteuid
, setgid
, and setegid
as well.authopen
command lets you obtain temporary rights to create, read, or update a file. You can use the launchd
daemon to start a process with specified privileges and a known environment. authopen
command, you provide the pathname of the file that you want to access. There are options for reading the file, writing to the file, and creating a new file. Before carrying out any of these operations, the authopen
command requests authorization from the system security daemon, which authenticates the user (through a password dialog or other means) and determines whether the user has sufficient rights to carry out the operation. See the manual page for authopen(1)
for the syntax of this command.launchd
daemon is used to launch daemons and other programs automatically, without user intervention. (If you need to support systems running versions of the OS earlier than 10.4, you can use startup items.)launchd
daemon can launch both systemwide daemons and per-user agents, and can restart those daemons and agents after they quit if they are still needed. You provide a configuration file that tells launchd
the level of privilege with which to launch your routine.launchd
to launch a privileged helper. By factoring your application into privileged and unprivileged processes, you can limit the amount of code running as the root user (and thus the potential attack surface). Be sure that you do not request higher privilege than you actually need, and always drop privilege or quit execution as soon as possible.launchd
in preference to writing a daemon running as the root user or a factored application that forks off a privileged process:launchd
launches daemons on demand, your daemon needs not worry about whether other services are available yet. When it makes a request for one of those services, the service gets started automatically in a manner that is transparent to your daemon.launchd
itself runs as the root user, if your only reason for using a privileged process is to run a daemon on a low-numbered port, you can let launchd
open that port on your daemon’s behalf and pass the open socket to your daemon, thus eliminating the need for your code to run as the root user.launchd
can launch a routine with elevated privileges, you do not have to set the setuid
or setgid
bits for the helper tool. Any routine that has the setuid
or setgid
bit set is likely to be a target for attack by malicious users.launchd
runs in a controlled environment that can’t be tampered with. If you launch a helper tool that has the setuid
bit set, it inherits much of the launching application’s environment, including:posix_spawn
, posix_spawnp
, or an exec
variant that takes an explicit environment argument, such as execve
).launchd
, which completely controls the launch environment.launchd
to launch a daemon.launchd
than to write factored code and fork off a separate process.launchd
is a critical system component, it receives a lot of peer review by in-house developers at Apple. It is less likely to contain security vulnerabilities than most production code.launchd.plist
file includes key-value pairs that you can use to limit the system services—such as memory, number of files, and cpu time—that the daemon can use.launchd
, see the manual pages for launchd
, launchctl
, and launchd.plist
, and Daemons and Services Programming Guide. For more information about startup items, see Daemons and Services Programming Guide.launchd
, the following lesser methods can be used to obtain elevated privileges. In each case, you must understand the limitations and risks posed by the method you choose.setuid
bit is set, the program runs as whatever user owns the executable regardless of which process launches it. There are two approaches to using setuid
to obtain root (or another user’s) privileges while minimizing risk:setuid
helper tool that runs only as long as necessary and then quits.setuid
, setgid
, and related routines to make sure they succeeded.setuid
bit and related routines, see Elevating Privileges Safely./Library/StartupItems
directory, it is started by the SystemStarter
program at boot time. Because SystemStarter
runs with root privileges, you can start your program with any level of privilege you wish. Be sure to use the lowest privilege level that you can use to accomplish your task, and to drop privilege as soon as possible.launchd
daemon instead. For more information on startup items and startup item privileges, see Startup Items in Daemons and Services Programming Guide.AuthorizationExecuteWithPrivileges
function, which launches a privileged helper as the root user.setuid
tools. See Authorization Services Programming Guide for more information.xinetd
daemon was launched with root privileges at system startup and subsequently launched internet services daemons when they were needed. The xinetd.conf
configuration file specified the UID and GID of each daemon started and the port to be used by each service.launchd
to perform the services formerly provided by xinetd
. See Daemons and Services Programming Guide for information about converting from xinetd
to launchd
. See the manual pages for xinetd(8)
and xinetd.conf(5)
for more information about xinetd
.setuid
bit set, has sufficient privileges to perform whatever task it has to do. However, if the user doesn’t have the rights to perform this task, you shouldn’t launch the tool and—if the tool gets launched anyway—the tool should quit without performing the task. Your nonprivileged process should first use Authorization Services to determine whether the user is authorized and to authenticate the user if necessary (this is called preauthorizing; see Listing 5-1). Then launch your privileged process. The privileged process then should authorize the user again, before performing the task that requires elevated privileges; see Listing 5-2. As soon as the task is complete, the privileged process should terminate.permitWithRight:flags:
method to determine whether the user has the right to kill the process. The application must have previously added this right—in this example, called com.apple.processkiller.kill
—to the policy database. The permitWithRight:flags:
method handles the interaction with the user (such as an authentication dialog). If this method returns 0
, it completed without an error and the user is considered preauthorized.setuid
tool that will kill the process (Listing 5-2).setuid
bit set so that it runs with root privileges. It imports the externalized authorization rights and checks the user’s authorization rights again. If the user has the rights, the tool kills the process and quits. The following numbered items correspond to comments in the code sample:AuthorizationCopyRights
function to determine whether the user has the right to kill the process. You pass this function the authorization reference. If the credentials issued by the Security Server when it authenticated the user have not yet expired, this function can determine whether the user is authorized to kill the process without reauthentication. If the credentials have expired, the Security Server handles the authentication (for example, by displaying a password dialog). (You specify the expiration period for the credentials when you add the authorization right to the policy database.)