Аутентифицировать локальные учетные записи пользователей Windows

Я написал этот 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 имя пользователя мой пароль


person PaulK    schedule 06.05.2015    source источник
comment
Учетная запись LocalSystem на самом деле не является более или менее привилегированной/доверенной, чем учетная запись администратора. Просто... по-разному доверяют. Другими словами, у него есть некоторые права, которых нет ни у одной обычной учетной записи пользователя, но у него также есть некоторые ограничения, которых почти нет ни у одной другой учетной записи.   -  person Jerry Coffin    schedule 07.05.2015
comment
В любом случае это не проблема безопасности, т. е. Windows намеренно не запрещает вам это делать из соображений безопасности. Просто то, что именно делает OpenDSObject, не поддерживается в этом контексте. (Это может работать из службы, настроенной для работы в реальной учетной записи.)   -  person Harry Johnston    schedule 07.05.2015
comment
@HarryJohnston да, это работает, если я настрою службу для работы от имени администратора, но я не хочу этого делать, потому что каждая служба в системе настроена для работы либо как LocalSystem, либо как NetworkService, поэтому я не уверен, что она будет иметь какие-либо последствия для безопасности... между прочим, речь идет об OpenVPN.   -  person PaulK    schedule 07.05.2015
comment
@JerryCoffin У вас есть идеи, какой токен привилегий мне искать? Я сравниваю вывод whoami /priv для LocalSystem и обычной учетной записи, но не знаю, что искать...   -  person PaulK    schedule 07.05.2015


Ответы (1)


Если вы просто хотите проверить пароль, я бы избегал всего вышеперечисленного. Есть несколько другой метод, который прекрасно работает с непривилегированной учетной записью. На самом деле вы хотите убедиться, что учетная запись не имеет права менять пароль.

С помощью этого метода вы вызываете NetUserChangePassword, который требует, чтобы вы указали существующий пароль пользователя для аутентификации перед его изменением.

Когда вы делаете это из учетной записи, у которой нет прав на изменение пароля этого пользователя, это, очевидно, не удастся (поэтому их пароль не изменится). Что нас волнует, так это то, как это терпит неудачу. Если это не удается, возвращая ERROR_INVALID_PASSWORD, вы знаете, что пароль был неправильным. Если это не удается, возвращая ERROR_ACCESS_DENIED, пароль был правильным, и функция не удалась, потому что учетная запись, из которой вы ее вызываете, не имеет права изменять пароль этого пользователя.

Таким образом, вместо того, чтобы требовать учетную запись с высоким уровнем привилегий, такую ​​​​как LocalSystem или администратор, это позволяет вам выполнять работу из учетной записи, по существу, без каких-либо прав (по сильному предпочтению, даже без права изменить свой собственный пароль).

person Jerry Coffin    schedule 07.05.2015
comment
Отлично, спасибо! Для протокола: я также нашел эту статью в MSDN, в которой объясняется, как чтобы использовать функцию LogonUser WinAPI для достижения той же цели. - person PaulK; 07.05.2015
comment
@ Джерри, это поведение задокументировано? - person Harry Johnston; 08.05.2015
comment
@HarryJohnston: Да и нет. Тот факт, что он может/вернет эти два значения. Я не уверен, есть ли у них (в настоящее время) какая-либо документация о приоритете между значениями ошибок, поэтому, если вы передаете неправильный пароль и не имеете права изменить пароль, возвращаемое значение вы получу ERROR_INVALID_PASSWORD. - person Jerry Coffin; 08.05.2015