Thursday, March 12, 2015

Determining Admin Rights

I'm now a global product lead for Avecto Privilege Guard (now called DefendPoint).  Privilege Guard is used to create an application execution policy to elevate processes, passively execute process, or block processes.  We are using the product to tighten security on desktops removing users from the administrator group but giving users the ability to continue to function.

One of our biggest issues was determining whether or not a user was running as an administrator.  On the outset, this seems like an easy question to answer.  However, with User Access Control (UAC) in place, it becomes more difficult. An administrator on Windows computers with UAC enabled will execute all scripts and applications with standard user rights until something triggers UAC and asks for elevation.  In a script, it is fairly easy to check for admin rights prior to execution by calling something that only an administrator would have access.  For example, you can call "net session" to determine if your shell is currently elevated.

To find out how many users are running with access to elevated rights is more difficult.  You could try to export the list of groups and users that are a member of the local administrator group but it quickly becomes difficult when you start dealing with nested domain groups.  Your account could receive administrator group membership by being part of a domain local group that is part of a domain global group that is part of another domain global group which is the actual group that has been added to the local administrators group.  Given enough time and recursive power, you can write a script that can give you the truth but it will not scale very well.

We found a great little utility on Windows 7 and greater computers that can quickly express every group membership your account is part connected.
whoami.exe /groups | find /i "administrators"
It "whoami.exe /groups" exports every group membership that is captured in the authentication token.  It is clean, it is locally cached, and doesn't require any processing or complicated recursive language that can easily have a loop error.

After testing and feeling comfortable we created an SCCM compliance powershell script that was very simple:
whoami.exe /groups | Select-String "s-1-5-32-544" -quiet
It seemed to work great with a slight problem, 10% of our inventory would generate an error instead of an answer of true or null for false.  I would connect to these computers and try to figure out what was happening and would find whoami.exe either fail or hang.  What I found in the event log was usually a couple group policy errors or warnings prior to a script failure.  It looked like we were picking up issues where group policy was temporarily failing because of one issue or another.  Either the secure channel was compromised waiting for a reset or something else was a problem.  I could easily fix the issue by rebooting the machine.

Now I think we found an even better solution.  I believe that whoami.exe is doing some type of secure channel look up on the domain which is not what we want to capture.  We want to capture whether a user is part of the builtin\administrator group.
[System.Security.Principal.WindowsIdentity]::GetCurrent().UserClaims.Value | Select-String "S-1-5-32-544" -quiet
We were able to test a second SCCM compliance baseline with both CI's attached to get side-by-side results.  One CI was set to query whoami and the other just used the powershell script shown above.  In our test group we went from 13% failures to 0.71% failures.

I did not find very good documentation on the difference of Claims or UserClaims so I picked the one that seemed most likely and started testing.  If someone could point me to more information, I would appreciate it.

We were looking to follow this great SCCM process from Wells Fargo to capture every computer's local group membership.  I really like their elegant method of capturing the data in WMI through a compliance script and then using SCCM to collect the information at a different time.  I'll have to implement this for another project.

http://mnscug.org/blogs/sherry-kissinger/244-all-members-of-all-local-groups-configmgr-2012