模拟本地机器在应该失败时成功

Impersonation for Local Machine Succeeding when it should fail

问题:

我有 windows 服务使用模拟来检查单独服务器上的服务状态,但是在测试期间注意到当用户提供本地计算机地址和无效的本地计算机帐户时,检查将继续打开服务控制管理器并成功检索状态。我们的目标是让它只与有效的本地计算机帐户一起使用。

代码: 模拟命名空间(包含用于设置模拟的方法(SoddingNetworkAuth):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Impersonation
{
  public class Network
  {
    public class SoddingNetworkAuth : IDisposable
    {
      [DllImport("advapi32.dll", SetLastError = true)]
      private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
      [DllImport("kernel32", SetLastError = true)]
      private static extern bool CloseHandle(IntPtr hObject);
      private IntPtr userHandle = IntPtr.Zero;
      private WindowsImpersonationContext impersonationContext;
      public SoddingNetworkAuth(string user, string domain, string password)
      {
        if (!string.IsNullOrEmpty(user))
        {
          // Call LogonUser to get a token for the user  
          bool loggedOn = LogonUser(user, domain, password,
                          9 /*(int)LogonType.LOGON32_LOGON_NEW_CREDENTIALS*/,
                          3 /*(int)LogonProvider.LOGON32_PROVIDER_WINNT50*/,
          out userHandle);
          if (!loggedOn)
            throw new Win32Exception(Marshal.GetLastWin32Error());
          // Begin impersonating the user  
          impersonationContext = WindowsIdentity.Impersonate(userHandle);
        }
      }
      public void Dispose()
      {
        if (userHandle != IntPtr.Zero)
          CloseHandle(userHandle);
        if (impersonationContext != null)
          impersonationContext.Undo();
      }
    }
  }
}

我为测试编写的控制台应用程序:

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;


namespace NetworkAuthIssue
{
    class Program
    {
        static void Main(string[] args)
        {
            string result;
            try
            {
                using (new Impersonation.Network.SoddingNetworkAuth("Invalid User", "localhost", "InvalidPassword"))
                {
                    var serviceController = new ServiceController("Power", "localhost");
                    if (serviceController.Status == ServiceControllerStatus.Running)
                    {
                        result = "Authenticated, service running";
                    }
                    else
                    {
                        result = "Authenticated, service not running";
                    }
                }
            }
            catch (Exception e)
            {
                result = "Authentication Failed";
            }
            Console.WriteLine(result);
            Console.Read();
        }
    }
}

我是运行Windows8.1

我现在无法检查,但我遇到了与您类似的问题,这是由登录方法中选定的 LogonType/LogonProvider 值引起的。您应该在控制台应用程序中试用它们,并使用适合您场景的组合。

另请参阅此方法的 msdn 文档:https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx

这是因为您正在使用 LOGON32_LOGON_NEW_CREDENTIALS

来自 https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184%28v=vs.85%29.aspx(强调我的):

This logon type allows the caller to clone its current token and specify new credentials for outbound connections. The new logon session has the same local identifier but uses different credentials for other network connections.

"outbound connections" 部分很重要。这意味着对于本地连接,根本不使用提供的凭据。当前身份用于本地连接。