⬆️ ⬇️

The influence of a small window on the user's memory, and what to do about it



Even with the release of Windows Vista \ 2008, administrators were faced with a small but unpleasant problem: a warning message about password expiration became lonely to appear in the most inconspicuous corner of the screen. And this is instead of the window right in the center, as it was before!



From here and change of passwords at the last moment, to the accompaniment of access failures; and indignation, why the VPN suddenly stopped working, and what to do about it on a business trip. Of course, not the problem of the year, but the phenomenon is annoying and unpleasant. Therefore, we understand how to overcome it.



Reports and Excel on guard memory



In the article “ Excel instead of PowerShell: queries to AD and system reports ” I told how to get information from Active Directory using Excel. Thanks to this mechanism you can always get a report on the validity of user passwords. In modern domains for this there is an attribute msDS-UserPasswordExpiryTimeComputed , which is located in the class user.



With Power Query, we can easily get a similar label:





Report on password expiration dates in MS Excel.



Now, if we add a formula like



=([@[msDS-UserPasswordExpiryTimeComputed]]<();" !";([@[msDS-UserPasswordExpiryTimeComputed]]-5<();"  !";"")) 


in the next column, we will get a table of this kind:





We make the report more visual.



It remains only to add rules for coloring cells based on their content, and it will be quite beautiful:





And even more visual.



When setting up automatic data update, you can look at the table and prepare for requests from users. Or instruct the account manager (yes, somewhere there are such special people) to ring up employees.



Let's try to use PowerShell as account manager.



Automatic employee notifications



Fortunately, you can retrieve data from Active Directory not only through Excel, but also with the help of your favorite scripting languages ​​like PowerShell.



To begin with, we will get a list of users and their addresses with such a query:



 $users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0} ` -Properties "Name", "EmailAddress", "msDS-UserPasswordExpiryTimeComputed" | ` Select-Object -Property "Name", "EmailAddress", ` @{Name = "PasswordExpiry"; Expression = {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() }} 


As you can see, on this request, I get only those users that meet the three criteria:





As a result, we get a value table with the user name, his address and the password expiration date. For convenience, we set three options for the warning time — 7, 3, and 1 day:



 $SevenDayWarnDate = (get-date).adddays(7).ToLongDateString() $ThreeDayWarnDate = (get-date).adddays(3).ToLongDateString() $OneDayWarnDate = (get-date).adddays(1).ToLongDateString() 


Now, by comparing these three variables with the value of $ user.PasswordExpiry, we can send the corresponding notifications. Let me remind you that sending e-mail is done using the Send-MailMessage cmdlet.



But it is not necessary to notify users exclusively by mail - you can use the material “ Not a bot yet, but already something - we receive notifications from Zabbix in messengers ” and send notifications via any other communication channel.

A full listing of the script, which can be run daily using the scheduler, can be found under the spoiler.



Familiarize
 Import-Module ActiveDirectory #    $SevenDayWarnDate = (get-date).adddays(7).ToLongDateString() $ThreeDayWarnDate = (get-date).adddays(3).ToLongDateString() $OneDayWarnDate = (get-date).adddays(1).ToLongDateString() #   $MailSender = " - <bot@domain.com>" $Subject = '!     ' $EmailStub1 = ' -.   ' $EmailStub2 = '' $EmailStub3 = '' $EmailStub4 = '. ,    .     ,       .' $SMTPServer = 'smtp.domain.com' #  $users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0 } ` -Properties "Name", "EmailAddress", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Name", "EmailAddress", ` @{Name = "PasswordExpiry"; Expression = {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() }} #     . foreach ($user in $users) { if ($user.PasswordExpiry -eq $SevenDayWarnDate) { $days = 7 $EmailBody = $EmailStub1, $user.name, $EmailStub2, $days, $EmailStub3, $SevenDayWarnDate, $EmailStub4 -join ' ' Send-MailMessage -To $user.EmailAddress -From $MailSender -SmtpServer $SMTPServer -Subject $Subject -Body $EmailBody } elseif ($user.PasswordExpiry -eq $ThreeDayWarnDate) { $days = 3 $EmailBody = $EmailStub1, $user.name, $EmailStub2, $days, $EmailStub3, $ThreeDayWarnDate, $EmailStub4 -join ' ' Send-MailMessage -To $user.EmailAddress -From $MailSender -SmtpServer $SMTPServer -Subject $Subject ` -Body $EmailBody } elseif ($user.PasswordExpiry -eq $oneDayWarnDate) { $days = 1 $EmailBody = $EmailStub1, $user.name, $EmailStub2, $days, $EmailStub3, $OneDayWarnDate, $EmailStub4 -join ' ' Send-MailMessage -To $user.EmailAddress -From $MailSender -SmtpServer $SMTPServer -Subject $Subject -Body $EmailBody } else {} } 


Now users are warned, and it remains to hope for their responsibility. Consider another notification option.



Notify users at the entrance



You can return to the screen a message about the expiring password through a logon script or program in autoload. Unfortunately, for obvious reasons, this option is not suitable for users working with domain services remotely.



Here is an example of a simple PowerShell script slipped into autoload by group policies:



 $user= Get-ADUser -Identity $env:username -Properties 'msDS-UserPasswordExpiryTimeComputed','PasswordNeverExpires' if ( -not $user.'PasswordNeverExpires') { $diff=(new-timespan -start (get-date) -end ([datetime]::FromFileTime($user."msDS-UserPasswordExpiryTimeComputed"))).Days if ($diff -lt 7) { $msgBoxInput = [System.Windows.MessageBox]::Show("    "+ $diff + " !`n    ?","!","YesNo","Warning") switch ($msgBoxInput) { 'Yes' { cmd /c "explorer shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}" } 'No' { } } } } 


The explorer shell ::: {2559a1f2-21d7-11d4-bdaf-00c04f60b9f0} startup line is the launch of the Windows Security interface. After the release of Windows 2012, it disappeared from the Start menu and became available only by pressing Ctrl + Alt + Del or Ctrl + Alt + End in the case of connecting via RDP.





Notification window.

For connoisseurs under the spoiler, the old version of the script.



on AutoIT
 #Include <AD.au3> #include <Date.au3> _AD_Open() $array=_AD_GetPasswordInfo() if $array[9] <> "" then $t=_DateDiff ( "d", _NowCalc(), $array[9] ) if $t < 7 Then $a=MsgBox ( 4, "!", "      " &$t &" ."&@crlf&"    ?" ) if $a=6 then Run("explorer shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}") sleep(1000) endif endif endif _AD_Close() 


A simple implementation is supported by the _AD_GetPasswordInfo () function from the AD.au3 library. It gives an array of values ​​with password information, including its expiration time.



After the introduction of this mechanism, any problems with expired passwords stopped appearing.



Missing Domain



If the Active Directory infrastructure is not deployed for you - for example, in the case of a separate terminal server - then the solution also exists, albeit a bit more complicated.



To do this, we need a little bit of WMI magic and our favorite scripting language. Let's go back to the PowerShell examples:



 # . $Computer = $env:computername #  $UserName = $env:username #   $Days = 2 $User = [ADSI]"WinNT://$Computer/$UserName,user" $Flags = $User.UserFlags.psbase.Value #    . If ($Flags -band 65536) { "     " } Else { #   . $AgeDays = $User.PasswordAge.psbase.Value / 86400 $MaxAge = $User.MaxPasswordAge.psbase.Value / 86400 If ($AgeDays -gt $MaxAge) { " " } Else { If (($AgeDays + $Days) -gt $MaxAge) { "    $Days " } Else { "  " } } } 


With proper refinement, such a script can notify users at regular launch or upon login.



For a long time I thought about the meaning of the existence of the password lifetime. On the one hand, it is good and safe, on the other - the constant inventing of new passwords leads to the forgetting of these same passwords and, as a result, to stickers on the monitor and under the keyboard.



Therefore, more and more close to me is the practice when users themselves come up with passwords, but at the same time their work is regularly audited by a dictionary attack with utilities like L0phtCrack . The only requirement is the password length requirement (recalling the well-known xkcd image).



So it is possible for people to make life easier, and to avoid a defensive reaction to “tightening the screws” in the form of wonderful combinations like Qwerty123 . Well, and what - the system does not swear, but this is your IB ... ponapridumyvali here.



By the way, do you have an account manager or some fashionable youth practice of changing passwords?



')

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



All Articles