📜 ⬆️ ⬇️

Microsoft ActiveDirectory - update user passwords in external repositories

The article is more focused on those who administer or create a hybrid system environment, where the foundation is the Windows domain and you want to be able to authorize users on other platforms and systems with a centralized system for storing credentials. In most cases, you will have no problems, but if you need to implement authorization, for example, using CRAM-MD5 or another authorization scheme (which is not in AD), and generally not supporting LDAP (or not understanding LDAP in understanding Microsoft ), then this article is for you.

Introduction:


In general, Microsoft has such a service: Password Change Notification Service (PCNS). Its purpose is to trigger an event before changing the user's password and after, respectively. With these events, a password can be transmitted in clear text (naturally via secure channels), this is what we need.
To work with PCNS there are a number of paid products with rich functionality, etc., but we will try to make your bike out of free and available materials, for which we take:


Everything below was done for Windows Server 2008R2. So let's go!

Passwdhk


First, you need to install our PasswdHk library on all domain controllers, it will process the user password change event (the event is generated on the controller with write rights selected by the user automatically, and after changing the password, the hash is distributed to other controllers).
Download the installer (for x64), and install the library regularly. Then you need to copy C: \ Windows \ System32 \ passwdhk.dll to C: \ Windows \ SysWOW64 \.
Together with the DLL, there is also a graphical configuration utility, an example configuration file (reg file) and a performance test (bat file). All settings are made in the registry and are applied at system startup (when changing, the system must be restarted).
Shortcomings in the utility !!!
Please note! Each click of the Apply button will add another line in the registry parameter "SYSTEM \ CurrentControlSet \ Control \ Lsa \ Notification Packages", which will have to be adjusted with pens.

')
I will give the settings for our laboratory system:



Settings in the text
The Pre and Post Change sections define actions, respectively, before the password is changed (you can implement your own password complexity filter) and after the change.
  • Program: C: \ Windows \ system32 \ cmd.exe (Program started to handle the event);
  • Arguments: / c start C: \ Windows \ system32 \ WindowsPowerShell \ v1.0 \ powershell.exe -File d: \ control \ check-user.ps1 (Command line arguments passed to the program above);
  • Password Escaping sets the password character escaping, but unfortunately only it. Escaping the username does not occur, on top of that, the dll is clearly not up to date with UTF-8 type encodings, so the login in Cyrillic will look very sad (can anyone manage to decode the result in the normal form?)


The option described above with the launch via the start command is not accidental, it allows you to bypass a specific problem when the program started to process the password is executed more than the specified Wait Timeout. Since I ran all of this on a heavily loaded host with virtual machines, in a machine with extremely modest resources, launching the PowerShell shell and loading the module into a cold one (after a long wait), it was easy to cross in 40 seconds (at this time, the user indicated a password change sits and waits), and with immodest timeouts in 30 seconds the call to the handler was interrupted forcibly.

So, the work of PasswdHk is over here, now let's deal with getting a password on our side. PasswdHk passes the login and password in the last two arguments of the command line.

PowerShell Processing


For our laboratory work, I chose PowerShell (as a trendy phenomenon, you can do processing on anything).
Import-Module ActiveDirectory $csv_file = "d:\passwd.csv" $domain=(Get-ADDomain -Server localhost).DNSRoot $user=$args[0] $passwd=$args[1] if(Get-ADUser -Filter {sAMAccountName -eq $user } -SearchScope 2 -Server localhost){ $csv = @() $csv_new = New-Object System.Object $csv_new | Add-Member -MemberType NoteProperty -Name "DOMAIN" -Value $domain $csv_new | Add-Member -MemberType NoteProperty -Name "USER" -Value $user $csv_new | Add-Member -MemberType NoteProperty -Name "PASSWD" -Value $passwd $csv += $csv_new if (Test-Path $csv_file){ $csv | ConvertTo-Csv -NoTypeInformation -delimiter "`t" ` | select -Skip 1 ` | Out-File -Encoding UTF8 -Append $csv_file } else{ $csv | ConvertTo-Csv -NoTypeInformation -delimiter "`t" ` | Out-File -Encoding UTF8 -Append $csv_file } }; 

Here we retrieve a couple of login and password from the command line variables, we put the DNS name of the domain in which the password change occurred in $ domain, and put all this into a CSV with three columns (DOMAIN, USER, PASSWD), if the search for the user returned is not empty result (excludes cases with names not in Latin, you can still filter objects corresponding only to users, otherwise the machines regularly updating their passwords will also be found in this file).

Conclusion


By slightly changing this example, you can send these passwords to any environment you use, I used this method to generate CRAM-MD5 hashes for the mail system on Dovecot.

Source: https://habr.com/ru/post/239359/


All Articles