使用Powershell -encoded命令传递参数 [英] Using Powershell -encodedcommand to pass parameters

查看:681
本文介绍了使用Powershell -encoded命令传递参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种将参数传递到Powershell脚本的优雅方法,在该脚本中,字符串可以包含任意数量的需要转义的特殊字符.例如,带有特殊字符的复杂密码.

I'm trying to find an elegant way of passing parameters to a powershell script where the string can contain any number of special characters that would need to be escaped. For example, a complex password with special characters.

我当时正在查看-encodedcommand选项,但看来这仅旨在传递编码的脚本块,而不是参数的编码版本.

I was looking at the -encodedcommand option but it seems like this is only intended to pass an encoded script block, not an encoded version of parameters.

例如,考虑以下脚本:

param(
[Parameter()][Alias("un")][string]$Username,
[Parameter()][Alias("pw")][string]$Password
)

Write-Host "Username: $Username"
Write-Host "Password: $Password"

字符串'-un testuser -pw testpw'的base64编码如下: LQB1AG4AIAB0AGUAcwB0AHUAcwBlAHIAIAAtAHAAdwAgAHQAZQBzAHQAcAB3AA ==

The string '-un testuser -pw testpw' is base64 encoded as the following: LQB1AG4AIAB0AGUAcwB0AHUAcwBlAHIAIAAtAHAAdwAgAHQAZQBzAHQAcAB3AA==

我尝试将脚本作为.ps1文件调用,并通过上述字符串传递-encodedcommand,但出现错误找不到与参数名称为'encodedcommand'匹配的参数

I tried calling the script as a .ps1 file and passing -encodedcommand with the above string but got the error 'A parameter cannot be found that matches parameter name 'encodedcommand'

好的,这必须是直接调用powershell.exe.

So, fine, this has to be a call to powershell.exe directly.

还尝试了以下方法: powershell.exe -encodedcommand LQB1AG4AIAB0AGUAcwB0AHUAcwBlAHIAIAAtAHAAdwAgAHQAZQBzAHQAcAB3AA == -file Base64ParamTest.ps1

Also tried the following: powershell.exe -encodedcommand LQB1AG4AIAB0AGUAcwB0AHUAcwBlAHIAIAAtAHAAdwAgAHQAZQBzAHQAcAB3AA== -file Base64ParamTest.ps1

这运行了脚本,但是参数没有值.

This ran the script, but the parameters had no value.

这表现出我所期望的,但是却不像我希望的那样.有没有办法将我自己的参数实际作为安全编码的字符串传递?

This is behaving as I would expect, but not as I would hope. Is there a way to actually pass my parameters themselves as safely encoded strings?

推荐答案

您必须将脚本调用作为命令的一部分包括在内,例如:

You have to include the script invocation as part of the command e.g.:

PS> $command = "& '$pwd\login.ps1' -un testuser -pw testpw"
PS> $bytes = [Text.Encoding]::Unicode.GetBytes($command)
PS> $encodedCommand = [Convert]::ToBase64String($bytes)
PS> powershell.exe -noprofile -encodedCommand $encodedCommand
Username: testuser
Password: testpw

以下是我过去记录的有关如何处理脚本密码的一些笔记:

Here are some notes I've taken in the past on how to deal with passwords in scripts:

###########################################################
#
# Stashing passwords to avoid interactive password prompting
#

# NOT RECOMMENDED BUT IF PASSWORD IS DYNAMIC OR WIDELY KNOWN

$passwd = ConvertTo-SecureString "Not Very Secret Password" -AsPlainText -Force

# Need a way to prompt for password and use clear text password for use with net use
$cred = Get-Credential
$cred.GetNetworkCredential().UserName 
$cred.GetNetworkCredential().Password

#
# SAFE BUT NOT NECESSARILY PORTABLE APPROACH 
# Depends on how DPAPI works with roaming profiles
#

# Capture once and store to file
$passwd = Read-Host "Enter password" -AsSecureString
$encpwd = ConvertFrom-SecureString $passwd
$encpwd
$encpwd > $path\password.bin

# Later pull this in and restore to a secure string
$encpwd = Get-Content $path\password.bin
$passwd = ConvertTo-SecureString $encpwd

# Let's see if the rehydrate worked?
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwd)
$str =  [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$str

$cred = new-object System.Management.Automation.PSCredential 'john',$passwd
$cred

# NOTE: The "secret" required to rehyrdate correctly is stored in DPAPI - consequence:
#       You can only rehydrate on the same machine that did the ConvertFrom-SecureString


#
# PORTABLE BUT NOT NECESSARILY SAFE APPROACH
#

# Let's do this so that it will work on multiple machines:

$key = 1..32 | ForEach-Object { Get-Random -Maximum 256 }
$passwd = Read-Host "Enter password" -AsSecureString
$encpwd = ConvertFrom-SecureString $passwd -Key $key
$encpwd
# Could easily modify this to store username also
$record = new-object psobject -Property @{Key = $key; EncryptedPassword = $encpwd}
$record
$record | Export-Clixml $path\portablePassword.bin

# Later pull this in and restore to a secure string
$record = Import-Clixml $path\portablePassword.bin
$passwd = ConvertTo-SecureString $record.EncryptedPassword -Key $record.Key

# Let's see if the rehydrate worked?
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwd)
$str =  [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$str

$cred = new-object System.Management.Automation.PSCredential 'john',$passwd
$cred

Start-Process powershell.exe -Credential $cred -NoNewWindow

# Portable is better BUT the secret (Key) is shared (stored with the password file)
# Can be reversed to original password - still much better than clear-text password
# stored in your script.

这篇关于使用Powershell -encoded命令传递参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆