如何安全地存储使用 Windows 任务计划程序每天运行的脚本的密码?

问题描述 投票:0回答:1

我编写了一个PowerShell脚本来执行一些操作。操作完成后,我希望脚本使用

Send-MailMessage
cmdlet 发送邮件。

为此,我使用了谷歌的应用程序密码功能。但我对将应用程序密码以纯文本形式存储在脚本本身中没有信心。我可以以某种方式加密并将其存储在脚本或单独的文件中,但人们仍然可以看到该密码。即使我加密密码,解密登录名也会存在于脚本本身中。我认为有用的另一种方法是将加密密码作为环境变量传递,但是 1.我找不到如何做到这一点,2.我仍然认为这不安全,因为人们可以检查环境变量。

有没有更好的方法来实现这个目标?

powershell password-encryption
1个回答
1
投票

处理凭据的一般方法是避免它们,而是依赖其他方式进行身份验证,例如证书或 Windows 身份验证。

正如您自己显然发现的那样,尝试编写单因素身份验证的脚本要么会导致catch-22,要么不安全,因为无论您的深度有多深,有权访问您的脚本的每个人都可以访问密钥使用通过默默无闻的安全性来隐藏它。

如果您无法更改服务器的身份验证方式,最安全实用的方法可能是使用 Windows DPAPI(数据保护 API) 创建您自己的“单点登录”,其中加密基于计算机和用户凭据。

为此,您可以使用 PowerShell ConvertTo-SecureStringConvertFrom-SecureString cmdlet。
首先创建一个安全字符串(在相关计算机/用户帐户下):

Read-Host 'Enter your password' -AsSecureString | ConvertFrom-SecureString

这将返回一个字符串,例如:

01000000d08c9ddf0115d1118c7a00c04fc297eb01000000da4b9d0c09bdb140b3060606f3557e1200000000020000000000106600000001000020000000319f97dca4698fd8848b183e0a7e3fa26127043f68b75ed0ffad6e60eee59201000000000e8000000002000020000000e7f6f6c563f442ef7563967ab907abd528147e1cb8d03efdb4892f29ecbe38d3100000003098dedec04172048148654f5846bbcd40000000d270797bc32ba3d42a217d26dc1395b4bbf4fb4a9f9fe701b98270e1db848de3b048c36a792061fea06e1123b0288d687ffdda2ae934f63f60d58a8c19631007

⚠️警告
SecureString 的内容在非 Windows 系统上未加密。

您可以将此字符串放入环境变量或其他位置,甚至简单地将其嵌入到您的脚本中:

$EncryptedPassword = '01000000d08c9ddf...

请注意,此字符串只能在特定计算机上并由创建

$EncryptePassword
的用户帐户解密。此限制实际上增加了安全性(还知道每次使用
ConvertFrom-SecureString
命令时,您都会得到不同的字符串)。

要在脚本中显示纯文本密码,您可以执行以下操作:

$Password = $EncryptedPassword | ConvertTo-SecureString | ConvertFrom-SecureString -AsPlainText

请注意,您实际上应该尽量避免使用上述命令,因为这会泄露密码并可能留下记忆痕迹,至少执行一次

Remove-Variable $Password
是一件好事。

加密您的脚本

您甚至可以考虑使用 DPAPI 加密您的整个脚本,包括硬编码的纯密码(这实际上比使用

PS12EXE
这样的工具更安全):

  • New-EncryptedScript.ps1
param(
    [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
    [string] $Path,
    [switch] $AsBase64
)
$Item = Get-Item $Path
if ($Item) {
    $OutPath = "$($Item.DirectoryName)\$($Item.BaseName).Encrypted$($Item.Extension)"
    $ScriptBlock = Get-Content -Raw -Path $Path
    $Hex = $ScriptBlock | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
    if ($AsBase64) {
        $Bytes = [byte[]] -split ($Hex -replace '..', '0x$& ')
        $Base64 = [Convert]::ToBase64String($Bytes)
        Set-Content -Path $OutPath "`$Base64 = '$Base64'"
        Add-Content -Path $OutPath '$Bytes = [System.Convert]::FromBase64String($Base64)'
        Add-Content -Path $OutPath '$Hex = -Join $Bytes.Foreach{ $_.ToString("x2") }'
    }
    else {
        Set-Content -Path $OutPath "`$Hex = '$Hex'"
    }
    Add-Content -Path $OutPath '$ScriptBlock = $Hex | ConvertTo-SecureString | ConvertFrom-SecureString -AsPlainText'
    Add-Content -Path $OutPath 'Invoke-Expression $ScriptBlock'
    Add-Content -Path $OutPath 'Remove-Variable Base64, Bytes, Hex, ScriptBlock -ErrorAction SilentlyContinue'
}

用途:

.\New-EncryptedScript.ps1 .\MailMessage.ps1 -AsBase64

.\MailMessage.Encrypted.ps1

再次强调:

.\MailMessage.Encrypted.ps1
脚本只能在计算机和创建它的帐户上运行。

© www.soinside.com 2019 - 2024. All rights reserved.