调用 (&) 运算符比 Invoke-Expression 更不容易受到代码注入攻击吗?

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

PowerShell 函数需要运行一个 .exe,其位置在设计时未知,因为它是 NuGet 包的一部分。如果我使用

Invoke-Expression
运行它,那么 PSScriptAnalyzer 会发出警告,告诉我寻找替代方法,但是如果我使用
&
运行它,那么我不会收到任何警告。

这是一个模块的一部分,用于在安装的 IDE 不支持代码覆盖率的计算机(例如 Visual Studio Community Edition)上运行单元测试并生成代码覆盖率报告。

function Invoke-ReportGenerator {
    param (
        [Parameter(Mandatory=$true)][string]$testProjectFolder,
        [Parameter(Mandatory=$true)][string]$testProjectName,
        [Parameter(Mandatory=$true)][string]$assemblyUnderTest,
        [Parameter(Mandatory=$false)][string]$coverageXmlFilename,
        [Parameter(Mandatory=$false)][string]$reportGeneratorPath
    )

    if ([System.String]::IsNullOrWhiteSpace($coverageXmlFilename)) {
        $coverageXmlFilename = "coverage.opencover.xml";
    }

    $absoluteOutputPath = [System.IO.Path]::Combine($testProjectFolder, "CodeCoverage");
    $absoluteInputPath = [System.IO.Path]::Combine($testProjectFolder, $coverageXmlFilename);
    $argumentArray = @(
        "-reports:$absoluteInputPath",
        "-targetDir:$absoluteOutputPath",
        "-title:$testProjectName",
        "-assemblyFilters:$assemblyUnderTest"
    );
    if ([System.String]::IsNullOrWhiteSpace($reportGeneratorPath)) {
        $reportGeneratorPath = "$env:USERPROFILE\.nuget\packages\reportgenerator\5.2.4\tools\net6.0\reportgenerator.exe ";
    }

    $reportGeneratorCommand = "$reportGeneratorPath $argumentArray";
    Invoke-Expression $reportGeneratorCommand;
}

这是 PSScriptAnalyzer 发出的警告

Invoke-Expression is used. Please remove Invoke-Expression from script and find other options instead.

Microsoft 文档说避免使用 Invoke-Expression

仔细考虑安全隐患。当来自不受信任源(例如用户输入)的字符串直接传递到 Invoke-Expression 时,可以执行任意命令。始终首先考虑不同的、更强大、更安全的解决方案。

如果我改变线路

Invoke-Expression $reportGeneratorCommand;

& $reportGeneratorCommand;

然后警告消失。但这肯定和

Invoke-Expression
一样容易受到代码注入攻击吗?我错过了什么?

编辑:按照@MathiasRJessen的建议,用

& $reportGeneratorPath @argumentArray
替换函数的最后两行稍微简化了函数,但我相信仍然容易受到攻击。

powershell code-injection
1个回答
0
投票

Invoke-Expression
和调用运算符(
&
.
)之间的区别是结构化语法

Invoke-Expression
不同,运算符单独接受目标命令和参数,并且按照注释中的建议,您应该像这样使用它们:

& $command @arguments

但我相信它仍然很脆弱。

也许下面的例子会动摇你的信念。

让我们首先定义一个目标命令和一些用户提供的参数,包括尝试的命令注入:

$command = 'Write-Host'
$arguments = @(
  'Legitimate message'
  ';'
  'Write-Host'
  'malware'
)

让我们看看当我们构造一个字符串并将其传递给

Invoke-Expression
时会发生什么,就像您到目前为止所做的那样:

PS ~> $expression = "$command $arguments"
PS ~> Invoke-Expression $expression
Legitimate message
malware

如您所见,

Invoke-Expression
愉快地评估了目标命令和最后添加的
Write-Host malware
命令。

让我们尝试使用调用运算符进行相同的操作:

PS ~> & $command @arguments
Legitimate message ; Write-Host malware

正如您在此处看到的,所有参数都按原样传递 - 不调用调用者注入的任何其他命令。

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