The UNIX superuser
Introduction
Attackers prefer to target highly privileged users. On a UNIX operating system, the preferred target is a superuser, often referred to as the ‘root user’. By definition, a superuser is one with a UID value of 0. On z/OS UNIX, that definition is extended to include started tasks with the TRUSTED or PRIVILEGED attribute.
The design of RACF supports separation of duties. For example, a user with the OPERATIONS attribute is allowed to access data, but not manage that access. A user with the SPECIAL attribute is allowed to manage security, including access to resources, but is not (directly) allowed to access those resources. A user with the AUDITOR attribute is allowed to establish logging options, but not to change other security-related settings. A SPECIAL user cannot (directly) change logging options, or even see them.
In contrast, the UNIX superuser can do anything and everything on a traditional UNIX system. Think of it as having SPECIAL and OPERATIONS, seasoned with inherent SURROGAT authority, served with a side-dish of file system management, and garnished with the ability to start and stop processes. On z/OS UNIX, when it comes to non-standard extensions to the security model, UID(0) is not respected. We saw this in previous articles regarding UNIX file auditing and extended attributes, for example.
While superuser privilege only applies to UNIX file systems and processes, do not get too confident about the safety from superusers of your traditional z/OS resources protected by RACF profiles. A superuser is allowed to switch identity to any user defined to z/OS UNIX (that is, any user with a UID, whose default group has a GID). This switch can include the z/OS identity as well as the UNIX identity. Thus, for example, a superuser does not automatically get UPDATE access to an authorized APF library, but it could switch identity to a z/OS UNIX user who does have such access. If any application configuration files are stored in the file system, they can be modified by a superuser. When it comes to abusing your superuser authority, the possibilities are endless!
In short, UID(0) is an inherent separations of duties issue. But there are ways of mitigating, and even replacing, its use.
Don’t assign UID(0) to human beings
The simplest way to protect against UID(0) is to not assign it. Of course, there are going to be system-level components that require it, and that’s fine. But granting UID(0) to carbon-based life forms introduces all sorts of separation of duties issues, as outlined above.
In my previous article, “UNIX Users and Groups”, I described use of the SHARED.IDS profile in the UNIXPRIV class to prevent assignment of xIDs that are already in use. UID(0) is already in use, as you must assign it to the BPXROOT user ID. Thus, to assign UID(0), you must use the SHARED keyword. The SHARED keyword requires either system SPECIAL or READ authority to SHARED.IDS. Limit this capability to trusted administrators who are aware of the risks, and make sure justification is provided whenever UID(0) is requested. Review existing UID(0) users to make sure they are only assigned to functional user IDs, like UNIX daemons. Such user IDs should be PROTECTED, to prevent them from being targets of a logon.
Assigning individual capabilities
Using resources in the UNIXPRIV class, you can grant users specific superuser capabilities without giving more authority than their job role requires. These capabilities include file access, process management, mount and unmount of file systems, aspects of file security management, and other miscellaneous abilities.
The SUPERUSER.FILESYS resource grants system-wide access to files at various access levels. This is roughly analogous to the OPERATIONS attribute, but with more granularity. READ access allows any file to be read, and any directory to be searched. UPDATE includes READ and adds the ability to write to any file. CONTROL includes UPDATE, and allows writing to directories (i.e. creating and deleting files).
With RACF profiles, individual access list entries override OPERATIONS. For example, I could permit an OPERATIONS user with ACCESS(NONE) within a DATASET class profile, and they cannot access data sets covered by the profile. A similar capability exists with regard to SUPERUSER.FILESYS access. By defining SUPERUSER.FILESYS.ACLOVERRIDE, UNIX acl entries will override SUPERUSER.FILESYS authority. So, while you cannot explicitly scope the UNIXPRIV authority to individual files or directory trees, you can use this technique to keep them out of specific objects. Also note that the FSACCESS class (described in my file system security article) does not respect UNIXPRIV, and so is another way to lock out SUPERUSER.FILESYS users. On the flip side, users permitted to SUPERUSER.FILESYS will also need FSACCESS authority where appropriate.
In the area of security management, individual UNIXPRIV resources control the ability to change file ownership (SUPERUSER.FILESYS.CHOWN) and to change permissions, both permission bits and acls (SUPERUSER.FILESYS.CHANGEPERMS). As we saw in previous articles, extensions to the standard (AUDITOR audit bits, extended attributes, and security labels) never respected UID(0), and thus require no corresponding resource in the UNIXPRIV class.
The ability to change file ownership/permissions requires that you have the authority to actually get to the object you wish to change. That is, you need search access to all directory path components leading up to the object. In the past, this often involved giving the user READ access to SUPERUSER.FILESYS, which also grants file access. Or perhaps AUDITOR or ROAUDIT was granted to the user, which gave him more RACF authority than necessary. This situation was improved in z/OS 2.2 when the SUPERUSER.FILESYS.DIRSRCH resource was added. This allows only directory searches.
So go ahead, review your current UID(0) users, and see if some can be replaced with a set of UNIXPRIV authorities. While you’re at it, make sure you are logging successful accesses to these profiles (with the possible exception of SUPERUSER.FILESYS.DIRSRCH).
Using the su command to implement job roles
The UNIX ‘switch user’ command su is often associated with switching into ‘superuser mode’. This is true and is described in the next section. However, su also allows you to switch into the identity of any UNIX user. You are not just switching to their UID and GIDs, but to their RACF user ID as well. For you z/VM afficionados, it’s sort of like LOGON BY.
The su command is authorized by either specifying the target user ID’s password (bad) or by virtue of having authority in the SURROGAT class (good). Using SURROGAT allows you to switch into a PROTECTED user, so that the user cannot be the target of a password attack. For example, to allow me to switch into FILEADMN’s identity:
PERMIT BPX.SRV.FILEADMN CLASS(SURROGAT) ID(BRUCE) ACCESS(READ)
In the shell, I use the su command with the -s option (so that it doesn’t prompt me for a password):
$ su -s fileadmn
$ id
uid=10(FILEADMN) gid=100(NOTMYGRP)
$ # Do stuff under the authority of FILEADMN
$ exit
This technique allows you to define a job role into which a user can temporarily switch. In the example above, FILEADMN could be provisioned with only the UNIXPRIV permissions necessary for file system administration. And since the end-user is switching into an MVS identity in addition to a UNIX identity, the new capabilities need not be restricted to UNIX-oriented tasks. The shell has a ‘tsocmd’ command that allows you to issue TSO commands from the shell. You are in a full-screen environment, so you can scroll back up to see output that doesn’t fit on a single screen. In fact, all the shell tools and techniques are at your disposal, so you can direct command output into a file, for example.
So, play around! After the switch, issue:
$ tsocmd listuser
You will see that RACF also thinks you are the target user ID. So, for example, you could use this technique to elevate your RACF privilege temporarily in the same manner.
But if you really must …
For example, SMP/E documentation states that UID(0) is necessary in some cases. Instead of assigning UID(0), use the BPX.SUPERUSER profile in the FACILTY class to grant the ability for a user to switch into ‘superuser mode’. READ access is required. Log successful accesses to this profile.
Be aware that the user is still able to do everything she would be able to do when explicitly assigned UID(0). However, superuser mode has the advantage that the user doesn’t always have superuser powers, only when specifically requested. This allows the user to elevate privilege for a short duration of time to perform a specific function. Then, superuser mode can be relinquished. This can mitigate the chance of a conscientious administrator accidentally causing damage.
In the shell, issue the su command with no operands to enter superuser mode. The prompt character helpfully changes to reflect that you are in superuser mode. This visual cue can remind you that you are running with elevated privilege. Issue the exit command to switch back to your normal UID:
$ id
uid=18(TSOUSR8) gid=1(SYS1)
$ su
# id
uid=0(BPXROOT) gid=1(SYS1)
# exit
$ id
uid=18(TSOUSR8) gid=1(SYS1)
$
Note that su is only changing the ‘effective UID’ of the process. This is the UID (in the User Security Packet) on which UNIX authorization decisions are based. The display of the user ID BPXROOT is simply an artifact of the underlying code mapping the UID to a user ID for display. Therefore, switching into superuser mode does not also confer traditional RACF resource authority for resources to which the BPXROOT user ID is permitted.
Superuser mode can also be entered from within ISPF and REXX.
z/OS UNIX resource limits
Another thing that a superuser can do is use the setrlimit() function to increase any of the system limits for a process. These limits include things like how much CPU may be consumed, and how many concurrent threads (tasks) can be active for a single user. BPXPRMxx defines these values at the system level, and the OMVS segment of the RACF USER profile contains fields that can override these settings.
As an alternative to granting an application user ID UID(0) just so it can increase some of these limits when necessary, you can instead give that user higher limits than the system-wide values.
Conclusion
What are some things you can do, right now, to eliminate or mitigate the use of UID(0)?
-
- Review all user IDs with UID(0). For functional user IDs, make sure they are PROTECTED. For human users, see if individual UNIXPRIV resources can be used to grant them the Least Privilege required for their job role. UID(0) may have been granted a long time ago before some of the UNIXPRIV resources even existed.
- Review the access list of SUPERUSER.FILESYS. If READ access was granted to allow unfettered directory search, replace it with access to SUPERUSER.FILESYS.DIRSRCH.
- Review users with the AUDITOR (and the newer ROAUDIT) attribute for the same reason as above.
- Implement SHARED.IDS in the UNIXPRIV class and be skeptical of any and all requests for UID(0).
- Log successful accesses to BPX.SUPERUSER and the UNIXPRIV class profiles.
Brought to you by Bruce Wells
Bruce Wells is the RACF Product Owner, and has been a RACF design and developer on both the z/VM and z/OS versions for over 30 years.