如何使用硬编码密码修复 PowerShell 中 WinSCP SFTP 脚本的安全性

How to fix security within WinSCP SFTP scripts in PowerShell with hard-coded passwords

因此,我的组织委托我清理一些与某些自动化脚本有关的安全问题,这些脚本在 运行 作为自动化任务的脚本中具有硬编码密码。其中一项任务包含 SFTP 脚本,这些脚本使用密码、主机名、凭据、端口以及脚本中公开的所有内容来导出和导入文件。因此,我想首先了解如何在一个可以隐藏的单独文件中调用此类凭据,然后再了解加密和加盐。但我的主要重点是将它们从脚本中移除,以防流量每次都被拦截。 PowerShell 代码如下所示:

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
}

我们的另一个看起来像这样:

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
}

我熟悉 Python 和 json 以及在 json 文件中调用类似于以下内容的内容:

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

并在 Python 脚本中使用 (config['object']['nested_element']) 调用它。 我想用 PowerShell 做一些类似的事情,但是我对 PowerShell 的了解非常有限。

Yeppers,当然,永远不会在文件中以明文形式存储信用。

有多种方法可以存储凭据以供使用。安全文件(xml 等)、注册表或 Windows 凭据管理器,这在 Microsoft 网站以及网络上的许多文章和 Whosebug 上的问答中都有详细记录。

只需搜索 'securely store credentials PowerShell'

示例结果...

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 通过 MS 的模块 powershellgallery.com 可直接从您的 PowerShell 环境安装。

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.                                                      
... 
#>

非常感谢@postanote 和@Martin Prikryl 我能够解决这个问题。 您基本上可以使用内容类似于以下内容的 config.xml 文件:

<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>

从这里您可以在模板的开头使用以下内容:

# 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
    }

我这里有更多的 SFTP 模板,人们可以在
https://github.com/Richard-Barrett/ITDataServicesInfra/tree/master/SFTP