Adversaries modify setuid (set user ID) and setguid (set group ID) bits to elevate their permissions in macOS and Linux environments
Editor’s note: While the detection opportunities and analysis on this page are still relevant, it has not been updated since 2023.
Once an adversary gains access to a machine, they need to make sure they have enough permissions to persist, evade defensive controls, steal credentials, and more. Adversaries abuse setuid and setgid bits to elevate their privilege levels on macOS and Linux, potentially accessing both cloud-hosted and physical on-premise machines. With elevated privileges, adversaries can modify system configurations, install software, access sensitive files, perform credential theft, disable security products, and much more. Adversaries may also set the setuid or setgid bit on binaries that wouldn’t normally have them, enabling them to so that they can easily elevate privileges in the future.
Setuid and setgid binaries are executable files with a special permission bit that allows the binary to run as either the owner (setting the user ID) or the owning group (setting the group ID) of the file. For example, if a user named bob
runs a file with the following permissions, then the process would actually run as if root
ran the binary instead of bob
:
Permissions | Owner | Group | Filename
-rwsr-xr-x
root
root
/usr/bin/ping*
Notice the s
in place of where an x
would normally be for user permissions. The same is true of the setgid bit, except it sets the owning group of the file instead of the user. Normally this is benign, expected behavior that allows a non-privileged user like bob
to run a binary that needs elevated privileges. However, if there’s a bug in the binary that an adversary can exploit, they can act with all of the privileges of the owning user or group, which most often is root or some other privileged account. These sorts of bugs may seem rare, but they are in fact surprisingly common.
Adversaries most often leverage this technique by finding native binaries that have the setuid or setgid bit set and are owned by root
or some other privileged user. After finding such a binary, they attempt to exploit a flaw in the binary in order to gain execution or, at the very least, perform an action as the privileged user.
One notable example of this technique is the PwnKit vulnerability discovered in January 2022, which exemplifies how setuid binaries can be dangerous when adversaries abuse them. PwnKit was a bug in the pkexec utility that ships with polkit, a component that sets system-wide permission levels and is included by default in many Linux distributions. The pkexec
binary was owned by root
and had the setuid bit set. It also had a bug in it that allowed an unprivileged user to load a shared object file that would run with root privileges. This bug made it trivial for an unprivileged user to elevate privileges. DataDog has a great write-up on PwnKit if you’re looking for additional details.
chmod u+s /usr/bin/some_binary
if some_binary
is owned by root
. A natural mitigation is to make sure that file permissions are set correctly. This means following the practice of least privilege for file permissions.nosuid
flag set where appropriate. This means that any file with the setuid or setgid bit set, mounted at or within that location, will not be allowed to run. This is often the default for things like /tmp
, /proc
, /sys
, etc., but your mileage may vary depending on the distribution you’re running. Be aware that this may cause some tools to stop working if they depend on the ability to execute setuid/setgid binaries, so proceed with caution.ping
binary, on more modern systems it is no longer a setuid binary—but rather has the CAP_NET_RAW
capability. This still allows it to create the right kind of socket but does not give it any of the other privileges that running as root
would provide.Unfortunately, in most cases the burden of updating binaries to use capabilities lies with the distribution maintainers more than the end user.
Note: The visibility sections in this report are mapped to MITRE ATT&CK data sources and components.
Adversaries often execute reconnaissance commands in search of setuid and setgid binaries. Therefore, defenders can find relevant telemetry by monitoring for discovery commands related to the setuid and setgid binaries. Looking for specific command-line parameters would help defenders be able to key in on commands related to the setuid and setgid bit. One example would be commands that use the octal or symbolic form of file permissions, such as 4755
or u+s
. For example:
chmod 4755 /bin/bash
There are myriad tools on any given Linux distribution that can allow a user to search for files with the given permissions and owner. Looking for execution of these types of commands could help identify the goals of an adversary as well. Below are just a few examples:
find / -perm -u=s -type f
ls -al | grep ‘rws’
stat -c “%A %U %G” /path/to/file | grep 'rws'
getfacl -R * | grep -C 3 "flags: "
Note: The collection sections of this report showcase specific log sources from Windows events, Sysmon, and elsewhere that you can use to collect relevant security information.
Many EDR products collect process and command telemetry. This is a valuable resource in being able to observe adversaries attempting to leverage this behavior. Some EDR products also show the file permissions of a binary that was run. Looking at this field may be helpful in investigating this technique.
The audit subsystem provides information about activities that are performed on a host. It can be configured to provide information about the user ID and group ID of a process executing a given syscall. It can also be used to monitor syscalls that would change a file’s owner or permissions.
Execution of setuid and setgid binaries can be considered normal behavior on many Linux distributions. For many years, the ping
binary was owned by root
and had the setuid bit set, as it needed to create a special type of socket that requires elevated privileges.
Detection strategies for this technique could include looking for commands that search for setuid or setgid binaries. The following detection analytic looks specifically for execution of the find binary searching for executables with the setuid or setgid bit set:
process == “find”
&&
command_includes (“-perm”)
&&
command_includes_any (“4000”, “2000”, “u=s”, “g=s”)
This would search for a command such as find /usr/bin -perm /4000
, which you can emulate with this atomic.
There are numerous Atomic Red Team tests for simulating T1548.001. This one in particular covers setting the setuid and setgid bits, executing a file with the setuid bit set, giving a binary the setuid capability, and executing a binary with the setuid capability.
Run the following script with sh!
(elevation required):
touch /tmp/evilBinary
sudo setcap cap_setuid=ep /tmp/evilBinary
We also have an AtomicTestHarness suite dedicated to simulating behavior around T1548.001. This suite of tests will run multiple built-in tools to simulate different ways to add the setuid and setgid bit to a binary.
Some simple ways to test this behavior would be to either run a search for binaries with setuid/setgid bits set or to actually run them.
A command to search for setuid/setgid binaries:
find /usr/bin -perm /4000
A command to execute a binary with the setuid bit set. You could use the output from the previous command. Some common tools with this bit set are ping
, su
, mount
, passwd
, sudo
, and others.
/path/to/setuid/binary
Get curated insights on managed detection and response (MDR) services, threat intelligence, and security operations—delivered straight to your inbox every month.