none
Listing Access Rights for all of our servers RRS feed

  • Question

  • We are in the process of enforcing new security requirements that call for specific enforcement of user rights (Local Security Policy \ Security Settings \ Local Policies \ User Rights Assignment). We are trying to find a method of dumping rights configuration on every server so that we can identify those servers they can be quickly re-mediated with a base group policy, and those that will require extra work to ensure that servers with special rights considerations are preserved and documented. We are hoping to use the same script to validate that the settings we push out from group policy actually apply to the servers.

    I am not looking for someone to write the script. I just cannot find a way to dump the policy in an efficient way. We have tried two WBEM Classes (RSOP_PolicySetting and RSOP_UserPrivilegeRight). Both would be fine if they showed the local configuration as well as the domain propagated settings. We need the combined answer, not just the group policy based settings.

    I found a method of using PSEXEC to execute SECEDIT to dump the settings on a remote system, I would then need to script the recovery of the output and change SIDS to user / groups. The method is looking pretty kludgy. Is there a better way to get this data and compile it for review? Powershell or command line is fine as long as we can do it remotely. WinRM is not allowed at our site, so any method dependent on that wont work for our purposes.

    Tuesday, July 22, 2014 4:56 PM

Answers

  • Off the top of my head, I don't know of a convenient C# / PowerShell wrapper for this, but the Win32 API function you'd want is LsaEnumerateAccountsWithUserRight.  A web search turned up some sample code here and there (particularly on pinvoke.net), but there's still quite of work to be done to turn that into an easily usable PowerShell command.

    Regardless of what method you use, you'll need to convert SIDs into user / group names; that's almost always the case.  Windows stores SIDs and translates to human-readable names as needed.

    • Marked as answer by Oldguard Wednesday, July 23, 2014 1:55 PM
    Tuesday, July 22, 2014 5:12 PM

All replies

  • Off the top of my head, I don't know of a convenient C# / PowerShell wrapper for this, but the Win32 API function you'd want is LsaEnumerateAccountsWithUserRight.  A web search turned up some sample code here and there (particularly on pinvoke.net), but there's still quite of work to be done to turn that into an easily usable PowerShell command.

    Regardless of what method you use, you'll need to convert SIDs into user / group names; that's almost always the case.  Windows stores SIDs and translates to human-readable names as needed.

    • Marked as answer by Oldguard Wednesday, July 23, 2014 1:55 PM
    Tuesday, July 22, 2014 5:12 PM
  • Are you asking how to get the rights of the local groups on a remote system?

    There are a number of utilities that display account rights as configured.   I don't think anyone would feel that using SECEdit is the way to do this.

    NTRights is an SDK utility.  WhoAmI will display the privileges assigned.

    WHOAMI /ALL

    Privilege Name                Description                          State
    ============================= ==================================== ========
    SeShutdownPrivilege           Shut down the system                 Disabled
    SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
    SeUndockPrivilege             Remove computer from docking station Disabled
    SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
    SeTimeZonePrivilege           Change the time zone                 Disabled

    Even WMI can return rights/provileges.


    ¯\_(ツ)_/¯

    Tuesday, July 22, 2014 5:16 PM
  • Another easy utility to use is from Mark R. at Microsoft: http://technet.microsoft.com/en-us/sysinternals/bb664922.aspx


    ¯\_(ツ)_/¯

    Tuesday, July 22, 2014 5:26 PM
  • Another easy utility to use is from Mark R. at Microsoft: http://technet.microsoft.com/en-us/sysinternals/bb664922.aspx


    ¯\_(ツ)_/¯


    That'll work.  NTRights and whoami only list the rights for a specific account, as opposed to showing all of the accounts / groups that have been assigned a particular user right.  AccessChk, on the other hand, does the trick ( accesschk -a * ).  You'd still have to do some text parsing, but that's potentially less work than writing all the pinvoke code to get at the Win32 API from PowerShell.
    Tuesday, July 22, 2014 5:35 PM
  • Appreciate your responses. Didn't know if that old NT4.0 reskit utility would work (maybe a last ditch effort if it comes to it). You said I could get the info from WMI. That would be optimal, but I cannot find the class that reports it. Do you know the name space and class that would provide what we need? If we could find that I would be fine from there.

    I don't need to know my user rights. I need to know which users and groups are assigned to each right at the system level. Exampe:

    SeDenyInteractiveLogonRight = Domain\Domain, Admins Domain\Enterprise Admins, Guests

    I have seen the API mentioned by David Wyatt. Not sure I have the experience level yet to understand how to begin to implement that.  I make no claims to being a programmer.  I tried to load it as a reflection assembly , but the advapi32.dll that I think contains the API fails to load. The module was expected to contain an assembly manifest... Going to look a little further, but this just might be over my current level of experience.

    Appreciate the ideas

    Tuesday, July 22, 2014 5:44 PM
  • advapi32.dll isn't a .NET assembly; it's native code (as is the entire Win32 API).  To access its functions from PowerShell and other .NET languages, you need to use P/Invoke.  There's definitely a learning curve to get used to that, and most people don't ever need to do it.  pinvoke.net is a great resource for examples on how to get C# or VB code working when accessing these APIs, and it's usually a fairly small step from there to leverage that in PowerShell.

    Tuesday, July 22, 2014 6:14 PM
  • Lets start with some basics. Local rights settings should never remote accounts because it makes this harder to do and makes it harder to adjust access.

    I would create a function that scanned for all foreign accounts being directly used in local security policy.

    If you have the CFG files extracted from the servers you can use the SIDs to query local accounts for identity.

    Get-WmiObject Win32_Account -filter "SID='$sid'"

    This will decode the local sids.  To get remote SIDs you can query a DC the same way.

    I would just dump all foreign SIDs and fix the servers to use a local group instead.

    Normally this would never happen but I have been on sites where untrained admins have decided to add foreign SIDS into the local [policy. 


    ¯\_(ツ)_/¯

    Tuesday, July 22, 2014 8:22 PM
  • Appreciate your responses. Didn't know if that old NT4.0 reskit utility would work (maybe a last ditch effort if it comes to it). You said I could get the info from WMI. That would be optimal, but I cannot find the class that reports it. Do you know the name space and class that would provide what we need? If we could find that I would be fine from there.

    WMI can only reflect the settings applied by Group Policy and I see that this is not what you are looking for.


    ¯\_(ツ)_/¯

    Tuesday, July 22, 2014 8:23 PM
  • We can also do this although is is very cumbersome:

    # export all current settings in security database
    secedit /export /areas USER_RIGHTS /cfg OUTFILE.CFG
    
    Load and filter CFG file into a hashtable
    $props=cat OUTFILE.CFG |?{$_ -match 'Se.*='}|Out-String |ConvertFrom-StringData
    
    #Use hash to create an object
    $rights=New-Object PsObject -Property $props
    
    # turn all SID strings into arrays
    $rights.psobject.Properties|%{$_.Value=$_.Value.Split(',')}
    $rights.psobject.Properties|%{$_.Value=$_.Value.Replace('*','')}
    
    # We now have a manageable object with all SIDs which can be decoded.
    
    $rights | %{ $_.PsObject.Properties.Value | %{gwmi Win32_account -filter "SID = '$_'"}}

    This will decode all local account SIDs.  With a bit of extra work it can be formatted into a very simple report from this point.


    ¯\_(ツ)_/¯



    • Edited by jrv Tuesday, July 22, 2014 8:40 PM
    Tuesday, July 22, 2014 8:38 PM
  • Looking at the API call, I think I will run into problems with remote execution, so I think I am going to go with the running SECEDIT through a WMI call and then pick up the results and process the SIDS.

    Greatly appreciate the discussion on the issue.I learned a bit from both of you. Thank you for the help.

    I think the final answer on this appears that outside of SECEDIT there is no easy way to get the data. Any methods of obtaining the information will require local calls on the system and conversion of SIDS to user/group names...

    Wednesday, July 23, 2014 1:54 PM
  • Looking at the API call, I think I will run into problems with remote execution, so I think I am going to go with the running SECEDIT through a WMI call and then pick up the results and process the SIDS.

    Greatly appreciate the discussion on the issue.I learned a bit from both of you. Thank you for the help.

    I think the final answer on this appears that outside of SECEDIT there is no easy way to get the data. Any methods of obtaining the information will require local calls on the system and conversion of SIDS to user/group names...


    It is actually not as hard as you  think.  Use WMI Win32_Process to execute secedit on each system.  Design it to dump to a file named as the server.  Remotely copy all files locally.  Use code I posted to run WMI remotely with the contents of each file.  I posted a script that solves 90% of all of you issues.

    ¯\_(ツ)_/¯

    Wednesday, July 23, 2014 2:13 PM