Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Skripty PowerShellu, jako jsou jiné programovací jazyky, můžou být ohrožené útoky prostřednictvím injektáže. Útok prostřednictvím injektáže nastane, když uživatel poskytne vstup do zranitelné funkce, která obsahuje další příkazy. Ohrožená funkce spouští další příkazy, což může být závažná ohrožení zabezpečení. Uživatel se zlými úmysly může například zneužít ohroženou funkci ke spuštění libovolného kódu na vzdáleném počítači, čímž by mohl ohrozit tento počítač a získat přístup k jiným počítačům v síti.
Jakmile o problému víte, existuje několik způsobů, jak chránit před injektážními útoky.
Příklad zranitelného kódu
Ohrožení zabezpečení injektáže kódu PowerShellu zahrnuje vstup uživatele, který obsahuje kód skriptu. Uživatelský vstup se přidá do zranitelného skriptu, kde PowerShell analyzuje a spouští ho.
function Get-ProcessById
{
param ($ProcId)
Invoke-Expression -Command "Get-Process -Id $ProcId"
}
Funkce Get-ProcessById vyhledá místní proces podle hodnoty ID. Přebírá argument parametru $ProcId libovolného typu. Potom $ProcId se převede na řetězec a vloží se do jiného skriptu.
Invoke-Expression rutina analyzuje a spustí zadaný řetězec. Tato funkce funguje správně, když se předá platné ID procesu.
Get-ProcessById $PID
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
97 50.09 132.72 1.20 12528 3 pwsh
Parametr $ProcId ale neurčí typ. Přijímá libovolnou řetězcovou hodnotu, která může obsahovat další příkazy.
Get-ProcessById "$PID; Write-Host 'pwnd!'"
V tomto příkladu funkce správně načetla proces identifikovaný $PID, ale také spustil vložený skript 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!
Způsoby ochrany před útoky prostřednictvím injektáže
Existuje několik způsobů, jak se chránit před útokem prostřednictvím injektáže.
Použijte psaný vstup
Můžete zadat typ argumentu $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."
Vstupní parametr $ProcId je zde omezen na celočíselný typ, takže při předání řetězce, který nelze převést na celé číslo, dojde k chybě.
Nepoužívat Invoke-Expression
Místo použití Invoke-Expression, přímo zavolejte Get-Process a nechte PowerShellův pořadač parametrů ověřit vstup.
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."
Osvědčeným postupem je vyhnout se použití Invoke-Expression, zejména při zpracování uživatelského vstupu.
Invoke-Expression je nebezpečná, protože analyzuje a spouští jakýkoli obsah řetězce textu, který poskytnete, takže je zranitelná vůči injekčním útokům. Lepší je spoléhat se na vazbu parametrů PowerShellu.
Zabalte řetězce do jednoduchých uvozovek
Jsou však chvíle, kdy je použití Invoke-Expression nevyhnutelné a také potřebujete zvládnout vstup uživatelského řetězce. Uživatelský vstup můžete bezpečně zpracovat pomocí jednoduchých apostrofů kolem každé řetězcové proměnné. Jednoduchá uvozovka zajišťuje, že analyzátor v PowerShellu zachází s uživatelským vstupem jako s jedním řetězcovým literálem.
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."
Tato verze funkce ale není odolná vůči injekčním útokům. Uživatel se zlými úmysly může ve svém vstupu použít jednoduché uvozovky k vložení kódu.
Get-ProcessById "$PID'; Write-Host 'pwnd!';'"
Tento příklad používá jednoduché uvozovky ve vstupu uživatele, aby funkce spustila tři samostatné příkazy, z nichž jeden je libovolný kód vložený uživatelem.
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
97 46.08 183.10 1.08 2524 3 pwsh
pwnd!
Použijte metodu EscapeSingleQuotedStringContent()
Aby se zabránilo možnosti, že uživatel vloží vlastní apostrofy a tím zneužije funkci, musíte použít rozhraní EscapeSingleQuotedStringContent() API.
EscapeSingleQuotedStringContent() je veřejná statická metoda třídy PowerShell System.Management.Automation.Language.CodeGeneration . Tato metoda zajistí bezpečnost vstupu poskytnutého uživatelem tak, že uvozuje všechny apostrofy obsažené ve vstupu uživatele.
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."
Další informace naleznete v tématu EscapeSingleQuotedStringContent().
Detekce zranitelného kódu pomocí nástroje Injection Hunter
Injection Hunter je modul napsaný Lee Holmesem, který obsahuje pravidla analyzátoru skriptů PowerShellu pro detekci ohrožení zabezpečení injektáže kódu. Pro instalaci modulu z Galerie PowerShell použijte jeden z následujících příkazů:
# Use PowerShellGet v2.x
Install-Module InjectionHunter
# Use PowerShellGet v3.x
Install-PSResource InjectionHunter
Tento modul můžete použít k automatizaci analýzy zabezpečení během sestavování, procesů kontinuální integrace, nasazení a dalších scénářů.
$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.
Další informace naleznete v tématu PSScriptAnalyzer.