Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Make sure pasted text is black

Table of Contents

Overview

This post will explain how to find privilege escalation vuls on Windows that no one appears to be looking for, because it's been pretty easy to find a bunch of them. After explaining how to find them, I'll introduce some defenses that can partly mitigate the problem in different ways. But what I'd like to see change is for developers to start looking for these vuls in the way I describe so that they stop introducing them in the first place.

Back when we first released released CERT BFF, the usual process for putting together a proof-of-concept exploit for a memory corruption vulnerability was:

  1. Fuzz the target until you get control of the instruction pointer.
  2. Find out which bytes can be used to store your shellcode, using using BFF string minimization.
  3. Use Use ROP as  as necessary to modify the program flow so that it executes your shellcode.

It was often relatively straightforward to go from from Start to PoC with CERT BFF. As time went on, the bar for exploiting memory corruption vulnerabilities was raised. This can likely be attributed to two things that happened over the years:

  1. Increased fuzzing by parties releasing software.
  2. Increased presence of exploit mitigations in both software and the platforms that they run on.

I have recently worked on a vulnerability discovery technique that reminded me of the early BFF days. Both with respect to how easy it is to find the vulnerabilities and also how easy it can be to exploit them. In fact, the concept is so trivial that I was surprised by how successful it was in finding vulnerabilities. Just like the idea of going directly from fuzzing with BFF to a working exploit became less and less viable as time went on, I'd like for there to be much less low-hanging fruit that can be easily found with this technique.

In this post I will share some of my findings as well as the filter itself for finding privilege escalation vulnerabilities with with Sysinternals Process Monitor (Procmon).

The Concept

When a program is installed on the Windows platform, some components of it may run with privileges, regardless of which user is currently logged on to the system. These privileged components generally take two forms:

  1. Installed services
  2. Scheduled tasks

How might we achieve privilege escalation on a Windows system? Any time that a privileged process interacts with a resource that an unprivileged user may be able to influence, this opens up the possibility for a privilege escalation vulnerability.


What to look for

The easiest way to check for privileged processes that might be able to be influenced by non-privileged users is to use a Process Monitor filter that displays operations based on the following attributes:

  1. Files or directories that do not exist.
  2. Processes that have elevated privileges.
  3. Locations that may be writable by an unprivileged user.

Checks 1 and 2 can be trivially implemented in Process Monitor. Check 3 is a little more complicated and may result in some false positives if we limit our tool to strictly what can be done with a Process Monitor Filter. But I've created a filter that seems to do a pretty good job of making privilege escalation vulnerabilities pretty obvious.


Using the filter

Using the Privesc.PMF Process Monitor filter is relatively straightforward:

  1. Enable Process Monitor boot logging (Options → Enable Boot Logging)
  2. Reboot and log in
  3. Run Process Monitor
  4. Save the boot log when prompted
    Image Modified
  5. Import the "Privesc" filter (Filter → Organize Filters → Import...)
  6. Apply the Privesc filter (Filter → Load Filter → Privesc)
  7. Look for and investigate unexpected file accesses.


Investigating results

Let's start by looking at a boot log of a common baseline that we might deal with as a vulnerability analyst - a 64-bit Windows 10 2004 system with VMware Tools installed:

Even with virtually no software installed in our VM, we can already see something suspicious: C:\Program%20Files\

Windows users may be familiar with the path path C:\Program Files\, but what's with the the %20? Why might such a file operation occur? We'll cover the reason in the section below.


Mistakes that developers make

There are a number of mistakes that a developer might make that can lead to a privileged process being able to be influenced by an unprivileged user. The mistakes that I've noticed with respect to simple privilege escalation vulnerabilities with Windows applications fall into two main categories:

  1. Unexpected paths being accessed.
  2. Unexpected Access Control Lists (ACLs) applied to paths being used.

Unexpected paths being accessed

In some cases, an unexpected path is accessed during the execution of a program. That is, the developer would probably be surprised if they realized that the path was being accessed. These unexpected path accesses can be caused by a number of reasons:

HTML-encoded paths

As we noticed in the screenshot above, the VMware Tools process process VGAuthService.exe attempts  attempts to access the path path C:\Program%20Files\VMware\VMware%20Tools\VMware%20VGAuth\schemas\xmldsig-core-schema.xsd. How might this happen? If a path containing spaces is is HTML encoded, those spaces will be replaced with %20with %20.

What are the consequences of this transformation? The most important aspect of this new path is that rather than being a subdirectory of of C:\Program Files\, which has proper ACLs by default, this requested path now starts looking at the root directory. Unprivileged users on Windows systems can create subdirectories off of the system root directory. This will be a recurring theme, so remember this.

From an unprivileged command prompt, let's see what we can do:

Success!

We can dig a little deeper in Process Explorer by selecting the file access and pressing Ctrl-K to get the call stack:

Here we can see that the file access is triggered by by VGAuthService.exe + 0x110d9, and along the way there is a call to to xmlLoadExternalEntity().

Putting all of the pieces together here, we have a privileged process that attempts to load a file that does not exist because the path is HTML encoded. Since an unprivileged user can create this path, this now turns into a case where an unprivileged user can influence a privileged process. In this particular case, the consequences are only an an XML External Entity (XXE) vulnerability vulnerability. But we're also just getting warmed up.

POSIX paths

If an application uses a POSIX-style path on a Windows machine, this path is normalized to a Windows style path. For example, if a Windows application attempts to access the /usr/local/ directory, the path will be interpreted as C:\usr\local\. And as described above, this is a path that an unprivileged user can create on Windows.

...

If we look at the call stack, we can see that this access is likely triggered by the libsasl.dll library:

And sure enough, if we look at the code for libsasl, we can see a hard-coded reference to the path path C:\CMU\bin\sasl2.

As an unprivileged user, we can create the directory and place whatever code we want there. Once again, we have calc.exe executing with SYSTEM privileges. All from an unprivileged user account.

Use of paths that only exist on a developer's system

...

Unexpected ACLs applied to paths being used

Most cases of an unexpected path being accessed by an application can be exploited because of a simple fact: unprivileged users can create subdirectories off of the Windows system root directory. Finding and exploiting software that fails to properly set ACLs requires just a bit more investigation.

Most of the ACL issues related to Windows software is related to one concept:
Software that executes from a subdirectory of of C:\Program Files\ or  or C:\Program Files (x86)\ has  has secure ACLs ACLs by default by  by virtue of inheritance. For example, consider the case where I install my software to to C:\Program Files\WD\. Unprivileged users will not be able to modify the contents of the WD subdirectory the WD subdirectory because its parent directory of of C:\Program Files\ cannot  cannot be written to by unprivileged processes, and the the WD subdirectory  subdirectory by default will inherit its parents permissions.

Using the C:\ProgramData\ directory without explicitly settings ACLs

The The ProgramData directory  directory by design can be written to without elevated permissions. As such, any subdirectory that has been created in the ProgramData directory will by default be writable by unprivileged users. Depending on on how an  an application uses its ProgramData subdirectory, a privilege escalation may be possible if the ACLs for the subdirectory are not explicitly set.

Here we have a popular application that has a scheduled update component that runs from the C:\ProgramData\ directory:

This is a straightforward potential case of DLL hijacking, which is made possible due to lax ACLs on the directory from which the software runs. Let's plant a crafted msi.dll there and see what we can accomplish:

There's our calc.exe, executing with SYSTEM privileges. These problems seem a bit too prevalent. And easy to exploit.

It's worth noting that DLL hijacking isn't our only option for privilege escalation. Any user user-writable file that is used by a privileged process introduces the possibility of introducing a privilege escalation vulnerability. For example, here's a popular program that checks for a user-creatable text file to direct its privileged auto-update mechanism. As we can see here, the presence of a crafted text file can lead to arbitrary command execution. In our case, we have it launch calc.exe:

Installing to a subdirectory off of the system root

...