3

I'm trying to use WinSCP .NET assembly with secure credential, when the password secured in external file.

# Load WinSCP .NET assembly
Add-Type -Path "D:\WinSCPnet.dll"

# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp

# Env
$sessionOptions.HostName = "blabla.com"
$sessionOptions.UserName = "UUUU"
#$sessionOptions.Password = "PPPP"
$sessionOptions.SshHostKeyFingerprint = "XXXXXXXXX"
$remotePath = "/home/UUUU/"

With hard coded password its working. If I would like to use securestring for the password, how should I do that?

I tried:

read-host -assecurestring | convertfrom-securestring | out-file D:\securestring.txt

To keep the secure password in a file. Then, in my script, I get it back:

$sessionOptions.Password = get-Content D:\securestring.txt | convertto-securestring

$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $sessionOptions.UserName, $sessionOptions.Password}

But it's not working...

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
yaniv
  • 31
  • 1
  • 4

3 Answers3

4

Since WinSCP 5.7, the assembly accepts the SecureString using the SessionOptions.SecurePassword.

See https://winscp.net/eng/docs/library_sessionoptions

Thanks for inspiring this improvement.

While the assembly keeps the password encrypted in memory, it still needs to decrypt it eventually. Improvements to limit internal copies of the decrypted password are pending.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
3

As @Matt pointed out, the WinSCP .Net assembly doesn't accept secure strings or credential objects. You need to pass the password as a plaintext string. You can store the secure string in a file, though:

Read-Host 'Enter password' -AsSecureString |
  ConvertFrom-SecureString |
  Out-File 'C:\password.txt'

and use a PSCredential object to retrieve the decrypted password from the secure string after you read it from the file:

$un   = 'username'
$pw   = Get-Content 'C:\password.txt' | ConvertTo-SecureString
$cred = New-Object Management.Automation.PSCredential $un, $pw

try {
  Add-Type -Path 'WinSCPnet.dll'

  $opt = New-Object WinSCP.SessionOptions
  $opt.Protocol = [WinSCP.Protocol]::Sftp
  $opt.HostName = 'example.org'
  $opt.UserName = $cred.UserName
  $opt.Password = $cred.GetNetworkCredential().Password
  $opt.SshHostKeyFingerprint = 'ssh-rsa 2048 ...'

  $sftp = New-Object WinSCP.Session

  $sftp.Open($opt)
  ...
} catch {
  ...
} finally {
  if ($sftp) { $sftp.Dispose() }
}

WinSCP sample code taken from the documentation.

Note, however, that the password must be saved by the same user who is running the SFTP PowerShell script, because the encryption key is derived from that user's password.

Community
  • 1
  • 1
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
1

According to WinSCP the password property just supports a string. So trying to pass a secure string will not work. If you really want to store the password in a file, you could attempt to store it as the secure string but that is a really bad idea in general since it can be unsecured just as easily (Also not sure if it is possible). I recommend the following option.

# Only stored in memory which is safer.
$sessionOptions.Password = read-host

If you have your heart set on something else you could try this. Just know for previous reasons I do not condone this. Also i have to see if it even works because it looks like you cant output securestring to file.

read-host | out-file D:\securestring.txt
$sessionOptions.Password = get-Content D:\securestring.txt

Ansgar's explains what I didn't know was possible. You can stored the secure string in a file and use it elsewhere.

Matt
  • 45,022
  • 8
  • 78
  • 119