当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 防止脚本注入攻击

作者:精品下载站 日期:2024-12-14 02:59:05 浏览:13 分类:玩电脑

防止脚本注入攻击


与其他编程语言一样,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."

有关详细信息,请参阅EscapeSingleQuotedStringContent()。

使用 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.

有关详细信息,请参阅 PSScriptAnalyzer。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯