Pentester’s tricks: Local privilege escalation in OpenVAS

It’s not a common scenario but if during a pentesting you get access to some machine with a user that has sudo rights to execute openvas, you could escalate privileges to get root!

In this post I’m going to describe some OpenVAS workflows and then dive into this particular local privilege escalation.

A bit of background about OpenVAS workflows

OpenVAS is one of the most well-known vulnerability scanners. When you install OpenVAS you’ll get the openvas binary as outcome but it’s not a ready-to-call executable. You need two more components:

  • A project that implements the OSP protocol like ospd-openvas.
  • A library like python-gvm that provides the programming interface to be able to speak to OpenVAS using OSP conventions via ospd-openvas.

From python-gvm documentation, we have the following example:

It’s one of the simplest and lightest workflows to execute OpenVAS. There are more workflows like using a virtual machine but that involves more components.

Returning to our example, to run successfully the previous code snippet we must be able to communicate with ospd-openvas (it’s a unix socket). To achieve that, we can either set the socket permissions or run ospd-openvas with our user.

Additionally, an important recommendation in OpenVAS installation’s docs (point 5) is about running OpenVAS as root.

Please note that although you can run openvas as a user without elevated privileges, it is recommended that you start openvas as root since a number of Network Vulnerability Tests (NVTs) require root privileges to perform certain operations like packet forgery. If you run openvas as a user without permission to perform these operations, your scan results are likely to be incomplete.

[…]

The sudo rights are thought for the user running ospd-openvas. For instance, in Ubuntu Groovy (20.10) there’s a package for ospd-openvas that executes this service under the user _gvm. User _gvm will have the sudo rights to call openvas. This user has nologin as shell so I imagine that openvas is thought to be:

  1. Scheduled by another process running as _gvm .
  2. Scheduled by a high-privileged process (i.e. root) that can fork a process with _gvm as owner.

In my opinion, it seems a safe way of running OpenVAS.

From my own experience implementing workflows with OpenVAS, there are some differences:

  • There are coordinated releases for all the involved packages (i.e. v20.8.1) so you are kind of motivated to upgrade manually to get the latest features.
  • OS packages are a bit outdated or they don’t exist (in Ubuntu 20.04 ospd-openvas doesn’t exist) so people have to build their own packages and that leads to custom running user and permissions.
  • A scan could get stuck or not finish so you need to have some monitoring solution around OpenVAS.
  • There are more protocols to talk to OpenVAS too.

In the end, there are several ways to implement an OpenVAS workflow that could derive in different permission/ownership schemes and end up with a user having sudo rights to execute openvas. What’s important to us, as pentesters, is to know that if we got a shell as a user which has sudo rights to execute openvas , we can escalate privileges to root. Let’s go that path.

Finding the step to climb

So our user has sudo rights to execute openvas. An interesting feature of the openvas binary is that the configuration can be changed in runtime with the option -c. In the screenshot below I demonstrate that displaying the configuration using the option -s .

After looking at the different settings and how I could take advantage of them, I stumbled upon this article:

openvas binary loads plugins from a location defined by the setting plugins_folder . What about changing plugins_folder setting on runtime to point to a directory where I store a malicious plugin that will get executed when a OpenVAS scan runs? That’s the way to escalate privileges 🆙

Creating the exploit

To exploit this privilege escalation we have to create a scenario that consists of several steps. First, we’re going to create the malicious plugin in the directory /tmp/plugins:

This malicious NASL plugin will create a rootshell when it gets executed (line 15–18). It’s important to remember the plugin ID 1.2.3.4.5 declared on line 3 because it will be used later. Additionally, to be considered a valid plugins_folder, it needs to contain a file called plugin_feed_info.inc with a valid date string:

PLUGIN_SET = "202006091543"

Then we’re going to create our malicious configuration file at /tmp/openvas.conf that will be provided to openvas via -c option.

plugins_folder = /tmp/plugins
db_address = /tmp/redis-server.sock

It makes reference to our rogue plugin folder and to a Redis socket. I haven’t mentioned that but OpenVAS uses a Redis database to store some scan information. In Ubuntu Groovy, a Redis instance is initiated specially for OpenVAS but I can’t use it because it has strict permissions:

To get over this condition, I’ve started my own instance of Redis listening on socket /tmp/redis-server.sock and set it in my malicious configuration.

The next step is important. As explained before, we need to run ospd-openvas to communicate with openvas binary. Looking at the code, official ospd-openvas project calls openvas with sudo which is good, but it doesn’t set the -c option. So I had to create a fork to add a -c option referring to my malicious configuration. You can see it in the diff:

So, in my exploit scenario, I’ll run my fork with the following configuration:

This configuration aims to create a ospd-openvas socket at /tmp/ospd-openvas.sock so I have full control over it.

The last step is to trigger a scan and for that purpose we will use this script:

It’s pretty similar to the example from python-gvm . In fact, it’s an adaptation from this test. Let’s review the code:

  1. In line 8 I make a reference to my ospd-openvas socket.
  2. In line 14 I add my malicious plugin to be run as part of the vulnerability tests.
  3. In line 19 I make a call to start a scan.

If everything went well, a root shell is waiting for us at /tmp/rootshell !

Running the exploit

In case you want to try in a closed environment, I provide a sample Vagrantfile to do the escalation from the user runner (so remember to switch from vagrant to runner user).

The requirements are to install python-gvm and my ospd-openvas fork. I’ve done that using a virtual environment.

After that, you’re ready to run the exploit. The code is here. It’s a bit long to embed here because of the configuration files but I expect it’s easy to understand. You can see it in action in the video below:

Final words

I don’t want to try to convince anyone that it’s the default scenario but it’s possible and if in one of your penetration testing engagements you find a user account with sudo rights to run openvas , take advantage of it!

I reached out to Greenbone Security Team about the issue because it’s on the project’s contact page but in the end we realized it was a specific scenario and not the default one. Their response time was impressive and we could interchange around 8 emails in less than a day.

The recommendation is, as seen in the Ubuntu Groovy package, set the sudo rights to a user without shell access so the interaction is restricted to be done via ospd-openvas and that way is not possible to manipulate openvas command-line options.

security & development

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store