Threat Level: green Handler on Duty: Rob VandenBrink

SANS ISC: Internet Storm Center - SANS Internet Storm Center Internet Storm Center

Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!

Latest Diaries

Service Accounts Redux - Collecting Service Accounts with PowerShell

Published: 2019-04-25
Last Updated: 2019-04-25 18:45:03 UTC
by Rob VandenBrink (Version: 1)
0 comment(s)

Back in 2015 I wrote up a "find the service accounts" story  - (yes, it really has been that long).  The approach I wrote up then used WMIC.  Those scripts saw a lot of use back in the day, but don't reflect the fastest or most efficient way to collect this information - I thought today was a good day to cover how to do this much quicker in PowerShell.

Why would you need to do this?  In a penetration test or an internal security assessment, you normally want to enumerate any services that don't use the built-in Microsoft Service Accounts.  This is because actual service accounts almost never see a password change, and almost always are given local administrator or domain administrator rights.  Mainly because if you're going to be a software vendor that's dumb enough to still use Windows XP era service accounts, you might as well go all the way and make those accounts Domain Admin for any malware that wants to collect those passwords (stay tuned, we'll be doing this tomorrow!).  Microsoft's current recommended approach is to use the various built-in service accounts for services.  These don't have passwords, and can't be used for lateral movement to other workstations or servers.

That being said, let's pretend to be malware and collect those service accounts across an AD domain!

$targets =get-adcomputer -filter * -Property DNSHostName
$vallist = @()
$i = 1
$count = $targets.count

foreach ($targethost in $targets) {
  write-host $i of $count -  $targethost.DNSHostName
  if (Test-Connection -ComputerName $targethost.DNSHostName -count 2 -Quiet) {
    $vallist += Get-WmiObject Win32_service -Computer $targethost.DNSHostName | select-object systemname, displayname, startname, state
$vallist | export-csv all-services.csv

A few things to discuss.
First of all, $i, $count, and the "write-host" line are there just so that if you have several thousand hosts to enumerate, you can ensure that your script isn't hung, and how far along it might be at any given time.

The "Test-connection" check is there so that you don't wait several seconds trying to connect up to remote hosts that might not be up.

Also, this can only enumerate hosts that are actually up and accept a connection - you likely want to run this script during the day.  If you start your script and see that it's going to take longer than a business day to complete (for a larger domain for instance), you might want to pause it towards the end of the business day, and restart it the next morning after everyone is back at their desks.

OK - so now that the script has run, what have we found?  What we have is the list of **all** services that are installed on all hosts in the domain, along with the account that's used to start the service.

This is great for system admins looking for one thing or another, but for most security purposes you don't want the ones that are using the built-in service accounts.  To filter those out, you want to remove any service that is started by these accounts:

  • NT AUTHORITY\LocalService
  • LocalSystem
  • NT AUTHORITY\NetworkService
  • or an empty field

To do this, add these lines to the bottom of your script

$filtlist = @("LocalService", "LocalSystem", "NetworkService", "NT AUTHORITY\LocalService", "NT AUTHORITY\NetworkService", "NT AUTHORITY\NETWORK SERVICE", "NT AUTHORITY\LOCAL SERVICE")
$TargetServices = $vallist | Where-Object { $filtlist -notcontains $_.startname }

$TargetServices | export-csv bad-services.csv

Things to note in this bit of code?  the "contains" and "notcontains" operators are case-insensitive, so you upper / lower case doesn't matter in your filter.

So, what can we do with this list if we're attacking a domain?  We can use the domain admin and local admin lists that we sleuthed yesterday, and see which of these service passwords are domain admins!

Let's take that list of $TargetServices, and list the offending accounts:

$TargetSVCAccounts = $TargetServices.startname | Sort-Object -Unique


In a different domain it's common to also see service accounts that are local to the machine being enumerated, often those will have local admin rights, and often you'll find that those same (local admin) service userid and password are used on all workstations and often on all servers - which gets you almost the same access as domain admin rights (oops).

Normally the lists that come out of these scripts are short enough that I can compare them by eye to the list of local and domain admins we collected in yesterday's story.  But if you have one of those unfortunate domains where dozens or hundreds of people have domain or local admin rights, you might want to add a bit more code:

$SVCDomAdmins = @()
$Admins = $DomainAdmins.SAMAccountName.toupper()

Foreach ($Acct in $TargetSVCAccounts) {
    $a = $Acct.toUpper().Trim("AD\").Trim("@AD.COM")
    if ($Admins.Contains($a)) {$SVCDomAdmins += $a}

$SVCDomAdmins | Sort-Object -Unique | export-csv Service-DomainAdmins.csv

To find Service Accounts that are local admins, it's the exact same code, but replace line 2 with "$Admins += $localadmins.AdminID.toupper()"

If you have a minute today, try this on your domain - use our comment form to let us know if you find anything interesting!

What will we do with this list of accounts next?  Stay tuned for the next installment tomorrow :-)


Rob VandenBrink

0 comment(s)

Unpatched Vulnerability Alert - WebLogic Zero Day

Published: 2019-04-25
Last Updated: 2019-04-25 18:28:38 UTC
by Rob VandenBrink (Version: 3)
8 comment(s)

The news today is full of a new deserialization vulnerability in Oracle WebLogic.  This affects all current versions of the product (the POC is against 10.3, but 12.x versions are also affected).  The vulnerability affects the wls9_async_response package (which is not included by default in all builds), so the workaround is to either ACL the Z/_async/* and /wls-wsat/* paths, or delete wls9_async_response.war.  A successful attack gets the attacker remote code exec on the vulnerable server.

The root cause here seems to be that the affected WAR components ingest and process all serialized data, and have a blacklist of "bad" content.  What this means to me is that we're likely to see a number of similar vulnerabilities / attacks crop up over the next while, until Oracle changes this approach.

Indications are that this is in the "tens of thousands" of affected sites, not hundreds or thousands or millions (not yet at least).

The vulnerability is posted as CNVD-2018-07811 (China National Vulnerability Database) at  We don't have a CVE yet.

This bug was originally disclosed by the China Minsheng Banking Co.  There's a good write-up by the KnownSec 404 Team with  a bit more detail here:

This comes just one week after Oracle's "Patch Everything" Critical Patch Update (CPU) last week.  The next CPU isn't due for 3 months, so it'll be interesting to see what the out-of-band response patch or patches (if any) to this might be.

Stay tuned - we'll udpate this story as we get more information - in particular if we see attacks in the wild we'll post IoC's as we get them.

======= Update 1 =======

Thanks to our reader who commented below!

The matching CVE number for this is CVE-2018-2628, which was identified as patched last year (Oracle's CPU - Critical Patch Updates found here ).  However the POC mentioned was against a patched server, so I guess the patch isn't complete - nor can it be given Oracle's approach against this issue.

======= Update 2 =======

POC posts are at:

POC code is here (we have not tested this, so use this at your own risk):


8 comment(s)

Where have all the Domain Admins gone? Rooting out Unwanted Domain Administrators

Published: 2019-04-24
Last Updated: 2019-04-25 12:47:55 UTC
by Rob VandenBrink (Version: 1)
1 comment(s)

Ever been in an internal security assessment or penetration test, and need to list all domain admins?
First of all, why would you need to do that?  All to often, you'll find that way too many people have domain admins - you know, "just in case"
People like:

  • developers - who needed local admin on that one server, that one time, but we gave them domain admin and then forgot
  • or developers, because don't all devs need domain admin?
  • IT VP's and dev managers, because they used to be admins
  • the CEO, because they insisted
  • Steve, because Steve needed to update the timezone or install a printer at home, and the helpdesk mistakenly gave Steve domain admin rights for that

You get the idea.

So, aside from the people that are actual members of "Domain Admins", there are lots of groups that have elevated privileges in a domain, so we'll need to enumerate all of those too.  And you can put groups into groups, so we'll have to recurse through that mess to get the full list of users.  This can take quite a while in the GUI, but it's only a few lines of code in PowerShell:

$DomainAdmins = @()
$a = $()
'Domain Admins', 'Administrators', 'Enterprise Admins', 'Schema Admins', 'Server Operators', 'Backup Operators' | ForEach-Object {
    $groupName = $_
    $a = Get-ADGroupMember -Identity $_ -Recursive | Get-ADUser | Select-Object Name, samaccountname, @{n='GroupName';e={ $groupName }}
    $DomainAdmins += $a
$DomainAdmins | export-csv alldomainadmins.csv

This will list all the Admin users, and the group membership that put them there.  So you might find the same person on this list a few times (but that's a good thing in most cases).

If you just want the de-dup'd list of unique userids (without how they got there), add this snip to your code:

$uniqadmins = ($DomainAdmins | select SamAccountName,name )  | Sort-Object -Property samaccountname -Unique
$pctdomadmins = ($uniqadmins.count / (Get-ADUser -filter * ).count) *100
write-host $pctdomadmins "percent of domain users have domain admin rights"
$uniqadmins | export-csv uniqadmins.csv

When you run this against your domain, what is your percentage?  Did you find any surprises?  Please, use our comment form and let us know!

1 comment(s)

If you have more information or corrections regarding our diary, please share.

Recent Diaries

Where have all the Domain Admins gone? Rooting out Unwanted Domain Administrators
Apr 25th 2019
21 hours ago by Rob VandenBrink (1 comment)

Finding Local Administrators on a Domain Member Stations
Apr 24th 2019
1 day ago by Rob VandenBrink (0 comments)

Malicious VBA Office Document Without Source Code
Apr 23rd 2019
2 days ago by DidierStevens (0 comments)

.rar Files and ACE Exploit CVE-2018-20250
Apr 22nd 2019
4 days ago by DidierStevens (1 comment)

Analyzing UDF Files with Python
Apr 19th 2019
6 days ago by DidierStevens (0 comments)

View All Diaries →

Latest Discussions

Domain registration date plugin for email?
created Mar 30th 2019
3 weeks ago by Anonymous (0 replies)

Run Extracted binaries from mirror traffic on cuckoo
created Feb 6th 2019
2 months ago by ching (1 reply)

Another sextortion email
created Feb 5th 2019
2 months ago by Anonymous (0 replies)

Two-factor authentication: Why do I need it? What are the best apps?
created Jan 27th 2019
2 months ago by Russell (0 replies)

sextortion Mail
created Jan 10th 2019
3 months ago by Anonymous (0 replies)

View All Forums →

Latest News

View All News →

Top Diaries

Wide-scale Petya variant ransomware attack noted
Jun 27th 2017
1 year ago by Brad (6 comments)

Using a Raspberry Pi honeypot to contribute data to DShield/ISC
Aug 3rd 2017
1 year ago by Johannes (13 comments)

Second Google Chrome Extension Banker Malware in Two Weeks
Aug 29th 2017
1 year ago by Renato (0 comments)

Detection Lab: Visibility & Introspection for Defenders
Dec 15th 2017
1 year ago by Russ McRee (2 comments)

Maldoc with auto-updated link
Aug 17th 2017
1 year ago by Xme (2 comments)