我正在准备新电脑。应用图像后,我运行 PowerShell 脚本以执行一些图像后部署步骤。某些步骤必须以新(当前)用户身份运行,例如 HCCU 中的注册表设置,而其他通过脚本穿插的步骤必须以提升权限运行。
在我的脚本中,我为需要提升的代码调用下面的
RunElevated
函数。我想在提升和非提升代码块之间共享值和函数,但这可能吗?我尝试在调用 Start-Process powershell.exe 时传递参数,但遇到了引号中的引号、参数中的参数的“Inception”问题。
function RunElevated($ScriptBlock)
{
write-host -NoNewline "`nStarting a new window with elevated privileges. Will return here after..."
$scriptBlockWithBefore = {
write-host "`nSTEPS RUNNING WITH ELEVATED PRIVILEGES...`n" @mildAlertColours
}
$scriptBlockAfter = {
Write-Host -nonewline "`nHit Enter to exit this mode. "
Read-Host
}
$scriptBlockToUse = [scriptblock]::Create($scriptBlockWithBefore.ToString() + "`n" + $ScriptBlock.ToString() + "`n" + $scriptBlockAfter)
$proc = Start-Process "powershell.exe" -Verb runas -ArgumentList "-command `"$scriptBlockToUse`"" -PassThru -WorkingDirectory $pwd.ToString()
$proc.WaitForExit()
if($proc.ExitCode -ne 0) {
write-host "ran into a problem."
}
}
如 zett42 所述,您可以使用
powershell.exe
,Windows PowerShell CLI 的 -EncodedCommand
参数 安全地将任意代码传递给 PowerShell 子进程。
也通过arguments安全,你需要(目前未记录)
-EncodedArguments
参数。
这种基于Base64编码的方法:
这里是独立的示例代码演示了该技术:
# Sample script block to execute in the elevated child process.
$scriptBlock = {
# Parameters
param([string] $Foo, [int] $Bar, [hashtable] $Hash)
# Embedded function
function Get-Foo { "hi: " + $args }
# Show the arguments passed.
$PSBoundParameters | Out-Host
# Call the embedded function
Get-Foo $Bar
Read-Host 'Press Enter to exit.'
}
# List of sample arguments to pass to the child process.
$passThruArgs = 'foo!', 42, @{ SomeKey = 'Some Value' }
# Call via `Start-Process -Verb RunAs` to achieve elevation, and pass the
# Base64-encoded values to `-EncodedCommand` and `-EncodedArgument`
Start-Process -Wait -Verb RunAs powershell.exe -ArgumentList (
'-EncodedCommand', (
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($scriptBlock))
),
'-EncodedArguments', (
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes(
[System.Management.Automation.PSSerializer]::Serialize($passThruArgs)
))
)
)
注:
Start-Process
的-ArgumentList
参数是安全的,因为按定义传递的参数不包含空格或其他元字符。
Cpt.Whale 提出了一个很好的观点:如果您将需要提升的部分外包到 separate scripts(
*.ps1
文件),通过 Start-Process -Verb RunAs
的调用变得更简单,因为这样您就不必通过 CLI 传递 code,并且可以使用 -File
CLI 调用而不需要 Base64 编码。但是,您随后仅限于 strings 或具有 string-literal representations. 的参数
可选阅读:为什么selective elevation可能是首选/必要的:
您可能 prefer 选择性提升以获得更好的安全性:它允许您将使用提升运行的内容限制为仅真正需要它的代码。
你需要选择性海拔:
如果提升发生在不同的用户上下文中并且您的部分代码需要在当前用户的上下文中运行。
即使在 same 用户上下文中发生提升,在以提升运行时明显 not 执行的操作 - 至少在默认情况下 - 是 establish persistent drive mappings for the current user:
[1] 有关详细信息,请参阅此答案。