Powershell List User Rights Assignment Command

There are lots of “solutions” out there that just shell out to ntrights.exe or secedit or something else not powershell, and say “but powershell calls it so it counts!”  No it doesn’t.

There is no native NET or COM interface to manage local user rights assignment.  You have to use P/Invoke to call the API.  It’s a pain.  But I swiped some code from Roel van Lisdonk (http://www.roelvanlisdonk.nl/?p=1151) and got it working.  Looks like he got the code from Willy Denoyette (see http://www.pinvoke.net/default.aspx/advapi32.lsalookupsids) which I kept intact except for a minor error correction (it was missing a semicolon and wouldn’t compile). See http://www.hightechtalks.com/csharp/lsa-functions-276626.html for what seems to be Willy’s original source.

$LsaWrapper = @' using System; using System.Collections.Generic; using System.Text; namespace LsaSecurity { /* * LsaWrapper class credit: Willy Denoyette [MVP] * * http://www.hightechtalks.com/csharp/lsa-functions-276626.html * * Added support for: * * LsaLookupSids * * for the purposes of providing a working example. * * * */ using System.Runtime.InteropServices; using System.Security; using System.Management; using System.Runtime.CompilerServices; using System.ComponentModel; using LSA_HANDLE = IntPtr; public class Program { public static void Main() { using (LsaWrapper lsaSec = new LsaWrapper()) { string[] accounts = lsaSec.GetUsersWithPrivilege("SeNetworkLogonRight"); } } } [StructLayout(LayoutKind.Sequential)] struct LSA_OBJECT_ATTRIBUTES { internal int Length; internal IntPtr RootDirectory; internal IntPtr ObjectName; internal int Attributes; internal IntPtr SecurityDescriptor; internal IntPtr SecurityQualityOfService; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct LSA_UNICODE_STRING { internal ushort Length; internal ushort MaximumLength; [MarshalAs(UnmanagedType.LPWStr)] internal string Buffer; } sealed class Win32Sec { [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaOpenPolicy( LSA_UNICODE_STRING[] SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, int AccessMask, out IntPtr PolicyHandle ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaAddAccountRights( LSA_HANDLE PolicyHandle, IntPtr pSID, LSA_UNICODE_STRING[] UserRights, int CountOfRights ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaRemoveAccountRights( LSA_HANDLE PolicyHandle, IntPtr pSID, bool allRights, LSA_UNICODE_STRING[] UserRights, int CountOfRights ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaEnumerateAccountsWithUserRight( LSA_HANDLE PolicyHandle, LSA_UNICODE_STRING[] UserRights, out IntPtr EnumerationBuffer, out int CountReturned ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaLookupSids( LSA_HANDLE PolicyHandle, int count, IntPtr buffer, out LSA_HANDLE domainList, out LSA_HANDLE nameList ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern int LsaLookupNames2( LSA_HANDLE PolicyHandle, uint Flags, uint Count, LSA_UNICODE_STRING[] Names, ref IntPtr ReferencedDomains, ref IntPtr Sids ); [DllImport("advapi32")] internal static extern int LsaNtStatusToWinError(int NTSTATUS); [DllImport("advapi32")] internal static extern int LsaClose(IntPtr PolicyHandle); [DllImport("advapi32")] internal static extern int LsaFreeMemory(IntPtr Buffer); } public sealed class LsaWrapper : IDisposable { private bool _writeToConsole = false; [StructLayout(LayoutKind.Sequential)] struct LSA_TRUST_INFORMATION { internal LSA_UNICODE_STRING Name; internal IntPtr Sid; } [StructLayout(LayoutKind.Sequential)] struct LSA_TRANSLATED_SID2 { internal SidNameUse Use; internal IntPtr Sid; internal int DomainIndex; uint Flags; } //[StructLayout(LayoutKind.Sequential)] //struct LSA_REFERENCED_DOMAIN_LIST //{ // internal uint Entries; // internal LSA_TRUST_INFORMATION Domains; //} // Commented by KaushalendraATgmail.com [StructLayout(LayoutKind.Sequential)] internal struct LSA_REFERENCED_DOMAIN_LIST { internal uint Entries; internal IntPtr Domains; } [StructLayout(LayoutKind.Sequential)] struct LSA_ENUMERATION_INFORMATION { internal LSA_HANDLE PSid; } [StructLayout(LayoutKind.Sequential)] struct LSA_SID { internal uint Sid; } [StructLayout(LayoutKind.Sequential)] struct LSA_TRANSLATED_NAME { internal SidNameUse Use; internal LSA_UNICODE_STRING Name; internal int DomainIndex; } enum SidNameUse : int { User = 1, Group = 2, Domain = 3, Alias = 4, KnownGroup = 5, DeletedAccount = 6, Invalid = 7, Unknown = 8, Computer = 9 } enum Access : int { POLICY_READ = 0x20006, POLICY_ALL_ACCESS = 0x00F0FFF, POLICY_EXECUTE = 0X20801, POLICY_WRITE = 0X207F8 } const uint STATUS_ACCESS_DENIED = 0xc0000022; const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a; const uint STATUS_NO_MEMORY = 0xc0000017; IntPtr lsaHandle; public LsaWrapper() : this(null) { } // // local system if systemName is null public LsaWrapper(string systemName) { LSA_OBJECT_ATTRIBUTES lsaAttr; lsaAttr.RootDirectory = IntPtr.Zero; lsaAttr.ObjectName = IntPtr.Zero; lsaAttr.Attributes = 0; lsaAttr.SecurityDescriptor = IntPtr.Zero; lsaAttr.SecurityQualityOfService = IntPtr.Zero; lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES)); lsaHandle = IntPtr.Zero; LSA_UNICODE_STRING[] system = null; if (systemName != null) { system = new LSA_UNICODE_STRING[1]; system[0] = InitLsaString(systemName); } uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr, (int)Access.POLICY_ALL_ACCESS, out lsaHandle); if (ret == 0) return; if (ret == STATUS_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY)) { throw new OutOfMemoryException(); } throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret)); } public string[] GetUsersWithPrivilege(string privilege) { LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1]; privileges[0] = InitLsaString(privilege); IntPtr buffer; int count; uint ret = Win32Sec.LsaEnumerateAccountsWithUserRight(lsaHandle, privileges, out buffer, out count); if (ret != 0) { if (ret == STATUS_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } if (ret == STATUS_INSUFFICIENT_RESOURCES || ret == STATUS_NO_MEMORY) { throw new OutOfMemoryException(); } throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret)); } LSA_ENUMERATION_INFORMATION[] lsaInfo = new LSA_ENUMERATION_INFORMATION[count]; for (int i = 0, elemOffs = (int)buffer; i < count; i++) { lsaInfo[i] = (LSA_ENUMERATION_INFORMATION)Marshal.PtrToStructure((IntPtr)elemOffs, typeof(LSA_ENUMERATION_INFORMATION)); elemOffs += Marshal.SizeOf(typeof(LSA_ENUMERATION_INFORMATION)); } LSA_HANDLE domains; LSA_HANDLE names; ret = Win32Sec.LsaLookupSids(lsaHandle, lsaInfo.Length, buffer, out domains, out names); if (ret != 0) { if (ret == STATUS_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } if (ret == STATUS_INSUFFICIENT_RESOURCES || ret == STATUS_NO_MEMORY) { throw new OutOfMemoryException(); } throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret)); } /*string[] retNames = new string[count]; LSA_TRANSLATED_NAME[] lsaNames = new LSA_TRANSLATED_NAME[count]; for (int i = 0, elemOffs = (int)names; i < count; i++) { lsaNames[i] = (LSA_TRANSLATED_NAME)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRANSLATED_NAME)); elemOffs += Marshal.SizeOf(typeof(LSA_TRANSLATED_NAME)); LSA_UNICODE_STRING name = lsaNames[i].Name; retNames[i] = name.Buffer.Substring(0, name.Length / 2); }*/ // Following code also fetches Domains and associates domains and usernames string[] retNames = new string[count]; List currentDomain = new List(); int domainCount = 0; LSA_TRANSLATED_NAME[] lsaNames = new LSA_TRANSLATED_NAME[count]; for (int i = 0, elemOffs = (int)names; i < count; i++) { lsaNames[i] = (LSA_TRANSLATED_NAME)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRANSLATED_NAME)); elemOffs += Marshal.SizeOf(typeof(LSA_TRANSLATED_NAME)); LSA_UNICODE_STRING name = lsaNames[i].Name; retNames[i] = name.Buffer.Substring(0, name.Length / 2); if (!currentDomain.Contains(lsaNames[i].DomainIndex)) { domainCount = domainCount + 1; currentDomain.Add(lsaNames[i].DomainIndex); } } string[] domainPtrNames = new string[count]; LSA_REFERENCED_DOMAIN_LIST[] lsaDomainNames = new LSA_REFERENCED_DOMAIN_LIST[count]; for (int i = 0, elemOffs = (int)domains; i < count; i++) { lsaDomainNames[i] = (LSA_REFERENCED_DOMAIN_LIST)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_REFERENCED_DOMAIN_LIST)); elemOffs += Marshal.SizeOf(typeof(LSA_REFERENCED_DOMAIN_LIST)); } LSA_TRUST_INFORMATION[] lsaDomainName = new LSA_TRUST_INFORMATION[count]; string[] domainNames = new string[domainCount]; for (int i = 0, elemOffs = (int)lsaDomainNames[i].Domains; i < domainCount; i++) { lsaDomainName[i] = (LSA_TRUST_INFORMATION)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRUST_INFORMATION)); elemOffs += Marshal.SizeOf(typeof(LSA_TRUST_INFORMATION)); LSA_UNICODE_STRING tempDomain = lsaDomainName[i].Name; //if(tempDomain.Buffer != null) //{ domainNames[i] = tempDomain.Buffer.Substring(0, tempDomain.Length / 2); //} } string[] domainUserName = new string[count]; for (int i = 0; i 0x7ffe) throw new ArgumentException("String too long"); LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING(); lus.Buffer = s; lus.Length = (ushort)(s.Length * sizeof(char)); lus.MaximumLength = (ushort)(lus.Length + sizeof(char)); // If unicode issues then do this instead of previous two line //lus.Length = (ushort)(s.Length * 2); // Unicode char is 2 bytes //lus.MaximumLength = (ushort)(lus.Length + 2) return lus; } public bool WriteToConsole { set { this._writeToConsole = value; } } } public class LsaWrapperCaller { public static void AddPrivileges(string account, string privilege) { using (LsaWrapper lsaWrapper = new LsaWrapper()) { lsaWrapper.AddPrivileges(account, privilege); } } public static void RemovePrivileges(string account, string privilege) { using (LsaWrapper lsaWrapper = new LsaWrapper()) { lsaWrapper.RemovePrivileges(account, privilege); } } } } '@ Add-Type $LsaWrapper $account = "computername\name" # Will default to local computer if you do not specify computername. Can also accept domain name there. Name is a user name or group name. $right = "SeServiceLogonRight" # see http://msdn.microsoft.com/en-us/library/windows/desktop/bb545671(v=vs.85).aspx for a list. [LsaSecurity.LsaWrapperCaller]::RemovePrivileges($account,$right);

29.739243-95.481730

Westside, Houston, TX, USA

Like this:

LikeLoading...

Related

This entry was posted in Computers and Internet, PowerShell, Random on by Jordan M.

While preparing for an Exchange Server 2007 to 2010 migration I needed to work out which users had been granted access to other mailboxes. This applied both to shared mailboxes (eg a Help Desk) and individual mailbox access (eg a personal assistant with access to the CEO's mailbox).

Exchange 2007/2010 provide the Get-MailboxPermission cmdlet that can be used to query the permissions on a mailbox. For example:

To get the same information about all of the mailboxes in the environment we could run this command.

The problem with that is it gives us more information than we really need, with a lot of SELF permissions and inherited permissions that aren't relevant to the task we're trying to accomplish.

You could export the output to CSV and manipulate it using Excel to get just the permissions information you want, but another method is to filter the PowerShell output.

For example, to filter out all of the SELF permissions and the inherited permissions we can run this command.

That gives us a much smaller output that is more useful.

The Identity field contains long strings because it includes the full directory path to the mailbox user, so it may get truncated on your screen. In that case you could export the output to CSV file.

The trouble you may notice with that is that the access rights do not appear correctly in the output CSV file.

So to fix that we need to use a slightly different command. This single-line command will export to CSV a list of any mailboxes where other users have permissions to access them, and will also list what level of access those users have.

Get-MailboxPermission helpdesk
Identity             User                 AccessRights        IsInherited Deny
--------             ----                 ------------        ---------------
exchangeserverpro...NTAUTHORITY\SELF    {FullAccess,Rea...False       False
exchangeserverpro...ESPNET\Alex.Heyne    {FullAccess}        False       False
exchangeserverpro...ESPNET\Debbie.Lisa   {FullAccess}        False       False
exchangeserverpro...ESPNET\Kevin.Douglas{FullAccess}        False       False
Get-Mailbox|Get-MailboxPermission
Identity             User                 AccessRights        IsInherited Deny
--------             ----                 ------------        ---------------
exchangeserverpro...NTAUTHORITY\SELF    {FullAccess,Rea...False       False
exchangeserverpro...ESPNET\BR-EX2007-MB${ReadPermission}    True        False
exchangeserverpro...ESPNET\ExchangeS...{FullAccess}        True        True
exchangeserverpro...ESPNET\DomainAdmins{FullAccess}        True        True
exchangeserverpro...ESPNET\Enterprise...{FullAccess}        True        True
exchangeserverpro...ESPNET\ExchangeO...{FullAccess}        True        True
exchangeserverpro...ESPNET\administrator{FullAccess}        True        True
exchangeserverpro...ESPNET\ExchangeS...{FullAccess}        True        False
exchangeserverpro...ESPNET\ExchangeP...{ReadPermission}    True        False
exchangeserverpro...NT AUTHORITY\NETW...{ReadPermission}    True        False
exchangeserverpro...ESPNET\ExchangeS...{ReadPermission}    True        False
exchangeserverpro...ESPNET\ExchangeV...{ReadPermission}    True        False
exchangeserverpro...ESPNET\ExchangeO...{FullAccess,Del...True        False
exchangeserverpro...ESPNET\administrator{FullAccess,Del...True        False
exchangeserverpro...ESPNET\Enterprise...{FullAccess,Del...True        False
exchangeserverpro...ESPNET\DomainAdmins{FullAccess,Del...True        False
Get-Mailbox|Get-MailboxPermission|where{$_.user.tostring()-ne"NT AUTHORITY\SELF"-and$_.IsInherited-eq$false}
Identity             User                 AccessRights        IsInherited Deny
--------             ----                 ------------        ---------------
exchangeserverpro...ESPNET\Alannah.Shaw  {FullAccess}        False       False
exchangeserverpro...ESPNET\PayrollTeam  {FullAccess}        False       False
exchangeserverpro...ESPNET\Alex.Heyne    {FullAccess}        False       False
exchangeserverpro...ESPNET\Debbie.Lisa   {FullAccess}        False       False
exchangeserverpro...ESPNET\Kevin.Douglas{FullAccess}        False       False
Get-Mailbox|Get-MailboxPermission|where{$_.user.tostring()-ne"NT AUTHORITY\SELF"-and$_.IsInherited-eq$false}|Export-Csv-NoTypeInformation mailboxpermissions.csv
AccessRights,Deny,InheritanceType,User,Identity,IsInherited,IsValid,ObjectState
Microsoft.Exchange.Management.RecipientTasks.MailboxRights[],False,All,ESPNET\Alannah.Shaw,"exchangeserverpro.net/Company/Head Office/Users/Mark.Patel",False,True,Unchanged
Microsoft.Exchange.Management.RecipientTasks.MailboxRights[],False,All,"ESPNET\Payroll Team","exchangeserverpro.net/Company/Head Office/Users/Payroll",False,True,Unchanged
Microsoft.Exchange.Management.RecipientTasks.MailboxRights[],False,All,ESPNET\Alex.Heyne,"exchangeserverpro.net/Users/Help Desk",False,True,Unchanged
Microsoft.Exchange.Management.RecipientTasks.MailboxRights[],False,All,ESPNET\Debbie.Lisa,"exchangeserverpro.net/Users/Help Desk",False,True,Unchanged
Microsoft.Exchange.Management.RecipientTasks.MailboxRights[],False,All,ESPNET\Kevin.Douglas,"exchangeserverpro.net/Users/Help Desk",False,True,Unchanged
Get-Mailbox|Get-MailboxPermission|where{$_.user.tostring()-ne"NT AUTHORITY\SELF"-and$_.IsInherited-eq$false}|Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ',$_.AccessRights)}}|Export-Csv-NoTypeInformation mailboxpermissions.csv

Exchange ServerExchange 2007, Exchange 2010, Exchange Management Shell, PowerShell, Scripts

0 comments

Leave a Reply

Your email address will not be published. Required fields are marked *