Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
PowerShell-Skripts wie andere Programmiersprachen können anfällig für Einfügungsangriffe sein. Ein Einfügungsangriff tritt auf, wenn ein Benutzer Eingaben für eine anfällige Funktion bereitstellt, die zusätzliche Befehle enthält. Die anfällige Funktion führt die zusätzlichen Befehle aus, bei denen es sich um eine schwerwiegende Sicherheitslücke handeln kann. Beispielsweise könnte ein böswilliger Benutzer die anfällige Funktion missbrauchen, um beliebigen Code auf einem Remote-Computer auszuführen, wodurch dieser Computer möglicherweise kompromittiert wird und Zugriff auf andere Computer im Netzwerk erlangt.
Sobald Sie das Problem kennen, gibt es mehrere Möglichkeiten zum Schutz vor Injektionsangriffen.
Beispiel für anfälligen Code
Sicherheitsanfälligkeiten bei der PowerShell-Codeeinfügung umfassen Benutzereingaben, die Skriptcode enthalten. Die Benutzereingabe wird zu anfälligen Skripts hinzugefügt, in denen sie analysiert und von PowerShell ausgeführt wird.
function Get-ProcessById
{
param ($ProcId)
Invoke-Expression -Command "Get-Process -Id $ProcId"
}
Die Get-ProcessById
Funktion sucht einen lokalen Prozess anhand des ID-Werts. Es verwendet ein $ProcId
Parameterargument eines beliebigen Typs. Anschließend wird $ProcId
in eine Zeichenfolge konvertiert und in ein anderes Skript eingefügt, das mithilfe des Invoke-Expression
-Cmdlets analysiert und ausgeführt wird. Diese Funktion funktioniert einwandfrei, wenn eine gültige Prozess-ID-Ganzzahl übergeben wird.
Get-ProcessById $PID
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
97 50.09 132.72 1.20 12528 3 pwsh
Der $ProcId
Parameter gibt jedoch keinen Typ an. Er akzeptiert beliebige Zeichenfolgenwerte, die andere Befehle enthalten können.
Get-ProcessById "$PID; Write-Host 'pwnd!'"
In diesem Beispiel hat die Funktion den von $PID
der Funktion identifizierten Prozess richtig abgerufen, aber auch das eingefügte Skript Write-Host 'pwnd!'
ausgeführt.
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
92 45.66 122.52 1.06 21736 3 pwsh
pwnd!
Möglichkeiten zum Schutz vor Injektionsangriffen
Dies sind mehrere Möglichkeiten, um vor einem Injektionsangriff zu schützen.
Getippten Input verwenden
Sie können einen Typ für das $ProcId
Argument angeben.
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."
Hier ist der $ProcId
Eingabeparameter auf einen ganzzahligen Typ beschränkt, daher tritt ein Fehler auf, wenn eine Zeichenfolge übergeben wird, die nicht in eine ganze Zahl konvertiert werden kann.
Verwenden Sie nicht Invoke-Expression
.
Statt Invoke-Expression
zu verwenden, rufen Sie direkt Get-Process
auf und lassen Sie den Parameterbinder von PowerShell die Eingabe überprüfen.
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."
Als bewährte Methode sollten Sie die Verwendung Invoke-Expression
vermeiden, insbesondere bei der Behandlung von Benutzereingaben.
Invoke-Expression
ist gefährlich, weil es den von Ihnen bereitgestellten Zeichenfolgeninhalt analysiert und ausführt, wodurch es anfällig für Injectionangriffe ist. Es ist besser, sich auf die PowerShell-Parameterbindung zu verlassen.
Zeichenfolgen in einfachen Anführungszeichen umschließen
Es gibt jedoch Zeiten, in denen die Verwendung von Invoke-Expression
unvermeidbar ist und Sie auch Benutzereingaben von Zeichenfolgen behandeln müssen. Sie können Benutzereingaben sicher verarbeiten, indem Sie jede Zeichenfolgenvariable in einfache Anführungszeichen setzen. Das einfache Anführungszeichen sorgt dafür, dass der PowerShell-Parser die Benutzereingabe als einen einzigen string wörtlich behandelt.
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."
Diese Version der Funktion ist jedoch noch nicht vollständig vor Injektionsangriffen sicher. Ein böswilliger Benutzer kann weiterhin einzelne Anführungszeichen in seiner Eingabe verwenden, um Code einzugeben.
Get-ProcessById "$PID'; Write-Host 'pwnd!';'"
In diesem Beispiel werden einzelne Anführungszeichen in der Benutzereingabe verwendet, um zu erzwingen, dass die Funktion drei separate Anweisungen ausführt, von denen ein beliebiger Code vom Benutzer eingefügt wird.
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
97 46.08 183.10 1.08 2524 3 pwsh
pwnd!
Verwenden der EscapeSingleQuotedStringContent()
Methode
Zum Schutz davor, dass Benutzer einfache Anführungszeichen einfügen, um die Funktion auszunutzen, müssen Sie die EscapeSingleQuotedStringContent()
API verwenden. Dies ist eine statische öffentliche Methode der PowerShell System.Management.Automation.Language.CodeGeneration-Klasse . Mit dieser Methode wird die Benutzereingabe sicher, indem einzelne Anführungszeichen in der Benutzereingabe entfernt werden.
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."
Weitere Informationen finden Sie unter EscapeSingleQuotedStringContent().
Erkennen anfälligen Codes mit Injection Hunter
Injection Hunter ist ein Modul von Lee Holmes, das Regeln des PowerShell Script Analyzers zum Erkennen von Schwachstellen bei Code-Injektionen enthält. Verwenden Sie einen der folgenden Befehle, um das Modul aus dem PowerShell-Katalog zu installieren:
# Use PowerShellGet v2.x
Install-Module InjectionHunter
# Use PowerShellGet v3.x
Install-PSResource InjectionHunter
Sie können dies verwenden, um die Sicherheitsanalyse bei Builds, kontinuierlichen Integrationsprozessen, Bereitstellungen und anderen Szenarien zu automatisieren.
$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.
Weitere Informationen finden Sie unter PSScriptAnalyzer.