Introduction
Services, in Windows, are a critical component of the operating system and provide essential functions that keep our computers running smoothly, and hopefully securely. But did you know that these services could be exposing major vulnerabilities that put the security of your computers and network at risk? As a matter of fact, there are many applications that configure services incorrectly, by default, when their programs get installed. These misconfigurations can lead to a whole host of issues, some of the most serious being privilege escalation.
What is a service?
A Windows Service is a program that runs in the background on a Microsoft Windows operating system, without a user interface, and performs specific functions or tasks. Some services are designed to start automatically when the system starts and run continuously, even if there is no user logged in. Other services are designed to run only once, upon a user logging in. These services can run with the privileges of a specific account, which can be a local account or a domain account. This will be important later on. These services can also be configured to run as SYSTEM, which is a built-in account in windows that can do pretty much anything and everything. Again, remember this for later.
To view your system’s services, click on the windows icon or the search bar and type “services.” Then click on services. It should look something like this.
Once opened, it should look something like this. Keep in mind that most of the time you need Administrative privileges to modify windows services.
If you’re more of a console-type of person and you like using PowerShell for everything like me. You can use this to list all services along with some helpful information such as the service Name, the state, and the path to the service executable.
Get-WmiObject win32_service | select Name, DisplayName, State, PathName
Now, there’s a lot more to services. We’ve barely scratched the surface here, but for the purpose of this blog post, that’s enough information for now.
How Do Services Get Insecurely Configured?
When we see this type of vulnerability on penetration tests, it’s usually a result of one of a few things. Keep in mind these are not the only ways services can be vulnerable, just some of the more common ways.
Insecure Installation
First, many times programs install services incorrectly or configure unnecessary and overly permissive rights. This is one of the most common issues. It happens a lot more than we like to think and it’s a very hidden danger. Think about it. How often do you review the configuration of an application after you’ve installed it? Do you look at the folder structure and permissions? Do you review the permissions on registry keys or services that get created? We expect the installation to work and to configure things correctly. Sadly, many times that’s just not the case.
Admin Error
The second most common way we see services get insecurely configured is by intentional misconfiguration and human error. I’m lumping these together and we can just call this admin error for short. Many times, vendor documentation recommends configuring certain permissions for programs or services to run. Unfortunately, these recommendations from vendors are almost always more permissive than is actually required. But, it’s just easier for a vendor to claim their software needs these permissions than to try and figure out what permissions it actually requires. Other times it’s a result of an IT admin assigning insecure permissions or configuring services or folders incorrectly.
Regardless of the root cause, this is a very sneaky vulnerability that is difficult to spot if you’re not looking for it.
Common Insecure Service Configurations
There are a number of things that can go wrong with services. However, some of the riskiest misconfigures end up allowing for privilege escalation. That’s the key point here and why this can be a very risky vulnerability. Insecurely configured services may result in privilege escalation and/or the ability to run commands as the user who the service is configured to run as. Imagine if that service is running as a privileged domain account, like a Domain Admin. Yikes, that could be bad.
So what are some of the most common insecure service configurations? Based on what we see time and time again when performing internal penetration tests, we’re going to talk about:
- Unquoted Service Paths
- Insecure Service/File Permissions
- Insecure Service Executables
Unquoted Service Paths Vulnerability
What Are Unquoted Service Paths?
When the path to a service executable has a space within it, but the path is not wrapped with quotes (” “) within the service configuration, the service could be manipulated, such that an attacker could place their own executable somewhere in the path and their executable would be executed not the actual service executable.
How to Identify Unquoted Service Paths
A quick and easy way to find services with unquoted service paths is to open up PowerShell and run the following:
Get-WmiObject win32_service | select Name,PathName,StartMode,StartName | where {$_.StartMode -ne "Disabled" -and $_.StartName -eq "LocalSystem" -and $_.PathName -notmatch "`"" -and $_.PathName -notmatch "C:\\Windows"} | Format-List
If there are any hits it would look something like this.
This PowerShell command is using Get-WmiObject to query local services using WMI, Windows Management Instrumentation. It’s selecting only services where the start mode is Disabled, the account is LocalSystem, the service executable path is not c:\windows and the service executable path does not have “”. You can of course experiment with this by removing the check for services running as LocalSystem. You could also remove the start mode to find services that may have unquoted service paths but may be currently disabled.
The red box is the full path to the service executable, Totally.exe. Notice the arrows are pointing to places in the path where there are spaces. This is where the unquoted service path vulnerability lies. We can also see that the service is set to “Auto.” This is the service Startup Type. There are a couple of different startup types services can have, auto being one of them. Auto means the service starts automatically when the computer turns on. We also see that the service is currently Stopped.
Because there are spaces in the path, and there are no quotes surrounding the Path, this service could potentially be abused. There’s some technical nitty gritty here, but the important thing to know is that this vulnerability is a result of the way windows handles service paths when there are spaces. Using the example above, when windows tries to start this service it will look at the following paths in order and append “.exe” at the end of each space until it finds a service executable to start. So, in order to start Totally.exe the system would interpret the path above as:
- C:\Program.exe
- C:\Program Files\Legit.exe
- C:\Program Files\Legit Software\Totally.exe
- C:\Program Files\Legit Software\Totally Legit\Totally.exe
If an attacker is somehow able to place an executable anywhere in that path, with the correct name, they could essentially hijack this service and execute code as the user whose running the service.
What the screenshot above demonstrates is what abuse of unquoted service paths may look like in practice. The blue box and text (right) indicate the path to the real service executable. This is the one this service was originally configured to use. The red box and text (left) show that there is another service executable, higher up in the path. This “malicious” service executable is the one that’s actually getting executed.
Unquoted Service Paths Prerequisites
The only requirement to abuse this unquoted service path vulnerability is that you have to be able to plant a service executable somewhere in the path of the real service executable as we showed above.
Insecure Service/File Permissions Vulnerability
What Are Insecure Service Permissions?
When services have incorrect, misconfigured, or insecure permissions set, a low-privilege user may be able to modify the service’s settings, such as the service executable path or other properties.
How to Identify Insecure Service Permissions
Just like file and directory permissions, you can view service permissions in a number of ways. You could use sc sdshow
, which is built into windows but when it comes to service permissions, I like to use AccessChk from the Sysinternals suite. You can check the permissions of a service like this:accesschk.exe -c LegitService -l
Again, using the same service as the previous examples, we can check to see if any low-privilege users have any permissions on this service.
From the screenshot above we can see that the lowprivuser user tried to replace Totally.exe with Malicious.exe but the operation was denied, no access. We can also see that after running accesschk on the service, “Everyone” has “SERVICE_ALL_ACCESS”, which means all users have full access to do whatever they want with that service.
If you remember, this service is running as SYSTEM. So again, all users have full permission to modify the settings and attributes of this service.
Using built-in windows commands (sc config binpath=
) we can modify the “binpath” of this service so that it points to a “malicious” executable instead of the original executable. As you can see, the blue box shows the binpath of the service executable before modification and the red box shows the binpath of the service executable after modification.
Since Everyone, including lowprivuser, has full access to this service, not only can anyone modify the binpath, but anyone could also restart the service and execute a malicious program, which would run as SYSTEM.
What are Insecure Service File Permissions?
When service files have incorrect, misconfigured, or insecure permissions set, a low-privilege user may be able to modify the service’s settings, such as the service executable path or other properties.
How to Identify Insecure Service File Permissions
The method for discovering this vulnerability revolves around enumerating permissions of all directories which services are configured to execute from. There are a number of options for doing this, including using AccessChk from the Sysinternal Suite. You can also use built-in programs such as icacls.exe, which is a tool that can be used to view and modify permissions in windows.
Open up a command prompt and type icacls <file/folder path> like this:
Using the same service from the first example as the target we can run icacls "C:\Program Files\Legit Software"
which is this service’s root folder. The output of this command shows a few things that are important to us.
First, the abbreviations you see in () have specific and unique meanings. These represent specific rights (permissions) that are applied to the user or group shown. In the screenshot above we see that “Everyone” has (OI)(CF)(F). We don’t need to go into detail on all of these, but we will cover a couple of important rights to keep in mind.
- (F) – Full access
- (RX) – Read and execute access
- (W) – Write-only access
- (M) – Modify access
So, the “Everyone” group has Full Access to this directory. In windows, inheritance is enabled by default. Since Everyone has Full Access to the Legit Software directory, it would by default, also have Full Access over all sub-directories and files.
Hopefully, you can start to see the danger here. If you remember from our previous example, we have a service executable that lives in this directory, that’s running as SYSTEM.
Since all users are a part of “Everyone” the lowprivuser user is able to modify anything and everything in that directory. This includes the service executable.
This screenshot shows the lowprivuser user copying Totally.exe to Totally-original.exe, then overwriting Totally.exe with Malicious.exe. Now, the next time this service starts, the malicious executable will be run. However, there’s a catch.
By default, non-administrators cannot restart or stop services. So the lowprivuser user is not able to manually restart this service. However, since this service is set to Auto, the user could simply reboot the computer and when the computer starts up again the service will be executed. Of course, if the user could crash the service somehow and cause it to restart, that could also be a way of restarting the service without rebooting.
Vulnerability Prerequisites
In order to exploit insecure service file permissions a couple of things have to be possible. First, the account attempting the abuse has to have some permissions to modify the files/directories where the service executable is configured to execute from. Second, the account has to be able to restart the service. Remember though, if the service is set to auto, a simple reboot would cause the service to restart.
Insecure Service Executable Vulnerability
What Are Insecure Service Executables?
When the service executable itself has insecurely configured permissions this could result in a low-privileged user being able to modify and/or replace the service executable itself.
How to Identify Insecure Service Executables
Just like the previous examples, we can use a number of tools to find insecure permissions on service executables. In the screenshot below, I show using both Accesschk and icacls to view the permissions on the service binary.
When using accesschk we can see that “Everyone” has RW or Read & Write Permissions. When using icacls we can see the permissions are shown as (F), meaning Full Access. With that in mind, a low-privilege user would be able to modify and/or replace this executable with their own malicious executable.
Vulnerability Prerequisites
The prerequisites for this vulnerability are similar to those of insecure service file permissions. First, the account attempting to perform the abuse has to have some permissions to modify the service executable. Second, the account has to be able to restart the service. Just like the others, if the service is set to auto, a simple reboot would cause the service to restart.
How To Mitigate These Vulnerabilities
While these vulnerabilities can go unnoticed and they may not be immediately obvious, they are fairly straightforward to fix, once they have been found. The mitigations for these are similar and all tie into one another, which is why I saved this part for the end.
There are many vulnerabilities that can be solved by adopting least privilege. It’s recommended to implement least privilege and only allow access to modify services to those accounts that require it. This is especially important for end-user systems. Unfortunately, it’s not uncommon to see services abused after their workstation becomes compromised. The safest option is to assume that end-users will at some point get compromised and ensure systems are resilient to that fact. If you’re adhering to a least privilege model, attackers are going to have a much tougher time.
To say that a slightly different way, ensure that low-privilege users (e.g. Domain Users, Authenticated Users, Users, Everyone, or similar) do not have permission to modify or write service executables. Additionally, ensure these low-privilege users do not have Full Control permission to any directories that contain service executables.
Lastly, if there are services that have spaces in the service path but are not wrapped with quotes, those can be fixed by simply wrapping the service path in quotes (“).
How to Scale the Identification of Insecure Windows Services
So far we’ve been discussing one-off and ad-hoc cases of insecure windows services. I wanted to share the fundamentals of how to identify when a service may be vulnerable so that you know what to look for. On any given system in your environment, there are at least a few dozen services and applications. Scale that out to all of the systems in your environment and you have a lot of systems and services to check. That’s part of the reason that your gold image, system deployment, and hardening processes are so important. But, what are some strategies for reviewing all your systems for these insecure services?
Sample Your Systems
You could review a sampling of your systems. Let’s say you have 100 end-user workstations and 50 servers. Perform a manual review of let’s say, 10%. Review 10 workstations and 5 servers. If you discover any insecure services, you can probably assume that the other systems are affected. If you don’t find any vulnerable services, document which systems you checked and review another group of 10/5 next quarter.
Try To Review Them All
The other option is to use your asset inventory tools, endpoint management tools, or possibly even some vulnerability scanning tools to try and review all the services on all of your endpoints. Below are a couple of options for you to consider.
PDQ Inventory Saves The Day
One of my favorite asset inventory tools is PDQ Inventory. It’s easy to install and use. It’s quick and accurate. It’s inexpensive. It’s a really great product. It makes finding unquoted service paths on all your windows computers extremely easy. From within PDQ Inventory, select Tools → Run Command. From there, copy and paste that PowerShell code from above into the command window and make sure ps1 is selected. Then click Choose Computers and add the computers you want to scan. Then click Execute. From there, you can even click Save Tool and save this in your Tool menu so you can use it again.
If there are any hits, they show up like the screenshot above. If nothing is found you should see Return Code: 0
in the results window. As you can see PDQ can be pretty awesome for this kind of thing. You can then use the next best tool, PDQ Deploy, to issue a fix to all machines. Heck, you could even set up a recurring scan with PDQ Inventory that identifies unquoted service paths, puts those computers into a collection, and then use PDQ Deploy to automatically deploy a fix. Pretty slick if you ask me.
The above screenshot shows one possible way to create a dynamic collection in PDQ Inventory for computers where there are services with unquoted service paths. Of course, testing is advised. This is a very rough solution, but it does illustrate the point.
Vulnerability Scanners May Be Able To Help, Sorta
Fortunately, vulnerability scanning tools such as Nessus may be able to detect some of these insecure windows services. For example, unquoted service paths or services with insecure permissions may get flagged by Nesssus, but only in their default form, which I’ve shown here. By default, I mean, when services have overly permissive rights for Everyone, Domain Users, Authenticated Users, or Users. What Nessus won’t catch is when some other group or user is configured with more permissions than is necessary. Or when the permissions are not as obvious as SERVICE_ALL_ACCESS or Full Access. This is one of the reasons that manual inspection, regular reviews, and penetration testing are so important. Vulnerability scanners cannot possibly find all the vulnerable things. Defense in depth, this is the way.
Closing
If you’ve made it this far, thank you. I hope this blog post has been informative for you. My goal with this blog post was to describe some of the most common ways windows services can be insecurely configured, why it’s a risk, and provide some recommendations for identification and mitigation. If you’ve read this post and were looking for more or if there’s any information you feel is missing, please let me know and I’d be happy to revise it.