Used PowerShell to change my RHEL root passwords via PuTTY, but I don't know what I changed my password to

Basically the title. My friend provided me a script to batch change RHEL passwords via Powershell and PuTTY, but the new password I entered doesn't work when I try to log in. I think the issue is that it doesn't escape one of the special characters that's in the new password, but I can't figure out what the new password would have been.

The "new password" I used was similar to this: a1b2c3d"4e5f6g7

I attempted to replace the secure strings for regular strings, or use telnet instead of SSH with a packet capture to determine what exactly is being sent, but none of that has worked thus far.

System.Management.Automation.PSCredential -argumentlist "root",$newrootPassword
     $newrootPassword2 = Read-Host "Retype new root password" -AsSecureString
     $newrootCredential2 = new-object -typename System.Management.Automation.PSCredential -argumentlist "root",$newrootPassword2


    putty.exe -ssh -pw $oldrootCredential.GetNetworkCredential().Password root@$_

    echo y | plink.exe -ssh -v -pw $oldrootCredential.GetNetworkCredential().Password root@$_ "echo root:'$newrootPassword' | chpasswd" 2>&1 

I expected the new password to be a1b2c3d"4e5f6g7; however, this does not work upon login.


Solution 1:

The problem is you are trying to pass SecureString into something that expects a standard string. The Password property is in SecureString format, you won't be able to pass this to plink, it will just get translated as System.Security.SecureString If the password change actually worked this is what password would have been set.

To translate a SecureString to text format suitable for plink command you need to use function like this example from here

function Get-PlainText()
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.Security.SecureString]$SecureString
    )
    BEGIN { }
    PROCESS
    {
        $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString);

        try
        {
            return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr);
        }
        finally
        {
            [Runtime.InteropServices.Marshal]::FreeBSTR($bstr);
        }
    }
    END { }
}

You can test your commands by using Write-Host to output command line value before testing with actual plink.exe. Or you can run ProcMon and filter on Operation is Process Create, then when you see plink.exe launched you can use properties to see the full actual command line that is getting passed.