powershellcode-injection

Safe dynamic member access


In our environment we detecting vulnerable code with Injection Hunter. See also: Security Auditing for PowerShell Scripts

Use case

In this specific case it concerns a PvsServerBiosBootstrap object, that looks like:

$BootStrap = [ordered]@{Bootserver1_Ip='1.2.3.4';Bootserver1_Netmask='0.0.0.0';Bootserver1_Gateway='0.0.0.0';Bootserver1_Port='1234';Bootserver2_Ip='1.2.3.4';Bootserver2_Netmask='0.0.0.0';Bootserver2_Gateway='0.0.0.0';Bootserver2_Port='1234';Bootserver3_Ip='1.2.3.4';Bootserver3_Netmask='0.0.0.0';Bootserver3_Gateway='0.0.0.0';Bootserver3_Port='1234';Bootserver4_Ip='1.2.3.4';Bootserver4_Netmask='0.0.0.0';Bootserver4_Gateway='0.0.0.0';Bootserver4_Port='1234';VerboseMode='True';InterruptSafeMode='True';PaeMode='True';BootFromHdOnFail='False';RecoveryTime='50';PollingTimeout='5000';GeneralTimeout='30000';ServerId='12345678-1234-1234-1234-1234567890ab';Guid='12345678-1234-1234-1234-1234567890ab';Name='ARDBP32.BIN'}

Where it is evident to iterate trough the Bootserver* properties like: $BootStrap."Bootserver$($Counter)_Ip". This PvsServerBiosBootstrap object might be quiet seldom but commonly, objects are often flattened. (even I think that this should be generally avoided,)

False positive?

For some reason the Injection Hunter detects a risk on a simplified syntax like $Object.$Property = 'Something' and $Object.$Property for a $Property and $Object like: $Property = 5; $Object = [PSCustomObject]@{ Property = 'Something' }

Invoke-ScriptAnalyzer -CustomRulePath $InjectionHunterPath -ScriptDefinition {
    $Object = [PSCustomObject]@{ Property = 'Something' }
    $Property = 'Property'
    $Object.$Property = 'SomethingElse'
}.ToString()

RuleName                            Severity     ScriptName Line  Message
--------                            --------     ---------- ----  -------
InjectionRisk.StaticPropertyInjecti Warning                 4     Possible property access injection via dynamic member
on                                                                access. Untrusted input can cause arbitrary static
                                                                  properties to be accessed: $Object.$Property

But I fail to see how one might exploit this if the $Property is defined in the same script (or even the same scope). Can this than be considered as a false positive?
Besides, I wonder what the cleanest syntax would be to prevent the warning (apart from just suppressing the warning). I have tried things along with $Object.[String]$Property but the best substitute I have been able to find so far is which is rather cumbersome:

$Object.PSObject.Properties.where{$_.Name -eq 'Property'}[0].Value = 'SomethingElse'

In other words, how do I safely modify a dynamic object member?


Solution

  • The rule apparently categorically flags uses of ., the member-access operator that either use:

    Can this than be considered as a false positive?

    With a static, verbatim value such as 'Property' assigned to $Property in the same scope, arguably, yes - but that is a very specific scenario.


    A less cumbersome workaround is to use index notation via the intrinsic psobject property:

    $Object.psobject.Properties[$Property].Value = 'SomethingElse'
    

    That said, the fact that this is not flagged - irrespective of what value is assigned to $Property - is arguably a problematic oversight on the part of the vulnerability analysis, as malicious code can use this technique precisely to bypass the warning.


    I encourage you to provide feedback to the module maintainers.
    Unfortunately, the InjectionHunter module's PowerShell Gallery page provides no link to a GitHub repo, so the only obvious way to contact them is via the Contact Owners link.