Search code examples
batch-filefor-loopsshpassword-encryptionplink

Using encrypted password to SSH to multiple servers using Plink


My batch file code requires to run some shell commands on multiple servers using SSH. For that I'm using Plink from a for loop.

I do not want to enter the password in plain text to the Plink command line using -pw. Instead, due to security concerns, I want to use a password encryption for my password and store the password into a separate text file.

I tried using sshpass, but that is not supported in batch. As request to run the code will be on multiple servers, so I don't want to generate SSH key pair for each server as it will not be possible for hundreds of servers in the environment.

@echo off
for /f "delims=" %%a in (path\to\servers.txt) DO (
    plink -v -ssh user@%%a -pw MY_PASSWORD echo %%a ; cat /path/to/config_file
)
pause

I expect the batch script to run on all servers using encrypted password. But with current code, the output is displayed using plain password.


Solution

  • It's difficult to achieve this with a plain batch file.

    But you can use PowerShell instead with its ConvertTo-SecureString and ConvertFrom-SecureString cmdlets.

    To encrypt a password use:

    Read-Host -AsSecureString | ConvertFrom-SecureString
    

    Type the password and save the output to a file (encryptedpassword.txt).

    To use the encrypted password, use:

    $encrypted = ConvertTo-SecureString(Get-Content ".\encryptedpassword.txt")
    $bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($encrypted)
    $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
    
    foreach ($hostname in (Get-Content ".\servers.txt"))
    {
        .\plink user@$hostname -pw "$password"
    }
    

    In PowerShell 7, you can simplify the code to:

    $encrypted = ConvertTo-SecureString(Get-Content ".\encryptedpassword.txt")
    $password = ConvertFrom-SecureString -SecureString $encrypted -AsPlainText
    # ...
    

    Based on:


    Though I have to repeat that using a public key authentication would be a way better solution.