While reviewing my Twitter feed I noticed a recent popular tweet from @0xdea.
I was intrigued and wanted to see if there was a way to leverage this to execute arbitrary code as root.
First we need to understand what the value of INT_MAX is. Fortunately the getconf command can be used to find the value or you can find it in /usr/include/limits.h.
[root@localhost ~]# getconf INT_MAX
[root@localhost ~]# grep ‘define INT_MAX’ /usr/include/limits.h
# define INT_MAX 2147483647
To exploit the vulnerability the user must have a UID value larger than 2147483647. I used the same value of 4000000000 that @0xdea posted.
[root@localhost ~]# useradd -u 4000000000 user9
[root@localhost ~]# id user9
uid=4000000000(user9) gid=1006(user9) groups=1006(user9)
The first test case I attempted was to manage a service. I successfully started tuned(8) as a low privilege user.
Now that the vulnerability has been verified I was on a quest to find a way to execute arbitrary code as root. I approached this using the same methodology I use when attacking sudo rules.
- Learn about the command(man, info, Google)
- Search for options/parameters/functionality to abuse.
- Execute commands
- Load libraries
- File paths
- Environment variables
- Pipe or store output
- Configuration files
- Determine if other commands are executed (strace -f,ltrace -f -S)
After paging through the systemctl man page and trying various commands/options, I successfully leveraged the link parameter to deploy a custom service file on a CentOS 7.4 system. I suspect there are other systemctl parameters or options that be abused.
man page excerpt
Link a unit file that is not in the unit file search paths into the unit file search path. This requires an absolute path to a unit file. The effect of this can be undone with disable. The effect of this command is that a unit file is available for start and other commands although it is not installed directly in the unit search path.
To achieve arbitrary code execution I copied an existing service file to my test users home directory and modified it. The main line to modify is ExecStart=, however I am sure there are plenty of other options but this was the easy button. The job is not connected to the standard I/O so I piped the output of id to the wall command. Full PoC here: CVE-2018-19788.sh. I asked @paragonsec to independently test it on his Debian system and he confirmed it was successful. Woot!
@paragonsec discovered a one-liner with the systemd-run command to get a full interactive root shell.
While this vulnerability should have limited exposure because of the large UID requirement, I still enjoyed the challenge of finding a way to leverage it to execute arbitrary code as root. Props to @0xdea for finding and disclosing the vulnerability. I appreciate @paragonsec for testing my PoC on short notice. My PoC was referenced in The Hacker News Warning! Unprivileged Linux Users With UID > INT_MAX Can Execute Any Command.