Threat Level: green Handler on Duty: Xavier Mertens

SANS ISC: Windows Service Accounts - Why They're Evil and Why Pentesters Love them! - SANS Internet Storm Center SANS ISC InfoSec Forums


Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!
Windows Service Accounts - Why They're Evil and Why Pentesters Love them!

Windows Service Accounts have been one of those enterprise "neccessary evils" - things that you have to have, but nobody ever talks about or considers to be a problem.  All too often, these service accounts are in the Domain Admins group, with passwords like "Service123", "S3rvic3" or something equally lame.  And all too often, application vendors that use these services insist on just such a configuration.

Why is using actual service accounts a bad thing?  Aside from the fact that the passwords are generally set to never change, the passwords are stored in the registry, in a text format that is easily captured to arrive at the actual password.  Needless to say, this generally allows an attacker to fly under the radar and move laterally to other hosts - pillaging your AD Domain at will.

Enumeration:
So, how do we find these service accounts?  It's the same method, whether you are doing this to protect your assets, or if you are in a Penetration Test or Security Assessment.  List all the services for all stations in the domain, and winnow out the ones that have service accounts (either local or domain) attached to them.

In days gone by, I would have used WMIC:

First, look at "getservices.cmd":

REM one or both of
netdom query server | find /v "List" > targetlist.out
netdom query workstation | find /v "List" >> targetlist.out

for /F "tokens=1" %%S in (targetlist.out) DO call servicelist.cmd %%S  >> services.out

type services.out | find /v /i "LocalSystem" | find /v "LocalService" | find /v /i "NetworkService"


where servicelist.cmd looks like:

wmic /node:%1 service get systemname,displayname,started,startmode,Startname

This will give you a list of all services that use local or domain accounts, what machines they are installed on, if they are running and if they are enabled, disabled or set for manual control.  However, this takes **forever**, especially the netdom command!  How can we do this in Powershell?
 

Enumeration Again - with Powershell:

So, if you've used the  WMIC approach to recover windows Service account information in a reasonably sized AD Domain, you've likely found it to be is a very sl-o-o-o-w process - we'll see that it runs much faster using Powershell.

First, let's try the "Get-Service" cmdlet.  

get-service -computername $TARGET | format-list
....
Name                : WwanSvc
DisplayName         : WWAN AutoConfig
Status              : Stopped
DependentServices   : {}
ServicesDependedOn  : {PlugPlay, NdisUio, RpcSs, NlaSvc}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : False
ServiceType         : Win32ShareProcess
....

We see here that get-service doesn't give us service account login information - in fact it doesn't give us a lot of things about the services that you'd expect to see.  What to do?  Use WMI within Powershell!

get-wmiobject win32_service -computername $TARGET | format-table systemname, displayname,startname, state

How do we then link this up to a list of computers in the domain?  Use the Get-ADComputers cmdlet of course!  (You might need to run "import-module activedirectory" on older systems)

So, linking it all together in a one-liner:

get-adcomputer -filter * | foreach { Get-WmiObject Win32_service -Computer $_.name } | select-object systemname, displayname,startname, state | export-csv services.csv

Will get you the list of all services on all hosts in the domain.  I normally grab the entire list, then filter it, just as in the WMIC example, to find our  "problem" services, the hosts that they're running on and especially the service accounts that are in use:

type services.csv  |  find /v /i "LocalSystem" | find /v "LocalService" | find /v /i "NetworkService"

Fixing the Problem
Microsoft has come up with a decent way to mitigate this issue.  Where possible, have your services run as "LocalSystem", "NT AUTHORITY\LocalService" or "NT AUTHORITY\NetworkService"
These settings are run levels for services only (they can't be used for interactive login), with differing security permissions, but NO PASSWORD.  What this means is that the service has the authority that it needs, but there isn't a password to crack, and the account can't be used for a normal interactive login session.

Tools like Metasploit can of course be used to run processes on a target (compromised) host with these privilege levels, but this service account approach is still way better than using actual accounts with real passwords.

If you've got a "neater" way of enumerating service accounts, especially in Powershell, please use our comment section - we'd love to hear from you!

===============
Rob VandenBrink
Metafore

Rob VandenBrink

469 Posts
ISC Handler
It would also be interesting to see similar for scheduled tasks vs services.
BigMcLargehuge

1 Posts Posts
The information provided and the "fix" provided is great, but a better/more helpful fix would be disabling unnecessary services.
We all know every version of Windows comes with boat load of services, the purpose of some of them is not fully known.
I've tried to find a definitive document from a reputable source to identify which services need to be disabled on different versions of Windows, but so far I've come up empty.
If anyone knows of any, please let me know.
AAInfoSec

49 Posts Posts
Nice way to enumerate the service accounts. Useful because where I work the service accounts (when absolutely required) are required to be unique to a service/server combination. So if one account is compromised someone cannot leverage the account on other servers. Along with prohibiting network and console logon. Agreed they are evil just because of the amount of effort to deploy them securely.
Rick

6 Posts Posts
have you looked into the DISA PPSM? the CAL list is PKI/CAC enabled so if you are not government affiliated then you probably do not have access to that list specifically, although some pages are publically available.
kyle

5 Posts Posts
Server 2008 R2 and higher supports Managed Service Account; these can be used for services such as SQL Server, Exchange and other services that requires a user credential, perhaps to access a network share. The service needs to be configured by PowerShell, and password is managed automatically by Windows.

More details at https://technet.microsoft.com/en-us/library/dd560633

If on Server 2012, can check out Group Managed Service Accounts
Mike7

42 Posts Posts
Nice post. There are a couple of syntax issues though.

1. Using "get-adcomputer" without a filter will prompt you to provide one when you run it. When prompted, you can type "*" and it will dump the computer accounts. If you don't want to get prompted, change the command to "get-adcomputer -Filter *"

2. In your "get-adcomputer" command, piping to "format-table" prior to "export-csv" will screw up the output and you'll just get a bunch of junk in the .csv. If you just want to export those 4 fields, use "select-object" instead of "format-table". "format-table" is a display filter meant for use in the console only so it should only be used if you want to view output in the console, not an exported file.

You can also use "import-csv" instead of "type" to analyze the .csv if you want per-field analysis as it will preserve the csv field boundaries where "type" will just dump the lines.

Finally for this to work, you need RPC access (TCP 135) and admin rights on the machines you are querying with "Get-WmiObject" to retrieve the service info remotely.
Inspector16

8 Posts Posts
Good catch, and thanks! I built my scripts iteratively, and my cut/paste I think was out of sync with my testing ..
I'll update the examples
Rob VandenBrink

469 Posts Posts
ISC Handler
No I work in the private sector. I tried accessing CAL & received authentication error, as expected. Thanks for the suggestion though!
AAInfoSec

49 Posts Posts
Reply to Rob & Inspector16:
I tried running this, but I got "The RPC server is unavailable." error. I ran it as domain admin, Windows firewall is off, tcp 135 is listening, WMI svc running.
However, this works on local computer (Windows 7) and remotely (Windows Server 2008) by not using "get-adcomputer" and only using "get-WmiObject".
I did import-module activedirectory.
AAInfoSec

49 Posts Posts
AAInfoSec:

Based on your description, it seems that just the "get-adcomputer" part doesn't work for you. I grabbed a pcap while running "get-adcomputer <computername>", and discovered that I hit the DC on TCP 9389 so you'd need that available through the firewall as well to run that cmdlet. This is "AD DS Web Services" according to https://technet.microsoft.com/en-us/library/Dd772723%28v=WS.10%29.aspx. "Get-WMIObject" requires TCP 135 which looks like it is already open for you to the remote targets.

To get around the port limitation of "get-adcomputer", I had to go back to methods of searching AD before "get-adcomputer" existed... You can use the following command instead of "get-adcomputer -Filter *". This will talk to the DC over LDAP (TCP 389):

([adsisearcher]"objectcategory=computer").findall() | ForEach {$_.Properties}

The pcap for "[adsisearcher]" shows it is waaaaaayyy chattier than "get-adcomputer", but you shouldn't have an issue with LDAP being open between a workstation and a DC.
Inspector16

8 Posts Posts
I'd counter the idea a better fix would be disabling services. At some point you've disabled what you can and you're left with services you need to secure. My primary responsibilities are system administration and not full time security. A lot of "best practice" or guidance material will tell you to disable unnecessary services. I've still got a system to run, so now what?

I'm already in a project to do clean up on service accounts. This information will be useful in doing that clean up. I can also use it to audit what others have done on the network. I could troll through my event log server, but looking at the script this looks like a more straightforward and less time consuming way to get the same answers.
Anonymous
Posts
One way to monitor for possible misuse of service accounts is this:

Since service accounts should be only be used on a (mostly) static number of machines, create a list of those machine/service-account pairs and monitor your authentications across the network. If any service-account authenticates to a machine where it has not done so before, investigate. It could be totally legit (new service or old service being deployed to new location) or it could be something more suspicious/malicious.

This can be done with a powershell script or a SIEM.
Anonymous
Posts
I believe the question was in regard to finding summary information helpful to deciding what services can and cannot be safely disabled in a given circumstance. I have not had to make similar decisions in a number of years, but at the time, concise and accurate information could be difficult to find. NIST white papers provided some, as did CIS documents. However, I found the blackviper.com site to be my best source of practical information to get started. I haven't used it since, but it does appear the maintainer is attempting to keep current.
Anonymous
Posts
Why switch over to the command prompt and use find when you can use powershell for that too?

get-adcomputer -filter * | foreach { Get-WmiObject Win32_service -Computer $_.name } | select-object systemname,displayname,startname, state | ConvertTo-csv | ForEach-Object { if($_ -notmatch "networkService" -AND $_ -notmatch "LocalService" -AND $_ -notmatch "LocalSystem") {$_} }

Add

| Set-Content "services.txt"

if you want it to a file instead of outputting to standard out
Justin

8 Posts Posts

Sign Up for Free or Log In to start participating in the conversation!