不要使用Invoke-Expression
,这与我脑海中长期存在的安全问题相关,需要提问。强烈的声明(参考 Invoke-Expression被认为是有害的文章)表明调用一个可以覆盖变量的脚本是有害的。
此外,PSScriptAnalyzer也建议不要使用
Invoke-Expression
,请参见AvoidUsingInvokeExpression规则。但是,我曾经自己使用过一种技巧来更新递归脚本中的公共变量,它实际上可以覆盖任何父级范围中的值,代码非常简单:
([Ref]$ParentVariable).Value = $NewValue
据我所知,一个潜在的恶意脚本也可以使用此技术来注入变量,无论如何调用都可以实现... 请考虑以下“恶意”
Inject.ps1
脚本:([Ref]$MyValue).Value = 456
([Ref]$MyString).Value = 'Injected string'
([Ref]$MyObject).Value = [PSCustomObject]@{Name = 'Injected'; Value = 'Object'}
我的Test.ps1
脚本:
$MyValue = 123
$MyString = "MyString"
$MyObject = [PSCustomObject]@{Name = 'My'; Value = 'Object'}
.\Inject.ps1
Write-Host $MyValue
Write-Host $MyString
Write-Host $MyObject
结果:
456
Injected string
@{Name=Injected; Value=Object}
正如您所看到的,在Test.ps1
范围中的所有三个变量都被Inject.ps1
脚本覆盖了。使用 Invoke-Command cmdlet 也可以实现这一点,而且无论我将变量的作用域设置为Private
都没有关系:
New-Variable -Name MyValue -Value 123 -Scope Private
$MyString = "MyString"
$MyObject = [PSCustomObject]@{Name = 'My'; Value = 'Object'}
Invoke-Command {
([Ref]$MyValue).Value = 456
([Ref]$MyString).Value = 'Injected string'
([Ref]$MyObject).Value = [PSCustomObject]@{Name = 'Injected'; Value = 'Object'}
}
Write-Host $MyValue
Write-Host $MyString
Write-Host $MyObject
是否有一种方法可以完全隔离调用的脚本/命令,以防止其覆盖当前作用域中的变量?
如果没有,那么以任何方式调用脚本是否会被视为安全风险?
$private:
来创建所有变量也是不切实际的。此外,其他经过验证的代码可能依赖于变量不是私有的。至于Invoke-Command
:不幸的是,文档是错误的:默认情况下,本地调用发生在子范围中,但是您可以使用-NoNewScope
选择进入同一范围执行。 - mklement0