【问题标题】:Authenticate Local Windows User Accounts验证本地 Windows 用户帐户
【发布时间】:2015-05-06 22:27:37
【问题描述】:

我编写了这个 JScript 来验证本地 Windows 用户帐户:

function ValidateCredentials(strUsername, strPassword) {
  var ADS_SECURE_AUTHENTICATION = 1;
  var objWMISvc = GetObject("winmgmts:\\\\.\\root\\cimv2");
  var colItems = objWMISvc.ExecQuery( "Select * from Win32_ComputerSystem");
  for (var it = new Enumerator(colItems); !it.atEnd(); it.moveNext()) {
    var objItem = it.item();
    if (objItem.PartOfDomain)
      continue;
    var strWorkgroup = objItem.Domain;
    var strComputer  = objItem.Name;
    var strPath = "WinNT://" + strWorkgroup + "/" + strComputer + "/" +
      strUsername + ",user";
    try {
      var objIADS = GetObject("WinNT:").OpenDSObject(strPath, strUsername,
        strPassword, ADS_SECURE_AUTHENTICATION);

      WScript.Echo("OK");
    } catch(e) {
      WScript.Echo("Invalid Username/Password");
    }
  }
}

ValidateCredentials(WScript.Arguments(0), WScript.Arguments(1));

当我以管理员和普通用户的身份从命令提示符运行它时,它工作正常。当脚本由作为 LocalSystem 用户运行的服务进程调用时,它不起作用。相反,对 OpenDSObject 的调用会引发异常,错误代码为 -2147023584(指定的登录会话不存在。它可能已经终止)。

这里有什么问题,我认为 LocalSystem 帐户实际上比管理员帐户更有特权或受信任?

您可以通过将脚本保存到某个 .js 文件中来亲自试用该脚本,然后在命令提示符下运行它,如下所示:

cscript.exe validate.js myUsername myPassword

【问题讨论】:

  • LocalSystem 帐户实际上并不比管理员帐户享有更多或更少的特权/信任。它只是......不同的信任。也就是说,它具有普通用户帐户所没有的一些权利——但它也有一些其他帐户几乎没有的限制。
  • 这在任何情况下都不是安全问题,即 Windows 不会出于安全原因故意阻止您这样做。只是在此上下文中不支持 OpenDSObject 所做的任何事情。 (它可能在配置为在实际帐户中运行的服务中工作。)
  • @HarryJohnston 是的,如果我将服务配置为以管理员身份运行,它确实有效,但我不愿意这样做,因为系统中的每个服务都配置为作为 LocalSystem 或 NetworkService 运行,所以我不确定它是否有任何安全隐患...顺便说一下,有问题的服务是 OpenVPN。
  • @JerryCoffin 你知道我应该寻找哪个特权令牌吗?我正在比较 LocalSystem 和普通帐户的“whoami /priv”输出,但不确定要查找什么...

标签: active-directory ldap windows-authentication directoryservices adsi


【解决方案1】:

如果您只想验证密码,我会避免上述所有操作。有一种不同的方法可以在非特权帐户中很好地工作。实际上,您想确保该帐户实际上没有更改密码的权利。

使用此方法,您调用NetUserChangePassword,这需要您指定用户的现有密码以便在更改之前进行身份验证。

当您从无权更改该用户密码的帐户执行此操作时,它显然会失败(因此他们的密码不会更改)。我们关心的正是它如何失败。如果返回ERROR_INVALID_PASSWORD 失败,那么您就知道密码错误。如果返回ERROR_ACCESS_DENIED 失败,则密码正确,函数失败,因为您调用它的帐户无权更改该用户的密码。

因此,不需要像 LocalSystem 或管理员这样的高权限帐户,这允许您从根本没有任何权限的帐户完成工作(强烈偏好,甚至没有更改自己密码的权利)。

【讨论】:

  • 太好了,谢谢!作为记录,我还在 MSDN 上找到了this article,它解释了如何利用 LogonUser WinAPI 函数来实现同样的事情。
  • @Jerry,这种行为有记录吗?
  • @HarryJohnston:是的,也不是。它可以/将返回这两个值的事实是。我不确定他们(当前)是否有关于错误值之间优先级的任何文档,所以如果您传递了错误的密码 并且 无权更改密码,则返回值您会得到ERROR_INVALID_PASSWORD
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 2010-09-08
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多