1

So my organization has tasked me with cleaning up some of the security issues in regards to some automated scripts that have hard coded passwords within the scripts that are running as automated tasks. One such task contains SFTP scripts that export and import files to and from with the password, host name, credentials, port, and everything exposed within the script. As a result, I would like to first see about how to call such credentials within a separate file that can be hidden and two see about encryption and salting it later. But my main focus is getting them out of the script in case traffic is every intercepted. Here is what the PowerShell code looks like:

param (
    $localPath = 'E:\FTP\SchooLinks\course_requests.csv',
    $remotePath = '/schoolinks_exports/course_planning/course_requests.csv'
)

try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "<domain_name>"
        UserName = "<username>"
        Password = "<password>"
        SshHostKeyFingerprint = "<fingerprint>"
    }

    $session = New-Object WinSCP.Session

    try
    {
        # Connect
        $session.Open($sessionOptions)

        # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary

        $transferResult =
            $session.GetFiles($remotePath, $localPath, $False, $transferOptions)

        # Throw on any error
        $transferResult.Check()

        # Print results
        foreach ($transfer in $transferResult.Transfers)
        {
            Write-Host "Download of $($transfer.FileName) succeeded"
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }

    exit 0
}
catch
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

Another one that we have looks like this:

param (
    $localPath = 'E:\FTP\TalentEd\SkywardApplicantExportSQL.txt',
    $remotePath = '/SkywardApplicantExportSQL.txt'
)

try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "<domain>"
        UserName = "<username>"
        Password = "<password>"
        SshHostKeyFingerprint = "<sha_fingerprint>"
    }

    $session = New-Object WinSCP.Session

    try
    {
        # Connect
        $session.Open($sessionOptions)

        # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary

        $transferResult =
            $session.GetFiles($remotePath, $localPath, $False, $transferOptions)

        # Throw on any error
        $transferResult.Check()

        # Print results
        foreach ($transfer in $transferResult.Transfers)
        {
            Write-Host "Download of $($transfer.FileName) succeeded"
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }

    exit 0
}
catch
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

I am familiar with Python and json and calling stuff within a json file similar to the following:

import json
with open('secrets.json','r') as f:
      config = json.load(f)

and calling it with (config['object']['nested_element']) within the Python script. I would like to do something similar with PowerShell, however I have very limited knowledge to PowerShell.

2 Answers 2

2

Yeppers, of course, never store creds in clear text in files.

There are several ways to store credentials for use. Secure file (xml, etc..), the registry, or Windows Credential Manager and this is well documented on Microsoft sites, as well as in many articles all over the web and via Q&A's on StackOverflow.

Just search for 'securely store credentials PowerShell'

Sample results...

Working with Passwords, Secure Strings and Credentials in Windows PowerShell

How to run a PowerShell script against multiple Active Directory domains with different credentials

Accessing Windows Credentials Manager from PowerShell

Save Encrypted Passwords to Registry for PowerShell

...and/or the modules via the MS powershellgallery.com directly installable from your PowerShell environments.

Find-Module -Name '*cred*' | 
Format-Table -AutoSize
<#
# Results

Version        Name                            Repository Description                                                                                          
-------        ----                            ---------- -----------                                                                                          
2.0            CredentialManager               PSGallery  Provides access to credentials in the Windows Credential Manager                                     
2.0.168        VcRedist                        PSGallery  A module for lifecycle management of the Microsoft Visual C++ Redistributables. Downloads the supp...
1.3.0.0        xCredSSP                        PSGallery  Module with DSC Resources for WSMan CredSSP.                                                         
1.1            VPNCredentialsHelper            PSGallery  A simple module to set the username and password for a VPN connection through PowerShell. Huge tha...
1.0.11         pscredentialmanager             PSGallery  This module allows management and automation of Windows cached credentials.                          
4.5            BetterCredentials               PSGallery  A (compatible) major upgrade for Get-Credential, including support for storing credentials in Wind...
1.0.4          WindowsCredential               PSGallery  Management module for Windows Credential Store.                                                      
... 
#>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @postanote I really appreciate the insights.
No worries. Glad it was useful.
WinSCP site itself has an article that covers this: Protecting credentials used for automation.
1

So many thanks to @postanote and @Martin Prikryl I was able to figure this out. You can basically use a config.xml file with contents similar to this:

<Configuration>
  <localPath>insert_local_file_path</localPath>
  <remotePath>insert_remote_file_path</remotePath>
  <Protocol>[WinSCP.Protocol]::Sftp</Protocol>
  <HostName>insert_hostname</HostName>
  <UserName>username</UserName>
  <Password>mypassword</Password>
  <SshHostKeyFingerPrint>fingerprint</SshHostKeyFingerPrint>
</Configuration>

From here you can use the following at the beginning of your template:

# Read XML configuration file
[xml]$config = Get-Content ".\config.xml"

param (
    $localPath = $config.Configuration.localPath
    $remotePath = $config.Configuration.remotePath
)

try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = $config.Configuration.Protocol
        HostName = $config.Configuration.HostName
        UserName = $config.Configuration.UserName
        Password = $config.Configuration.Password 
        SshHostKeyFingerprint = $config.Configuration.SshHostKeyFingerprint
    }

I have more SFTP templates here people can use at
https://github.com/Richard-Barrett/ITDataServicesInfra/tree/master/SFTP

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.