You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置NTLM认证后RPC服务器命名管道权限未受限的问题排查

Fixing RPC Server Restriction to Admin-only Connections via Named Pipes

Let's break down why your current configuration isn't enforcing the restrictions you want, and walk through the steps to lock down the server to only allow administrators and LocalSystem to connect.

Why Your Current Setup Fails

Right now, two key pieces are missing from your implementation:

  1. No Authorization Rules: Calling AddAuthentication(RpcAuthentication.RPC_C_AUTHN_WINNT) enables NTLM authentication, but it doesn't restrict which authenticated users are allowed to access the RPC service. Any valid Windows user can still connect once they pass NTLM.
  2. Permissive Default Pipe ACL: The library is creating the named pipe with a default, wide-open access control list (ACL) that grants RW to Everyone and Anonymous Logon. This means clients can establish a pipe connection before RPC authentication even runs, bypassing your intended restrictions.

Step 1: Enforce RPC Authentication + Authorization

First, we'll strengthen the RPC server's authentication requirements and add explicit authorization rules to only allow administrators.

// Initialize the server as before
server = new RpcServerApi(IId, MaxCalls, ushort.MaxValue, true);

// Set strict authentication level to block anonymous connections
server.SetAuthenticationLevel(RpcAuthnLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY);
// Enable NTLM authentication
server.AddAuthentication(RpcAuthentication.RPC_C_AUTHN_WINNT);

// Add authorization rule to only allow the Administrators group
server.AddAuthorization(RpcAuthorization.RPC_C_AUTHZ_NAME, @"BUILTIN\Administrators");
// Also add LocalSystem explicitly if needed
server.AddAuthorization(RpcAuthorization.RPC_C_AUTHZ_NAME, @"NT AUTHORITY\SYSTEM");

Step 2: Override Named Pipe ACL to Restrict Access

Next, we need to replace the default pipe ACL with one that only grants read/write access to administrators and LocalSystem. You can do this either when adding the protocol (if the library supports it) or by manually modifying the pipe's security settings after creation.

Option 1: Pass Custom Security Descriptor to AddProtocol

If your version of CSharpTest.Net.RpcLibrary has an overload of AddProtocol that accepts a security descriptor, use this approach:

// Create a security descriptor that only allows admins and LocalSystem
var adminOnlySd = CreateAdminOnlySecurityDescriptor();

// Add the named pipe protocol with the custom security descriptor
server.AddProtocol(RpcProtseq.ncacn_np, Id, MaxCalls, adminOnlySd);

Option 2: Manually Update Pipe ACL After Creation

If the library doesn't support passing a security descriptor directly, modify the pipe's permissions after calling AddProtocol:

// Add the protocol first
server.AddProtocol(RpcProtseq.ncacn_np, Id, MaxCalls);

// Update the pipe's security settings
var pipePath = @"\\.\pipe\myNamedPipe";
SetNamedPipeSecurity(pipePath, CreateAdminOnlySecurityDescriptor());

Helper Methods for Security Descriptor

Here's the code to create the restricted security descriptor and apply it to the pipe:

private static SecurityDescriptor CreateAdminOnlySecurityDescriptor()
{
    var sd = new SecurityDescriptor();
    var adminSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
    var localSystemSid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);

    // Create access control entries (ACEs) for allowed users/groups
    var adminAce = new CommonAce(
        AceFlags.None,
        AceQualifier.AccessAllowed,
        (int)PipeAccessRights.ReadWrite,
        adminSid,
        false,
        null
    );
    var systemAce = new CommonAce(
        AceFlags.None,
        AceQualifier.AccessAllowed,
        (int)PipeAccessRights.ReadWrite,
        localSystemSid,
        false,
        null
    );

    // Build the discretionary ACL
    var dacl = new DiscretionaryAcl(false, false, 2);
    dacl.AddAce(adminAce);
    dacl.AddAce(systemAce);

    sd.DiscretionaryAcl = dacl;
    sd.ControlFlags = ControlFlags.DiscretionaryAclPresent;

    return sd;
}

private static void SetNamedPipeSecurity(string pipePath, SecurityDescriptor sd)
{
    // Open the pipe handle
    var pipeHandle = CreateFile(
        pipePath,
        (uint)FileAccess.ReadWrite,
        (uint)FileShare.ReadWrite,
        IntPtr.Zero,
        FileMode.Open,
        (uint)FileAttributes.Normal,
        IntPtr.Zero
    );

    if (pipeHandle == IntPtr.Zero || pipeHandle == new IntPtr(-1))
        throw new Win32Exception();

    try
    {
        // Apply the new security descriptor
        if (!SetSecurityInfo(
            pipeHandle,
            ObjectType.FileObject,
            SecurityInfos.DiscretionaryAcl,
            null,
            null,
            sd.DiscretionaryAcl,
            null
        ))
            throw new Win32Exception();
    }
    finally
    {
        CloseHandle(pipeHandle);
    }
}

// Required Windows API imports
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool SetSecurityInfo(
    IntPtr handle,
    ObjectType objectType,
    SecurityInfos securityInfo,
    SecurityIdentifier owner,
    SecurityIdentifier group,
    DiscretionaryAcl dacl,
    SystemAcl sacl
);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    IntPtr hTemplateFile
);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);

// Enums for API calls
public enum ObjectType { FileObject = 1 }
[Flags] public enum SecurityInfos { DiscretionaryAcl = 0x00000004 }

Final Verification

After implementing these changes:

  1. Check the named pipe's ACL using PowerShell (Get-Acl \\.\pipe\myNamedPipe | Format-List) – it should only show permissions for Administrators and LocalSystem.
  2. Test with a non-admin account: the client should fail to connect (either at the pipe level or during RPC authorization).
  3. Test with an admin account or LocalSystem: the connection should succeed as expected.

内容的提问来源于stack exchange,提问作者grant-cameron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:48:15