Mitigating the 0-day Apache path traversal vulnerability
Tags: security, apache, 0day, vulnerability
Published: 2021-10-05 21:46:02

Apache has disclosed a critical **_actively exploited_** path traversal flaw in the popular Apache webserver, versions 2.4.49 and 2.4.50. This path traversal means that an attacker can trivially read the contents of any file on the server that the Apache process has access to. This could expose highly sensitive information, even as critical as the server's own private SSL certificates. See the [Sonatype blog](https://blog.sonatype.com/apache-servers-actively-exploited-in-wild-importance-of-prompt-patching) for more technical information on the vulnerability.

| Update      | 
| ----------- | 
| The fix in Apache version 2.4.50 was incomplete. Please follow these instructions to upgrade your nodes to Apache version **2.4.51** from both 2.4.49 and 2.4.50.| 

Puppet Enterprise and Bolt both make it easy to identify vulnerable systems and mitigate the exposure by upgrading the Apache package.


## Using Puppet Enterprise

Puppet Enterprise includes a feature called Package Inventory. This will allow you to quickly identify which nodes in your infrastructure are running the vulnerable version of Apache. It's disabled by default, so you'll need to turn it on first.

In the PE Console, find the PE Agent node group. Add the `puppet_enterprise::profile::agent` class if needed and then set the `package_inventory_enabled` parameter to `true`. Use the _Run Puppet_ button to trigger a Puppet run on all nodes. The inventory collection will take effect on all subsequent Puppet runs, so once it's completed, trigger a second Puppet run.

Now use the **Packages** page to view your infrastructure's package inventory. Filter by the package name "httpd", then click into the package detail page and filter by the version "2.4.49". This now lists all nodes with the vulnerable version.

If the package is managed by Puppet, use the **Instances** selector to drill in and then click **Copy path** to quickly find the spot in your codebase you need to update with a newer version. Run Puppet on all nodes once the codebase has been updated.

If you have instances in which the package is not managed by Puppet, then use a Puppet Task to push a package update to these nodes. Create a list of the affected nodes, then use the **Package** task to force the package to be updated. [See the docs](https://puppet.com/docs/pe/latest/running_tasks_in_the_console.html) for more information.

Since some distributions call the package "apache", repeat the above steps with that name too. And then given the second patch, check both package names for version "2.4.50" as well.

Find more information about the Package Inventory on its [docs page](https://puppet.com/docs/pe/latest/viewing_packages_in_use.html).


## Using Puppet Bolt

If you don't have Puppet Enterprise, Bolt allows you to use plans to gather information from nodes. Let's start by creating a new project by creating a directory called `apache_mitigation`. Now cd into that directory and turn it into a Bolt project by running `bolt project init`.

You'll want an inventory file so you can address all your nodes. If you don't have one already, then create one [following instructions](https://puppet.com/docs/bolt/latest/inventory_files.html). We will use the implicit `all` target group, or you can create a more specific group if you want to limit the nodes to be inspected.

Then create a new plan to manage the package upgrade process. Run `bolt plan new apache_mitigation::upgrade_vulnerable_packages --pp`. Add the following content to your new plan file:


``` puppet
plan apache_mitigation::upgrade_vulnerable_packages (
  String     $package,
  String     $vulnerable_version,
  String     $target_version,
  TargetSpec $targets,
) {
  # Get status of package on each target
  $package_status = run_task('package', $targets, 
    'name'   => $package, 
    'action' => 'status'
  )

  # Select targets that have the vulnerable package installed
  $vulnerable_targets = $package_status.filter_set |$result| {
    $result['version'] == $vulnerable_version
  }.targets

  # Upgrade the package to a non-vulnerable version on each target
  $result = run_task('package', $vulnerable_targets,
    'name'    => $package, 
    'action'  => 'upgrade',
    'version' => $target_version
  )

  return $result
}
```

Since different distributions use different package names, run that plan for both `httpd` and `apache`.

```
bolt plan run apache_mitigation::upgrade_vulnerable_packages package=httpd vulnerable_version=2.4.49 target_version=2.4.51 --targets=all
bolt plan run apache_mitigation::upgrade_vulnerable_packages package=httpd vulnerable_version=2.4.50 target_version=2.4.51 --targets=all

bolt plan run apache_mitigation::upgrade_vulnerable_packages package=apache vulnerable_version=2.4.49 target_version=2.4.51 --targets=all
bolt plan run apache_mitigation::upgrade_vulnerable_packages package=apache vulnerable_version=2.4.50 target_version=2.4.51 --targets=all
```



## Verifying the mitigation

Whether you choose to use Puppet Enterprise or Bolt to mitigate your exposure, once you're finished you can go back and verify that the vulnerable nodes have been upgraded. On Puppet Enterprise, you'd go back to the Packages page in the PE Console and drill down to the `httpd` or `apache` packages to validate versions. And if you used Bolt, you'd just run the `apache_mitigation::upgrade_vulnerable_packages` plan again and validate that the output is empty.

_Ben is the Product Manager of Ecosystem and Developer Experience at Puppet._


### Learn more



* See the [Sonatype blog](https://blog.sonatype.com/apache-servers-actively-exploited-in-wild-importance-of-prompt-patching) for more technical information on the vulnerability.
* [Read more](https://puppet.com/docs/pe/latest/viewing_packages_in_use.html) about Package Inventory.
* [Read more](https://puppet.com/docs/bolt/latest/bolt.html) about Puppet Bolt.