Search code examples
powershellpasswordspowershell-2.0securestring

Can I change the server administrator password using PowerShell SecureString?


I'm looking to write a script that will change the administrator password on a remote server using PowerShell. The following command will do this

$Admin=[adsi]("WinNT://" + MyServer + "/Administrator, user")
$Admin.SetPassword("NewPassword")

But I would like to be able to hide the "NewPassword" in the script to make it more secure.

So is there a way to save the "NewPassword" to a secure .txt file then be able to use it like this?

$Admin.SetPassword("$secureFile")

The script will be run as a scheduled task.


Solution

  • Yes, you can use the ConvertTo-SecureString and ConvertFrom-SecureString cmdlets to encrypt the password before saving it to a file on disk.

    However, keep in mind that you'll need an encryption key in order to encrypt/decrypt the password using the cmdlets. From the documentation:

    If an encryption key is specified by using the Key or SecureKey parameters, the Advanced Encryption Standard (AES) encryption algorithm is used. The specified key must have a length of 128, 192, or 256 bits because those are the key lengths supported by the AES encryption algorithm.

    If you don't specify a key, the Windows Data Protection API (DPAPI) will be used for the encryption. This means that the key will be tied to the user account who invoked the cmdlets. Now, if you're running the script as a scheduled job this solution will work just fine.

    Here's a couple of scripts that will save and read an encrypted password to an XML file on disk using a generated key:

    function Get-SecurePassword {
    <#
    .Synopsis
        Gets a password stored securely in an XML file.
    .Parameter Path
        The path to the XML file to import the password from.
    #>
    [CmdletBinding()]
    param(
        [Parameter(Position=1)]
        [string]$Path = "Password.xml"
    )
        if (Test-Path $Path) {
            $cache = Import-Clixml $Path
            $key = [System.Convert]::FromBase64String($cache.Secret)
            $password = $cache.EncryptedPassword | ConvertTo-SecureString -Key $key
            $password
        }
    }
    
    function Set-SecurePassword {
    <#
    .Synopsis
        Stores a password securely in an XML file.
    .Parameter Path
        The path to the XML file to export the password to.
    #>
    [CmdletBinding()]
    param(
        [Parameter(Position=1)]
        [string]$Password,
        [Parameter(Position=2)]
        [string]$Path = "Password.xml"
    )
        $key = New-StrongPasswordBytes -Length 32
        $textualKey = [System.Convert]::ToBase64String($key)
        $securePassword = $Password | ConvertFrom-SecureString -Key $key
        $cache = New-Object PSObject -Property @{ "EncryptedPassword" = $securePassword; "Secret" = $textualKey }
        $cache.PSObject.TypeNames.Insert(0, "SecurePassword")
        $cache | Export-Clixml $Path
    }
    
    function New-StrongPasswordBytes ($length) {
        Add-Type -Assembly System.Web
        $password = [System.Web.Security.Membership]::GeneratePassword($length, $length / 2)
        [System.Text.Encoding]::UTF8.GetBytes($password)
    }