Finding Local Administrators on a Domain Member Stations

Published: 2019-04-24
Last Updated: 2019-04-24 11:48:34 UTC
by Rob VandenBrink (Version: 1)
1 comment(s)

Now that we've got a list of domain admins ( https://isc.sans.edu/forums/diary/Where+have+all+the+Domain+Admins+gone+Rooting+out+Unwanted+Domain+Administrators/24874 ), lets find all the accounts that have local Administrator rights.
Local Admin used to be a common thing, back in the early XP days when Windows Security was new.  It was common back then to see everyone's AD account have local admin on their own machine, so that they could do things like update the clock, install printer drivers, or install games when they took their laptop home.

Sound familiar?  Well, those days are gone (or they should be).  In 99% of cases, you absolutely, positively do NOT need local admin for anything on a domain member computer (especially if it's not a server) that's administered by IT staff.  You might need an extra right here or there, but even then, it's very likely that you don't.  Windows 10 and even Windows 7 both do a good job without giving folks admin rights.  (We won't talk about that dark Windows 8 detour that nobody took, but W8 does just as good a job on this score)

What local admin does give you is rights that you shouldn't have, to perhaps install malware that might then access system files that nobody wants changed.  And if you don't use LAPS, local admin on one station will likely give you local admin on ALL the stations, which from a malware point of view is as good as domain admin in lots of organizations.

So let's get on with it - to find local admins across the board, you'll want something that looks like this:

import-module ActiveDirectory

function get-localadmin {
  param ($strcomputer)
  $admins = Gwmi win32_groupuser –computer $strcomputer  
  $admins = $admins |? {$_.groupcomponent –like '*"Administrators"'}
  $admins |% {
    $_.partcomponent –match “.+Domain\=(.+)\,Name\=(.+)$” > $nul
    $matches[1].trim('"') + “\” + $matches[2].trim('"')
  }
}

$i = 1
$localadmins = @()
$targets = Get-ADComputer -Filter * -Property DNSHostName
foreach ($targethost in $targets) {
  write-host "Testing" $targethost.DNSHostName "," $i "hosts completed"
  if (Test-Connection -ComputerName $targethost.DNSHostName -count 2 -Quiet) {
    $admins = get-localadmin $targethost.DNSHostName
    foreach ($a in $admins) {
      $val = new-object psobject
      $val | add-member -membertype NoteProperty -name Hostname -value $targethost.name
      $val | add-member -membertype NoteProperty -name AdminID -value $a
      $localadmins += $val
      }
  ++$i
  }
}
$localadmins | export-csv -append localadminusers.csv

Note that this code will grab everything, so when it hits the domain controllers it'll enumerate domain admins (which is the honest truth when you think about it).  Note also that if a station is not on the network when you run this script, of course you won't be able to enumerate any user information from it.

Run this on your own domain, user our comment form let us know if you find anything unexpected!

===============
Rob VandenBrink
Compugen

Keywords:
1 comment(s)

Comments

Hey Rob, I'm trying to run the script, but I get this error. I have the Powershell AD Module installed.

At C:\Tools\Powershell\Collect Local Admins.ps1:8 char:22
+ ... $_.partcomponent –match “.+Domain\=(.+)\,Name\=(.+)$” > $nul
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token '–match “.+Domain\=(.+)\,Name\=(.+)$” > $nul
$matches[1].trim('"') + “\” + $matches[2].trim('"')
}
}
$i = 1
$localadmins = @()
$targets = Get-ADComputer -Filter * -Property DNSHostName
foreach ($targethost in $targets) {
write-host "Testing" $targethost.DNSHostName "' in expression or statement.
At C:\Tools\Powershell\Collect Local Admins.ps1:17 char:49
+ write-host "Testing" $targethost.DNSHostName "," $i "hosts complete ...
+ ~
Missing argument in parameter list.
At C:\Tools\Powershell\Collect Local Admins.ps1:17 char:71
+ ... write-host "Testing" $targethost.DNSHostName "," $i "hosts completed"
+ ~
The string is missing the terminator: ".
At C:\Tools\Powershell\Collect Local Admins.ps1:7 char:14
+ $admins |% {
+ ~
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken

Diary Archives