Доступ к диспетчеру учетных данных Windows из PowerShell

Я использую PowerShell 2.0 (необходимый из-за SP2010) в Windows Server 2008 R2. Мне нужно получить учетные данные для процесса из диспетчера учетных данных Windows. Кажется, я не могу заставить это работать.

Мне дали этот кусок кода:

[Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
(new-object Windows.Security.Credentials.PasswordVault).RetrieveAll() | % { $_.RetrievePassword(); $_ }

обе строки кода выдают ошибки

Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime : Unable to find type [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]: make sure that the assembly containing this type is loaded.

и

(new-object Windows.Security.Credentials.PasswordVault).RetrieveAll() | % {$_.RetrievePassword(); $_ } 

соответственно. Я пытался как-то импортировать класс PasswordVault. До сих пор Google меня не подводил, я даже не смог выяснить, в какой сборке он находится. Что мне не хватает?


person Shaggydog    schedule 17.03.2015    source источник


Ответы (6)


В powershell5 введите:

   Install-Module CredentialManager -force

Затем

   New-StoredCredential -Target $url -Username $ENV:Username -Pass ....

и позже

   Get-StoredCredential -Target .... 

Исходный код модуля: https://github.com/davotronic5000/PowerShell_Credential_Manager.

person majkinetor    schedule 30.03.2016
comment
Я думаю, что вместо Install-Module вы имеете в виду Import-Module? - person shufler; 27.07.2016
comment
Нет, сначала нужно установить модуль: powershellgallery.com/packages/CredentialManager/2.0 - person majkinetor; 27.07.2016
comment
Ой, извини. Дерп. technet.microsoft.com/en-us/library/dn807162.aspx Не знаю, почему я не мог найти это раньше. Я ошибался! Спасибо :) - person shufler; 28.07.2016
comment
OP специально попросил PS2, почему за ответ PS5 так много голосов? Install-Module не является допустимым командлетом в PS2 - person dlkulp; 08.08.2017
comment
Тем не менее, вы можете установить модуль на PS2. Install-Module это только ярлык. - person majkinetor; 15.08.2017

Вам потребуется доступ к Win32 API для взаимодействия с диспетчером учетных данных.

CredMan.ps1 из галереи сценариев Technet прекрасно это демонстрирует.

Для более простых шаблонов использования, таких как просто перечисление участников или добавление новых учетных данных, вы также можете использовать cmdkey , встроенная утилита командной строки Windows для управления учетными данными.

Для повторного использования сохраненных учетных данных в PowerShell этот парень, кажется, нашел способ создать PSCredential из универсального дескриптора учетных данных из хранилища учетных данных, используя метод, аналогичный тому, что используется в CredMan.ps1: Get-StoredCredential

person Mathias R. Jessen    schedule 17.03.2015
comment
Спасибо, просто чтобы убедиться, прежде чем я потрачу время на его изучение, это позволит мне восстановить пароль, верно? - person Shaggydog; 17.03.2015
comment
Нет, по крайней мере cmdkey не будет. Зачем вам когда-либо хотеть восстановить пароль? - person Mathias R. Jessen; 17.03.2015
comment
Потому что мне нужно удаленно вызвать процесс с учетными данными, хранящимися в диспетчере учетных данных. Я думал, что эта часть была самоочевидной, зачем еще мне нужен доступ к диспетчеру учетных данных, если не использовать учетные данные, хранящиеся внутри? - person Shaggydog; 17.03.2015
comment
Не имея практического опыта реализации такого решения, я бы подумал, что правильный способ сделать это - экспортировать токен или контекст безопасности через SSPI или аналогичный, вместо того, чтобы напрямую возиться с паролем в текстовом виде. - person Mathias R. Jessen; 17.03.2015
comment
Я использую экземпляр System.Management.Automation.PSCredential в сценарии, поэтому, если вы знаете способ получить это из диспетчера учетных данных, я весь внимание. Я имею в виду глаза. - person Shaggydog; 17.03.2015
comment
cmdkey не восстанавливает пароль, но CredMan.ps1 делает это, потому что он использует Credential Manager Win32 API. Извлекаемый пароль хранится/отображается в виде обычного текста, поэтому после его получения вам потребуется ConvertTo-SecureString -AsPlainText-Force. - person shufler; 28.07.2016
comment
@MathiasR.Jessen, привет, Матиас, есть ли какие-либо ограничения для диспетчера учетных данных по сети? WinAPI CredWrite не работает, если я удаленно подключаюсь к Windows. Я спросил об этом здесь: security.stackexchange.com/questions/174185/ - person pinkpanther; 23.11.2017

Согласно документам, класс PasswordVault не поддерживается в Windows Server 2008 R2.

Минимальный поддерживаемый сервер Windows Server 2012

https://msdn.microsoft.com/library/windows/apps/windows.security.credentials.passwordvault.aspx

person David Anderson    schedule 17.03.2015
comment
Хорошо, точка принята. Поэтому мой вопрос: как мне получить доступ к диспетчеру учетных данных в Windows Server 2008? Должен быть способ. - person Shaggydog; 17.03.2015

Я нашел действительно хороший пост, этот код напечатает все имена пользователей, ресурсы и пароли

[Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
$vault = New-Object Windows.Security.Credentials.PasswordVault
$vault.RetrieveAll() | % { $_.RetrievePassword();$_ }

Авторы сообщения Тодда

person LuisEnMarroquin    schedule 21.06.2020

Если кому-то просто нужен фрагмент кода, чтобы он мог распространять сценарии без необходимости инструктировать конечных пользователей об установке модулей или включении файлов DLL, это должно помочь.

$code = @"
using System.Text;
using System;
using System.Runtime.InteropServices;

namespace CredManager {
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  public struct CredentialMem
  {
    public int flags;
    public int type;
    public string targetName;
    public string comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; // .NET 2.0
    public int credentialBlobSize;
    public IntPtr credentialBlob;
    public int persist;
    public int attributeCount;
    public IntPtr credAttribute;
    public string targetAlias;
    public string userName;
  }

  public class Credential {
    public string target;
    public string username;
    public string password;
    public Credential(string target, string username, string password) {
      this.target = target;
      this.username = username;
      this.password = password;
    }
  }

  public class Util
  {
    [DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool CredRead(string target, int type, int reservedFlag, out IntPtr credentialPtr);

    public static Credential GetUserCredential(string target)
    {
      CredentialMem credMem;
      IntPtr credPtr;

      if (CredRead(target, 1, 0, out credPtr))
      {
        credMem = Marshal.PtrToStructure<CredentialMem>(credPtr);
        byte[] passwordBytes = new byte[credMem.credentialBlobSize];
        Marshal.Copy(credMem.credentialBlob, passwordBytes, 0, credMem.credentialBlobSize);
        Credential cred = new Credential(credMem.targetName, credMem.userName, Encoding.Unicode.GetString(passwordBytes));
        return cred;
      } else {
        throw new Exception("Failed to retrieve credentials");
      }
    }

    [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)]
    private static extern bool CredWrite([In] ref CredentialMem userCredential, [In] int flags);

    public static void SetUserCredential(string target, string userName, string password)
    {
      CredentialMem userCredential = new CredentialMem();

      userCredential.targetName = target;
      userCredential.type = 1;
      userCredential.userName = userName;
      userCredential.attributeCount = 0;
      userCredential.persist = 3;
      byte[] bpassword = Encoding.Unicode.GetBytes(password);
      userCredential.credentialBlobSize = (int)bpassword.Length;
      userCredential.credentialBlob = Marshal.StringToCoTaskMemUni(password);
      if (!CredWrite(ref userCredential, 0))
      {
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
      }
    }
  }
}
"@
Add-Type -TypeDefinition $code -Language CSharp
# How to store credentials
[CredManager.Util]::SetUserCredential("Application Name", "Username", "Password")
# How to retrieve credentials
[CredManager.Util]::GetUserCredential("Application Name")
# How to just get the password
[CredManager.Util]::GetUserCredential("Application Name").password

Приведенный выше код был протестирован на PowerShell 7 и PowerShell 5, хотя вам может понадобиться более свежая версия .Net framework, если вы используете последнюю.

person Dragoon    schedule 11.06.2021
comment
Это прекрасно сработало для меня. Мне нравится, что мне не нужно загружать или устанавливать какие-либо модули. Спасибо! - person Dave Sibiski; 28.07.2021

Эти модули PowerShell только что получили полную версию: Общедоступно. Секрет может быть удостоверением.

Install-Module Microsoft.PowerShell.SecretManagement
Install-Module SecretManagement.JustinGrote.CredMan  # windows credential manager
Register-SecretVault SecretManagement.JustinGrote.CredMan
Set-Secret -Name TestSecret -Secret "TestSecret"
Get-Secret -Name TestSecret -AsPlainText
TestSecret
person js2010    schedule 18.02.2020
comment
К сожалению, через год после анонса (февраль 2020 г.) он все еще находится в (пре-)альфа-фазе, за много миль от готового к производству кода. ???? Ответственная команда MS не справляется с тем объемом работы, с которым сталкивается новая версия PowerShell, PowerShellGet или этого конкретного модуля. - person KUTlime; 26.01.2021