pages

LocalSecurityEditor .NET Library

LocalSecurityEditor - .NET Library

Description

.NET library for managing local security policy (User Rights Assignment). This library was written to use in PowerShell Module SecurityPolicy providing easy way to manage local security policy.

Supported User Rights Assignment

ConstantNameGroup Policy Setting
SeTrustedCredManAccessPrivilegeAccess Credential Manager as a trusted caller
SeNetworkLogonRightAccess this computer from the network
SeTcbPrivilegeAct as part of the operating system
SeMachineAccountPrivilegeAdd workstations to domain
SeIncreaseQuotaPrivilegeAdjust memory quotas for a process
SeInteractiveLogonRightAllow log on locally
SeRemoteInteractiveLogonRightAllow log on through Remote Desktop Services
SeBackupPrivilegeBack up files and directories
SeChangeNotifyPrivilegeBypass traverse checking
SeSystemtimePrivilegeChange the system time
SeTimeZonePrivilegeChange the time zone
SeCreatePagefilePrivilegeCreate a pagefile
SeCreateTokenPrivilegeCreate a token object
SeCreateGlobalPrivilegeCreate global objects
SeCreatePermanentPrivilegeCreate permanent shared objects
SeCreateSymbolicLinkPrivilegeCreate symbolic links
SeDebugPrivilegeDebug programs
SeDenyNetworkLogonRightDeny access to this computer from the network
SeDenyBatchLogonRightDeny log on as a batch job
SeDenyServiceLogonRightDeny log on as a service
SeDenyInteractiveLogonRightDeny log on locally
SeDenyRemoteInteractiveLogonRightDeny log on through Remote Desktop Services
SeEnableDelegationPrivilegeEnable computer and user accounts to be trusted for delegation
SeRemoteShutdownPrivilegeForce shutdown from a remote system
SeAuditPrivilegeGenerate security audits
SeImpersonatePrivilegeImpersonate a client after authentication
SeIncreaseWorkingSetPrivilegeIncrease a process working set
SeIncreaseBasePriorityPrivilegeIncrease scheduling priority
SeLoadDriverPrivilegeLoad and unload device drivers
SeLockMemoryPrivilegeLock pages in memory
SeBatchLogonRightLog on as a batch job
SeServiceLogonRightLog on as a service
SeSecurityPrivilegeManage auditing and security log
SeRelabelPrivilegeModify an object label
SeSystemEnvironmentPrivilegeModify firmware environment values
SeDelegateSessionUserImpersonatePrivilegeObtain an impersonation token for another user in the same session
SeManageVolumePrivilegePerform volume maintenance tasks
SeProfileSingleProcessPrivilegeProfile single process
SeSystemProfilePrivilegeProfile system performance
SeUndockPrivilegeRemove computer from docking station
SeAssignPrimaryTokenPrivilegeReplace a process level token
SeRestorePrivilegeRestore files and directories
SeShutdownPrivilegeShut down the system
SeSyncAgentPrivilegeSynchronize directory service data
SeTakeOwnershipPrivilegeTake ownership of files or other objects

Example Local Computer

using System;
using LocalSecurityEditor;

namespace TestApp {
    internal class Program {
        static void Main() {
            string[] accounts;

            Console.WriteLine("[*] Accessing  server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper()) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }

            Console.WriteLine("[*] Adding Account to the Server");

            using (LsaWrapper lsa = new LsaWrapper()) {
                lsa.AddPrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
            }

            Console.WriteLine("[*] Accessing  server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper()) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }

            Console.WriteLine("[*] Accessing  server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper()) {
                lsa.RemovePrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
            }

            using (LsaWrapper lsa = new LsaWrapper("")) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }
        }
    }
}

Example Remote Computer

using System;
using LocalSecurityEditor;

namespace TestApp {
    internal class Program {
        static void Main() {
            string[] accounts;

            Console.WriteLine("[*] Accessing AD1 server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper("AD1")) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }

            Console.WriteLine("[*] Adding Account to the Server");

            using (LsaWrapper lsa = new LsaWrapper("AD1")) {
                lsa.AddPrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
            }

            Console.WriteLine("[*] Accessing AD1 server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper("AD1")) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }

            Console.WriteLine("[*] Accessing AD1 server - Displaying Current");

            using (LsaWrapper lsa = new LsaWrapper("AD1")) {
                lsa.RemovePrivileges("EVOTEC\\przemyslaw.klys", UserRightsAssignment.SeBatchLogonRight);
            }

            using (LsaWrapper lsa = new LsaWrapper("AD1")) {
                accounts = lsa.GetPrivileges(UserRightsAssignment.SeBatchLogonRight);
            }

            foreach (var account in accounts) {
                Console.WriteLine(account);
            }
        }
    }
}

Example GenerateSID

string serviceName = "ADSync";
string serviceExpectedSid = "S-1-5-80-3245704983-3664226991-764670653-2504430226-901976451";
string serviceSid = NTService.GenerateSID(serviceName);
Console.WriteLine($"The SID for the service '{serviceName}' is: {serviceSid} {serviceExpectedSid} {(serviceSid == serviceExpectedSid)}");

Typed, OO API

using LocalSecurityEditor;

// Get state for a right (local machine)
var svc = UserRightsAssignment.SeServiceLogonRight.Get();
foreach (var p in svc.Principals) {
    Console.WriteLine($"{p.AccountName} -> {p.SidString}");
}

// Manage rights on a remote system (batching via manager)
using (var ur = new UserRights("SERVER01")) {
    // Add by account name or SID
    ur.Add(UserRightsAssignment.SeBatchLogonRight, new[] { @"DOMAIN\\svc_batch", "S-1-5-32-544" });

    // Replace entire set for a right (adds missing, removes extras)
    var result = ur.Set(
        UserRightsAssignment.SeDenyRemoteInteractiveLogonRight,
        new[] { @"DOMAIN\\contractor1", @"DOMAIN\\contractor2" });
    Console.WriteLine(result);
}

// Performance tip: for many operations, reuse a single UserRights instance.
// using var ur = new UserRights();
// ur.Add(right, new[] { "user1", "user2", "user3" });

Async APIs

// Query a single right asynchronously (local)
var state = await new UserRights().GetStateAsync(UserRightsAssignment.SeServiceLogonRight, ct);

// Enumerate all rights asynchronously (remote)
var all = await new UserRights("SERVER01").EnumerateAsync(ct);

// Grant/remove asynchronously
await new UserRights().AddAsync(UserRightsAssignment.SeBatchLogonRight, new[] { @"DOMAIN\\user1" }, ct);
await new UserRights().RemoveAsync(UserRightsAssignment.SeBatchLogonRight, new[] { @"DOMAIN\\user1" }, ct);

// Fluent async extensions
var remoteState = await UserRightsAssignment.SeServiceLogonRight.GetAsync("SERVER01", ct);

Thread Safety

  • UserRights and LsaWrapper can be shared safely across tasks.
  • Internally they use a reader-writer lock.
  • Parallel reads are allowed for Get, GetState, and Enumerate.
  • Writes such as Add, Remove, and Set are exclusive.
  • Dispose is exclusive and waits for in-flight operations.
  • For many operations, reuse a single UserRights instance.
  • For heavy fan-out, you can also create per-task instances.

Aggregate URA Objects (PowerShell-friendly)

// One object per user right, each with Principals[]
var allRights = UserRights.Get();

// Stream lazily
foreach (var ura in new UserRights().EnumerateLazy()) { /* ... */ }

// Or as a dictionary keyed by enum
var byRight = new UserRights().GetByRight();

// Or keyed by short name (for example "SeServiceLogonRight")
var byShort = new UserRights().GetByShortName();

// Single right as typed object
var single = UserRightsAssignment.SeServiceLogonRight.Get();
Console.WriteLine($"{single.Name} has {single.Count} principals");

Credits

This library was created based on help from multiple sources. Without them, it would not be possible.