PowerShell防止脚本注入攻击分享

  发布时间:2011-03-22 21:48:39   作者:佚名   我要评论
与其他编程语言一样,PowerShell 脚本容易受到注入攻击,易受攻击的函数运行额外的命令,这可能是严重的安全漏洞,了解问题后,可通过多种方式防范注入攻击

与其他编程语言一样,PowerShell 脚本容易受到注入攻击。 当用户向包含额外命令的易受攻击的函数提供输入时,会发生注入攻击。 易受攻击的函数运行额外的命令,这可能是严重的安全漏洞。 例如,恶意用户可能会滥用易受攻击的函数在远程计算机上运行任意代码,从而损害该计算机并获取对网络上其他计算机的访问权限。

了解问题后,可通过多种方式防范注入攻击。

易受攻击的代码示例

PowerShell 代码注入漏洞涉及包含脚本代码的用户输入。 用户输入添加到易受攻击的脚本中,由 PowerShell 分析和运行。

function Get-ProcessById { param ($ProcId) Invoke-Expression -Command "Get-Process -Id $ProcId" }

Get-ProcessById 函数按其 ID 值查找本地进程。 它采用任何类型的 $ProcId 参数。 然后将 $ProcId 转换为字符串,并插入到使用 Invoke-Expression cmdlet 分析和运行的另一个脚本中。 传入有效的进程 ID 整数时,此函数正常工作。

Get-ProcessById $pid NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 97 50.09 132.72 1.20 12528 3 pwsh

但是,$ProcId 参数未指定类型。 它接受任何可以包含其他命令的任意字符串值。

Get-ProcessById "$pid; Write-Host 'pwnd!'"

在此示例中,函数正确检索了由 $pid 标识的进程,但也运行了注入脚本 Write-Host 'pwnd!'。

NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 92 45.66 122.52 1.06 21736 3 pwsh pwnd!

防范注入攻击的方法

可通过多种方式防范注入攻击。

使用类型化输入

可以为 $ProcId 参数指定类型。

function Get-ProcessById { param ([int] $ProcId) Invoke-Expression -Command "Get-Process -Id $ProcId" } Get-ProcessById "$pid; Write-Host 'pwnd!'"

Get-ProcessById: Line | 7 | Get-ProcessById "$pid; Write-Host 'pwnd!'" | ~~~~~~~~~~~~~~~~~~~~~~~~~ | Cannot process argument transformation on parameter 'ProcId'. Cannot convert value "8064; Write-Host 'pwnd!'" to type "System.Int32". Error: "The input string '8064; Write-Host 'pwnd!' was not in a correct format."

此处,$ProcId 输入参数仅限于整数类型,因此,当传入不能转换为整数的字符串时,会发生错误。

不要使用 Invoke-Expression

无需使用 Invoke-Expression,直接调用 Get-Process,让 PowerShell 的参数绑定器验证输入。

function Get-ProcessById { param ($ProcId) Get-Process -Id $ProcId } Get-ProcessById "$pid; Write-Host 'pwnd!'"

Get-Process: Line | 5 | Get-Process -Id $ProcId | ~~~~~~~ | Cannot bind parameter 'Id'. Cannot convert value "8064; Write-Host 'pwnd!'" to type "System.Int32". Error: "The input string '8064; Write-Host 'pwnd!' was not in a correct format."

作为最佳做法,应避免使用 Invoke-Expression,尤其是在处理用户输入时。 Invoke-Expression 很危险,因为它会分析和运行你提供的任何字符串内容,使其容易受到注入攻击。 最好依赖于 PowerShell 参数绑定。

将字符串包含在单引号中

但是,有时使用 Invoke-Expression 是不可避免的,你还需要处理用户字符串输入。 可以使用每个字符串输入变量周围的单引号安全地处理用户输入。 单引号可确保 PowerShell 分析程序将用户输入视为单个字符串文本。

function Get-ProcessById { param ($ProcId) Invoke-Expression -Command "Get-Process -Id '$ProcId'" } Get-ProcessById "$pid; Write-Host 'pwnd!'"

Get-Process: Cannot bind parameter 'Id'. Cannot convert value "8064; Write-Host " to type "System.Int32". Error: "The input string '8064; Write-Host' was not in a correct format."

但是,此版本函数对于防范注入攻击还不是完全安全的。 恶意用户仍然可以在其输入中使用单引号来注入代码。

Get-ProcessById "$pid'; Write-Host 'pwnd!';'"

此示例在用户输入中使用单引号来强制函数运行三个单独的语句,其中一个语句是由用户注入的任意代码。

NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 97 46.08 183.10 1.08 2524 3 pwsh pwnd!

使用 EscapeSingleQuotedStringContent() 方法

若要防止用户插入自己的单引号字符来利用函数,必须使用 EscapeSingleQuotedStringContent() API。 这是 PowerShell System.Management.Automation.Language.CodeGeneration 类的静态公共方法。 此方法通过转义用户输入中包含的任何单引号来确保用户输入的安全性。

function Get-ProcessById { param ($ProcId) $ProcIdClean = [System.Management.Automation.Language.CodeGeneration]:: EscapeSingleQuotedStringContent("$ProcId") Invoke-Expression -Command "Get-Process -Id '$ProcIdClean'" } Get-ProcessById "$pid'; Write-Host 'pwnd!';'"

Get-Process: Cannot bind parameter 'Id'. Cannot convert value "8064'; Write-Host 'pwnd!';'" to type "System.Int32". Error: "The input string '8064'; Write-Host 'pwnd!';'' was not in a correct format."

使用 Injection Hunter 检测易受攻击的代码

Injection Hunter 是 Lee Holmes 编写的模块,其中包含用于检测代码注入漏洞的 PowerShell 脚本分析器规则。 使用以下命令之一从 PowerShell 库安装模块:

# Use PowerShellGet v2.x Install-Module InjectionHunter # Use PowerShellGet v3.x Install-PSResource InjectionHunter

可以使用此模块在生成、持续集成过程、部署和其他方案中自动执行安全分析。

$RulePath = (Get-Module -list InjectionHunter).Path Invoke-ScriptAnalyzer -CustomRulePath $RulePath -Path .\Invoke-Dangerous.ps1

RuleName Severity ScriptName Line Message -------- -------- ---------- ---- ------- InjectionRisk.InvokeExpression Warning Invoke-Dan 3 Possible script injection risk via the gerous.ps1 Invoke-Expression cmdlet. Untrusted input can cause arbitrary PowerShell expressions to be run. Variables may be used directly for dynamic parameter arguments, splatting can be used for dynamic parameter names, and the invocation operator can be used for dynamic command names. If content escaping is truly needed, PowerShell has several valid quote characters, so [System.Management.Automation.Languag e.CodeGeneration]::Escape* should be used.

相关文章

最新评论