📜 ⬆️ ⬇️

Some features of PowerShell when working with user accounts

I thought I was pretty good at powershell, but I never had to work with user credentials. However, now I’m looking for a job and at one of the interviews I was given a test task to write a script, which should:

  1. Check availability and status (enabled / disabled) of user account.
  2. Check whether the account is included in the group "Administrators"
  3. If there is no account, then create an account and add it to the administrators group, set the flags “Prevent the user from changing the password” and “The password does not expire”
  4. If the account exists, but is disabled or not in the “Administrators” group, then enable the account and add it to the “Administrators” group, set the “Prevent a user from changing the password” flags and “The password will not expire”
  5. The script should not depend on the language of the operating system.


I thought that nothing complicated and the first thing I decided to check is the Admin user on my computer. Without thinking, I hammered the command:

Get-User admin 

And immediately got an error
')
Get-User : "Get-User" , , .

A little taken aback by the fact that such a useful command did not recognize I googled and found that the Get-User command only works in the Powershell console for Exchange. To work with local users, you must use Get-Localuser , and for domain Get-Aduser . Realizing my mistake, I hammered:

 Get-Localuser admin 

And got an answer

 Name Enabled Description ---- ------- ----------- Admin True     / 

Well, now check whether there is a user or not, it will not be a big deal, however, another trick was waiting for me here. It was not so easy to do this through the if else conditional operator.

The fact is that if the user is in the system, then the output is not true, but a whole data set, with the name, description of the user, whether this account is enabled or not. And if there is no user, then powershell gives an error. After wandering through the expanses of the Internet, I found that for these purposes it is better to use the try catch operator.

 $user = 'admin' try { Get-LocalUser $user -ErrorAction Stop | Out-Null write-host  $user  -foregroundcolor Green } Catch { write-host  $user  -foregroundcolor Red } 

I added the $ user variable to make it easier to change usernames throughout the script. ErrorAction Stop is required so that the script does not stop at this step due to an error. Sign | separates the pipeline steps, and Out-Null will hide the error text output. I also added a text output with highlighting, for the convenience of checking the script.

Next, I wanted to check whether the account is enabled or disabled. As I said before, the Get-LocalUser command issues a whole set of data and for testing, I only needed to select one parameter Enabled with a value of true or false. To do this, I used the following command:

 (Get-LocalUser $user).enabled 

After making sure that it works, I did the following check and added a command to enable the user.

 $user = 'admin' if ((Get-LocalUser $user).enabled -eq "True") { write-host    -foregroundcolor Green } else { write-host    -foregroundcolor Red Enable-LocalUser $user write-host    -foregroundcolor Green } 

To enable the user, it is naturally necessary to run the console as an administrator.

In the second paragraph of the task, it was necessary to determine whether the user is in the group of administrators. To check for the presence of a user in a particular group, there is a Get-LocalGroupMember command. However, the name of the administrators group changes with the language of the operating system. So I had to use the standard SID S-1-5-32-544. I also made a check through try watch.

 $user = 'admin' try { Get-LocalGroupMember -SID S-1-5-32-544 -Member $user -ErrorAction Stop | Out-Null write-host  $user     -foregroundcolor Green } Catch { write-host  $user      -foregroundcolor Red Add-LocalGroupMember -SID S-1-5-32-544 -Member $user write-host  $user     -foregroundcolor Green } 

If the user is not in the group, administrators will be added to it.
At the next stage, I had the task to determine whether the user’s password change setting is disabled or not. Then I came across another pitfalls. The fact is that if a user has a password expiration date unlimited, then the PasswordExpires parameter does not display any values. And if this checkbox is disabled, then different users will have different date of password change. I came up with a way out of this situation:

 if ((Get-LocalUser $user).PasswordExpires -eq $null) { write-host      -foregroundcolor Green } else { write-host     -foregroundcolor Red set-LocalUser $user -PasswordNeverExpires:$true write-host      -foregroundcolor Green } 

Then I needed to create a user. I did not expect that a trick might be waiting for me here too. When creating a user team

 new-LocalUser -User $user -password P@ssW0rD! 

An error is returned:

"Password". "P@ssW0rD!" "System.String" "System.Security.SecureString".

The fact is that the -password parameter should use SecureString, instead of a plain text string. For this, I made the $ password variable and converted it to a securestring.

 $password = convertto-securestring "P@ssW0rD!" -asplaintext -force 

And the script itself to create a user and add it to the group of administrators

 new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true Add-LocalGroupMember -SID S-1-5-32-544 -Member $user 

A ready script that takes into account all the conditions I have turned out this way:

 $user = 'admin' $password = convertto-securestring "P@ssW0rD!" -asplaintext -force try { Get-LocalUser $user -ErrorAction Stop | Out-Null cls write-host  $user  -foregroundcolor Green if ((Get-LocalUser $user).enabled -eq "True") { write-host    -foregroundcolor Green } else { write-host    -foregroundcolor Red Enable-LocalUser $user write-host    -foregroundcolor Green } if ((Get-LocalUser $user).PasswordExpires -eq $null) { write-host      -foregroundcolor Green } else { write-host     -foregroundcolor Red set-LocalUser $user -PasswordNeverExpires:$true write-host      -foregroundcolor Green } try { Get-LocalGroupMember -SID S-1-5-32-544 -Member $user -ErrorAction Stop | Out-Null write-host  $user     -foregroundcolor Green } Catch { write-host  $user      -foregroundcolor Red Add-LocalGroupMember -SID S-1-5-32-544 -Member $user write-host  $user     -foregroundcolor Green } } Catch { cls write-host  $user  -foregroundcolor Red new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true Add-LocalGroupMember -SID S-1-5-32-544 -Member $user write-host  $user       -foregroundcolor Green } 

Post Scriptum

However, storing the administrator password in a script is not the best practice in terms of security. To do this, you can use the password hash, not the password itself.

 $user = 'admin1' $hash = "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000048baf1b47a72d845b4eeda8659da9fd70000000002000000000010660000000100002000000004d2a3bf03aac92c2e172dc002d1fe8759da4655850462aface5c25f52921e05000000000e8000000002000020000000bfa652b6f7cc6845e3cee1831b54ab93dc272d0b2203024c3de8bc4789a2698a10000000923fb50dcf01125913534d0c1ba6d827400000002757df7d8a8b39c8e84b81323acff1d72419580a0022cf610926e5f081a2e895320088d482eb407f8157aad82f091abee7427b357e871d12238a8f74131238e7" $hash $password = ConvertTo-SecureString -String $hash $password new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true Add-LocalGroupMember -SID S-1-5-32-544 -Member $user 

To get a password hash, you can use the following script

 $Secure = Read-Host -AsSecureString $Secure $hash = ConvertFrom-SecureString -SecureString $Secure $hash 

Which will ask for a password from the keyboard.

And a small bonus for displaying all disabled entries.

 Get-LocalUser | Where-Object {$_.enabled -eq $false} 

I hope my time will help someone in their work. Yes, and for yourself it will be useful not to forget this invaluable experience.

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


All Articles