This article is contributed. See the original author and article here.

Part 2 – Deploy LAPS, Check!  You’re all set, right?  Maybe… 


 


Hi Team, Eric Jansen here to follow up on some auditing suggestions that I mentioned for those of you that have LAPS deployed in your environment, in part one of this series.  If you haven’t read part one, then part two likely won’t make much sense, so I encourage you to read that as a prerequisite.  Since publishing part one, I’ve had questions, concerns, and feedback from readers, customers, friends, and other Microsoft engineers.  In today’s blog, I’d like to address some of those to hopefully provide even more clarity on why auditing LAPS in your enterprise is so important. 


 


I’m going to start by addressing a comment that I got from a cyber security engineer: 


 


Security Engineer:  “Our users don’t have the Remote Server Administration Tools (RSAT) on their workstations, so I don’t see this as a big risk”. 


 


Me: “Uh oh.  If you think that, being a security guy, then you probably aren’t the only one.” 


Me: Proceeded to show examples of why having RSAT on the workstation doesn’t matter. 


 


Note to self: Write this down – good content to share… 


 


Ok, so why was this so alarming to me?  In short, it’s because you don’t need the RSAT tools to accomplish this.  You could use any number of tools to search a directory with the Lightweight Directory Access Protocol (LDAP), to include some that have no prerequisites and are built into the Windows OS.  I just need to be a regular user with a relatively modern Windows OS that has PowerShell on it, and I have the ability to harvest LAPS passwords if delegations aren’t kept in check on computer objects.   


 


Case in Point:  The PowerShell ADSI Searcher Type Accelerator…  The [ADSISearcher] Type Accelerator is a wrapper for the DirectorySearcher .Net Class, which comes from the System.DirectoryServices Namespace and is used to perform queries against the Active Directory Domain Services hierarchy using LDAP. 


 


Below is a basic snippet of code that I wrote to demonstrate my point.  By running this as a regular user in PowerShell, if the extended rights on the computer object aren’t set correctly, then the password harvesting fest will begin: 


 


 

$ADSISearcher = [ADSISearcher]'(&(objectclass=computer)(ms-mcs-admpwd=*))' 
$AllComputers = $ADSISearcher.FindAll() 
$DailyHarvest = @() 

Foreach($Comp in $AllComputers){ 
$DailyHarvest += New-Object psobject -Property @{Name = $Comp.properties.name; Password = $Comp.properties.'ms-mcs-admpwd';} 
} 

$DailyHarvest 

 


 


Next is a common question that I get asked by customers: 


 


Customer:  “After running through your LAPS auditing blog and seeing less than desirable results in the findings from our environment, we’d like this addressed immediately, but on an on-going basis.  What do we need to do to regularly audit this?” 


 


Me:  “Great question, maybe we just setup a group managed service account to run a scheduled task and if there are any findings, email a notification to a distribution list that includes the administrative support team with suggested investigative and fix actions.” 


  


Like I said in part one, sometimes you just need that attention getter, but once the customer sees the findings, in most cases, they’ll want to fix it.   


 


For those that do want to patch things up, you’d need to do scans of the environment like you would with anything else.  One way to accomplish this would be to use a Group Managed Service Account (gMSA) to run on a scheduled task to run something similar to the one liner that I pointed out in part one, but maybe ‘out’ the list of machines with bad ACLs to a file on a share: 


 

Get-ADComputer -Filter * -Properties MS-Mcs-AdmPwd | Where-Object MS-Mcs-AdmPwd -ne $null | Select -ExpandProperty Name | Out-File $Path

 


An item of note however is that a gMSA is derived from the Computer Class, which is derived from the User Class, which is why the gMSA has an attribute for primaryGroupID.  If you look at said primaryGroupID for a gMSA you’ll notice that the default primary group is GROUP_RID_COMPUTERS, better known a “Domain Computers”.  With that said, you’ll want to add the gMSA to the “Domain Users” group to get that same ‘apples-to-apples’ comparison so that it more closely mirrors the findings that I outlined in part one, where we would see pre-staged computer objects given excessive rights, again, the most common being “Domain Users”, “Authenticated Users”, ”BUILTINUsers”, and “Everyone”.  Is it a true ‘apples-to-apples’ comparison though?  Not exactly, because when the gMSA runs, it’s also a member of “Domain Computers”. 


 


In one customer environment where we set this up, the scheduled task ran, but shockingly it came back with 1200+ MORE passwords (this was a large enterprise consisting of about 100K machines) when running under the gMSA context.  The reason was because for those 1200+ machines, “Domain Computers” was given the “All Extended Rights” permission.  So in their case, that also needed to be cleaned up.


 


But why does that matter if a regular user won’t be running as a gMSA?  Great question! 


 


You’re correct, the regular user wouldn’t be running as a gMSA, but it’s relatively easy to run as a computer, which has the same group membership (to “Domain Computers”).  As an example, let’s say that your regular user account had an initial harvest, collecting passwords from 900 machines.  Maybe a third of those are turned off or stale and permanently offline, and let’s say that for one reason or another you just can’t connect to another third of those.  So, we’ll say that there’s roughly 300 machines that are online and you ARE able to connect to those machines.  Now it’s just a matter of that user jumping on one of those machines as an admin and then running the same one line of code that they ran as a regular user, but this time as System.   


 


For those that don’t know what that does, System has extensive privileges on the local computer, but more importantly for our mission of harvesting more LAPS passwords, it “acts as the computer on the network“.   


 


So, if I’m running as System on one of the machines that I essentially was “given” the password to, when accessing a resource over the network it would be seen as the ComputerName$, which by default, will belong to ‘Domain Computers’.  With that being the case and if “Domain Computers” was given the “All Extended Rights” permission, now I just got the keys to another 1200+ computer accounts…and the day just got worse. 


 


Oh, but there’s more… 


 


The last thing that I want to talk about is more of an interesting scenario that’s recently happened that’s very relevant, makes the LAPS password harvesting even more scary, and should hopefully convince those who don’t see this as a big deal that maybe they really should audit the LAPS permissions in their environment: 


 


Customer:  “In doing some coding to validate group members of “Protected Groups” I noticed that someone changed the password of the Administrator account for the domain, but everyone says that they didn’t do it.  I need some help figuring out what’s going on. 


 


Me: “Interesting, let’s dig in…” 


 


In this scenario, we ran the following command to figure out when and where this change occurred: 


 


Repadmin /ShowObjMeta <DomainController> <”DN Path of the Administrator Account”> 


 


When digging in, we found that the change was done at a DC at a remote site, at X time, on the prior day.  So, he jumps on that DC, opens the security log and scrolls down to that timeframe, down to the second.  In that second there were probably 40 or 50 events, BUT he found the event where the password change was logged!  Awesome, except that no user was tied to that change, it showed that the DC itself made the change.  I thought of a couple of scenarios of how that was possible, but then he mentioned that the version number for the pwdLastSet attribute was up to almost 400, which was quite high for this relatively small environment that isn’t even 10 years old yet.  In short, we tracked it down to the LAPS client-side extension on the DC that was changing the password.  We found that the LAPS GPO, which had the default account defined (-500 SID, representing the Administrator account), was applied at the Domain Level, which applied to Domain Controllers, which in fact changed the password for the Administrator account for the domain.  So, when the password timestamp expired for each individual domain controller, upon the next policy refresh, that specific domain controller would reset the Administrator password; That explained why the version number was so high. 


 


Just to verify the finding, he used Reset-AdmPwdPassword cmdlet from the AdmPwd.PS (LAPS) PowerShell module and set -WhenEffective to the current time, so that the password would be reset again upon the next policy refresh.  The policy was refreshed and an updated Repadmin /ShowObjMeta showed that the password was changed on the DC that had Reset-AdmPwdPassword run against its computer object.  Now the test…. Can he log in as Administrator to a DC, with the password that was written to the MS-MCS-AdmPwd attribute on that remote site’s DC?  Yep… 


 


So, if that’s the case, then the possibility exists that the domain’s Administrator account credentials could be harvested.  From there, it’s game over, and the next thing you know, your pipeline is shutdown… 


 


Also, in case it doesn’t go without saying, don’t install the LAPS client-side extension on the DC and have a policy try to manage it, or at least if you do, have a very good understanding of what you’re doing…but even then, I wouldn’t recommend it… 


 


Until next time!  


  


Disclaimer:


The content above contains a sample script.  Sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.


 


Tags: LAPS, ms-Mcs-AdmPwd, ExtendedRightHolders, “All Extended Rights”, Security, Find-AdmPwdExtendedRights, Reset-AdmPwdPassword, Auditing, Pipeline 

Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.