microsoft_windows:adduser_powershell
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
microsoft_windows:adduser_powershell [2025/05/16 01:18] – rodolico | microsoft_windows:adduser_powershell [2025/05/25 01:24] (current) – rodolico | ||
---|---|---|---|
Line 5: | Line 5: | ||
It should not be interactive at all. | It should not be interactive at all. | ||
+ | |||
+ | The following is **insecure** as both the AES256 key and the password encrypted by it are in the script itself, so treat the script with the same security as you would the password itself. It obscures the password instead of actually hiding it; one step above actually putting the password in the file in plain text. It is secure against someone just reading it, but any script kiddie can hack the password in no time. | ||
+ | |||
+ | My initial, simplistic code did not take into account that when you create a secure passsword with no encryption key, it uses a key attached to the machine and user (maybe just the user). The result is that it will work just fine when run by the user on the same machine that generated it, but fails on other machines. | ||
+ | |||
+ | Note: I put a lot of comments in the scripts to explain what is going on. The actual code is very small. | ||
===== Generate password hash ===== | ===== Generate password hash ===== | ||
- | The first step is to generate a password | + | The first step is to generate a password, and encrypt it with a randomly generated key. This will save the results to two files, aes.key and encrypted_password.txt. |
- | <code powershell genPass.ps1> | + | Run this script one time and put the contents of the key and the encrypted passwords files into updateUser.ps1. Each time this is run, a new key is generated. |
- | $password = ConvertTo-SecureString -String " | + | |
- | $plain = convertFrom-securestring -securestring $password | + | |
- | $plain | + | |
- | </ | + | |
- | The final line will give a very long hex number, which is the hash of the password | + | <code powershell makepass.ps1> |
+ | # script to create a secure password and save it encrypted | ||
+ | # This will accept | ||
+ | # and save both the key and the encrypted password to files. | ||
+ | # This was createed to be used with the updateUser.ps1 script | ||
+ | # with the help of Copilot. | ||
+ | |||
+ | |||
+ | # Ensure | ||
+ | # Requires -Version 5.1 | ||
+ | # Requires -RunAsAdministrator | ||
+ | |||
+ | # Prompt for password | ||
+ | $password = Read-Host | ||
+ | |||
+ | # Generate a random key and save it | ||
+ | # Note: a new random key is generated each time this script runs. | ||
+ | # we save teh contents of the key to a file named aes.key | ||
+ | # This key should be kept secure and not shared publicly. | ||
+ | $key = New-Object Byte[] 32 | ||
+ | [Security.Cryptography.RNGCryptoServiceProvider]:: | ||
+ | Set-Content -Path " | ||
+ | |||
+ | # Export the secure string using the key | ||
+ | # The password will be encrypted using AES-256 with the generated key | ||
+ | # Note: The encrypted password will be saved in a file named encrypted_password.txt | ||
+ | $password | ConvertFrom-SecureString -Key $key | Set-Content " | ||
+ | </ | ||
===== Download and Modify script ===== | ===== Download and Modify script ===== | ||
Line 23: | Line 52: | ||
Adjust the following to your needs | Adjust the following to your needs | ||
- | * $password: Replace //Very Long Hex String from above// | + | * $username: Replace |
- | * $user: This will be the username you log in as | + | * $key: Replace the comma separated integers |
- | * $group: The group to add the user to | + | * $securePassword: Replace //contents of encrypted_password.txt// |
- | * $fullname: The display name of the user (optional) | + | * $fullName: This is the diplay name of the user |
- | * $description: A description of the user (optional) | + | * $description: An optional Description |
+ | * $localGroup: Group to add the user so (only one group) | ||
- | <code powershell adduser.ps1> | ||
- | # script to add a local user with admin privileges on a Windows machine | ||
- | # Generate the password hash with the following three lines (after changing " | ||
- | # | ||
- | # $password = ConvertTo-SecureString -String " | ||
- | # $plain = convertFrom-securestring -securestring $password | ||
- | # $plain | ||
- | # | ||
- | # paste the output into -String below | ||
- | # adjust the user and which group to add them to. | ||
- | # if user already exists, will ignore (with message. | ||
- | # password is updated no matter what | ||
- | # if user is already in group, will ignore (with message) | ||
- | $password | + | <code powershell updateUser.ps1> |
- | $user = ' | + | # Script to create or update a local user with a secure |
- | $group = "Administrators" | + | # This script checks if a local user exists, creates it if not, and sets the password. |
- | $fullname = "Test Account" | + | # It also ensures the user is part of the Administrators |
- | $description = 'Test Account' | + | # Requires -Version 5.1 |
+ | # Requires -RunAsAdministrator | ||
- | # Check if user exists | + | # this is insecure because both the key and the encrypted password are stored in plaintext within the script. |
- | if (-not (Get-LocalUser -Name $user -ErrorAction SilentlyContinue)) { | + | # and can be reversed to obtain the original password. |
+ | # This script is intended to be used with the makepass.ps1 script, which generates a secure password and key | ||
+ | # and saves it encrypted. | ||
+ | |||
+ | # For security, consider this password to be obscured, NOT secured. | ||
+ | |||
+ | # Define variables | ||
+ | # you must define $username, $key, and $securePassword variables before running this script. | ||
+ | |||
+ | |||
+ | # Ensure the username is valid and does not contain special characters | ||
+ | $userName = "Enter Username Here" # Replace with the actual username you want to create or update | ||
+ | |||
+ | # Replace with your actual key, contents of aes.key file | ||
+ | # The keyfile has 32 bytes, newline separated. Replace newlines with commas, | ||
+ | # and paste below. | ||
+ | # Example key: 96, | ||
+ | # Ensure the key is a byte array of 32 bytes | ||
+ | # Note: The key must be exactly 32 bytes for AES-256 encryption | ||
+ | $key = [Byte[]](1, | ||
+ | |||
+ | # Enter the contents of the file encrypted_password.txt here, within quotes. | ||
+ | # This should be the output from ConvertFrom-SecureString using the same key. | ||
+ | # Example: ' | ||
+ | # Note: The encrypted key will end with ' | ||
+ | $securePassword = ' | ||
+ | |||
+ | $fullName = "" | ||
+ | $description = "" | ||
+ | $localGroup = "" | ||
+ | |||
+ | # if $fullName is empty or null | ||
+ | if (-not $fullName) { | ||
+ | $fullName = $userName | ||
+ | } | ||
+ | |||
+ | # if $description is empty or null | ||
+ | if (-not $description) { | ||
+ | $description = "User created by script" | ||
+ | } | ||
+ | |||
+ | # if $localGroup is empty or null | ||
+ | if (-not $localGroup) { | ||
+ | $localGroup = " | ||
+ | } | ||
+ | |||
+ | # Check if user exists, create if not | ||
+ | if (-not (Get-LocalUser -Name $userName | ||
try { | try { | ||
- | New-LocalUser -Name $user | + | New-LocalUser -Name $userName |
- | Write-Host "User ' | + | |
} catch { | } catch { | ||
- | Write-Warning | + | Write-Error " |
+ | exit 1 | ||
} | } | ||
- | } else { | ||
- | Write-Host "User ' | ||
} | } | ||
- | # Set (or reset) | + | # Set the password |
try { | try { | ||
- | Set-LocalUser -Name $user -Password $password | + | Set-LocalUser -Name $userName |
- | Write-Host " | + | |
} catch { | } catch { | ||
- | Write-Warning | + | Write-Error " |
+ | exit 1 | ||
} | } | ||
- | # Add to local group if not already a member | + | # Ensure user is in correct |
- | try { | + | if (-not (Get-LocalGroupMember -Group $localGroup |
- | | + | try { |
- | Add-LocalGroupMember -Group $group -Member $user | + | Add-LocalGroupMember -Group $localGroup |
- | Write-Host "User ' | + | } catch { |
- | } else { | + | Write-Error "Failed to add user '$userName' |
- | Write-Host "User '$user' | + | exit 1 |
} | } | ||
- | } catch { | ||
- | Write-Warning " | ||
} | } | ||
+ | # Output success message | ||
+ | Write-Host "User ' | ||
</ | </ | ||
Line 88: | Line 151: | ||
===== Enhancements ===== | ===== Enhancements ===== | ||
- | Note, if the password hash is to be transported | + | * Do not send the script |
- | + | * Multiple groups could be set up by changing group to an array and then looping through them. | |
- | -SecureKey appearantly uses single pad encryption | + | * < |
+ | * < | ||
===== Links ===== | ===== Links ===== | ||
- | * https:// | + | |
+ | * https:// | ||
+ | | ||
+ | * Script was generated with the help of Copilot. While I had a majority of it written beforehand, Copilot became a shortcut to doing the whole AES thing. | ||
+ | * https:// | ||
* https:// | * https:// | ||
* https:// | * https:// | ||
Line 99: | Line 167: | ||
* https:// | * https:// | ||
* https:// | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
Also, thanks to DavidN for tightening it up a little for me. | Also, thanks to DavidN for tightening it up a little for me. |
microsoft_windows/adduser_powershell.1747376302.txt.gz · Last modified: 2025/05/16 01:18 by rodolico