Aracılığıyla paylaş


Betik ekleme saldırılarını önleme

Diğer programlama dilleri gibi PowerShell betikleri de ekleme saldırılarına karşı savunmasız olabilir. Ekleme saldırısı, kullanıcı ek komutlar içeren savunmasız bir işleve giriş sağladığında gerçekleşir. Güvenlik açığı olan işlev, ciddi bir güvenlik açığı olabilecek ek komutları çalıştırır. Örneğin, kötü amaçlı bir kullanıcı, güvenlik açığı olan işlevi kötüye kullanarak uzak bir bilgisayarda rastgele kod çalıştırabilir ve büyük olasılıkla bu bilgisayarın güvenliğini tehlikeye atabilir ve ağdaki diğer makinelere erişim elde edebilir.

Sorunu fark ettikten sonra, ekleme saldırılarına karşı korumanın çeşitli yolları vardır.

Güvenlik açığı olan kod örneği

PowerShell kodu ekleme güvenlik açıkları, betik kodu içeren kullanıcı girişini içerir. Kullanıcı girişi, PowerShell tarafından ayrıştırılıp çalıştırıldığı güvenlik açığı olan betiklere eklenir.

function Get-ProcessById
{
    param ($ProcId)

    Invoke-Expression -Command "Get-Process -Id $ProcId"
}

İşlev, Get-ProcessById yerel bir işlemi kimlik değerine göre arar. Herhangi bir türde parametre $ProcId bağımsız değişkenini alır. $ProcId daha sonra bir dizeye dönüştürülür ve cmdlet'i kullanılarak ayrıştırılan ve çalıştırılan başka bir betike Invoke-Expression eklenir. Geçerli bir işlem kimliği tamsayısı geçirildiğinde bu işlev düzgün çalışır.

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 Ancak parametresi bir tür belirtmez. Diğer komutları içerebilen herhangi bir rastgele dize değerini kabul eder.

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

Bu örnekte, işlevi tarafından $pidtanımlanan işlemi doğru bir şekilde alır, ancak eklenen betiği Write-Host 'pwnd!'de çalıştırır.

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

Ekleme saldırılarına karşı koruma yolları

bir enjeksiyon saldırısına karşı korumanın çeşitli yollarıdır.

Yazılan girişi kullanma

Bağımsız değişken için $ProcId bir tür belirtebilirsiniz.

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."

Burada, $ProcId giriş parametresi bir tamsayı türüyle sınırlıdır, bu nedenle bir dize geçirildiğinde bir tamsayıya dönüştürülemez bir hata oluşur.

Kullanmayın Invoke-Expression

kullanmak Invoke-Expressionyerine doğrudan öğesini çağırın Get-Processve PowerShell'in parametre bağlayıcısının girişi doğrulamasını sağlayın.

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."

En iyi yöntem olarak, özellikle kullanıcı girişini işlerken kullanmaktan Invoke-Expressionkaçınmanız gerekir. Invoke-Expression sağladığınız dize içeriğini ayrıştırıp çalıştırarak ekleme saldırılarına karşı savunmasız hale getirmesi nedeniyle tehlikelidir. PowerShell parametre bağlamasına güvenmek daha iyidir.

Dizeleri tek tırnak içine alma

Ancak, kullanmanın Invoke-Expression kaçınılmaz olduğu ve kullanıcı dizesi girişini de işlemeniz gereken zamanlar vardır. Her dize giriş değişkeninin çevresinde tek tırnak işareti kullanarak kullanıcı girişini güvenli bir şekilde işleyebilirsiniz. Tek tırnak, PowerShell'in ayrıştırıcısının kullanıcı girişini tek bir dize değişmez değeri olarak ele almalarını sağlar.

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."

Ancak, işlevin bu sürümü henüz ekleme saldırılarına karşı tamamen güvenli değildir. Kötü amaçlı bir kullanıcı, kod eklemek için girişinde tek tırnak işareti kullanmaya devam edebilir.

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

Bu örnek, işlevi üç ayrı deyimi çalıştırmaya zorlamak için kullanıcı girişindeki tek tırnakları kullanır. Bunlardan biri, kullanıcı tarafından eklenen rastgele koddur.

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

EscapeSingleQuotedStringContent() yöntemini kullanma

Kullanıcının işlevden yararlanmak için kendi tek tırnak karakterlerini eklemesine karşı koruma sağlamak için API'yi EscapeSingleQuotedStringContent() kullanmanız gerekir. Bu, PowerShell System.Management.Automation.Language.CodeGeneration sınıfının statik bir genel yöntemidir. Bu yöntem, kullanıcı girişinde yer alan tek tırnaklardan kaçarak kullanıcı girişini güvenli hale getirir.

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."

Daha fazla bilgi için bkz . EscapeSingleQuotedStringContent().

Enjeksiyon Avcısı ile güvenlik açığı olan kodu algılama

Ekleme Avcısı , Lee Holmes tarafından yazılan ve kod ekleme güvenlik açıklarını algılamaya yönelik PowerShell Betik Çözümleyicisi kurallarını içeren bir modüldür. modülü PowerShell Galerisi yüklemek için aşağıdaki komutlardan birini kullanın:

# Use PowerShellGet v2.x
Install-Module InjectionHunter

# Use PowerShellGet v3.x
Install-PSResource InjectionHunter

Derlemeler, sürekli tümleştirme işlemleri, dağıtımlar ve diğer senaryolar sırasında güvenlik analizini otomatikleştirmek için bunu kullanabilirsiniz.

$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.

Daha fazla bilgi için bkz . PSScriptAnalyzer.