1

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?

iRon
  • 20,463
  • 10
  • 53
  • 79
  • Where is `$Property` defined? – Mathias R. Jessen Aug 22 '23 at 12:49
  • @MathiasR.Jessen, IMO that doesn't matter: `Invoke-ScriptAnalyzer -CustomRulePath $InjectionHunterPath -ScriptDefinition '$Property = 5; $Object.$Property'` – iRon Aug 22 '23 at 12:51
  • 1
    Of course it matters :) If `$Object` and `$Property` are both user-controlled or tainted then the warning is pretty spot on – Mathias R. Jessen Aug 22 '23 at 12:52
  • @MathiasR.Jessen, Agree (I meant, it doesn't matter for the warning), so what you are suggesting is that it is actually a false positief for something as: `$Property = 5; $Object.$Property }` (updated the question) – iRon Aug 22 '23 at 13:23

1 Answers1

2

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

  • an expression (e.g. .$Property, .('Prop' + $index), .$(++$i; 'Prop' + $i))
  • or an expandable string (e.g, ."$Property", but not verbatim strings such as .'$Property')

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • fyi: I have sent a message via the [Contact Owner](https://www.powershellgallery.com/packages/InjectionHunter/1.0.0/ContactOwners) link and will keep you posted if anything changes. See also: [`#2` False positives for InjectionRisk.StaticPropertyInjection](https://github.com/matt2005/InjectionHunter/issues/2) – iRon Aug 23 '23 at 08:00
  • Thanks, @iRon. I understand that you probably want to use `$Object.psobject.Properties[$Property].Value` as a way to avoid a warning, but the fact that this isn't treated the same as `$Object.$Property` is a loophole in the analysis. – mklement0 Aug 23 '23 at 12:55