Redacting Sensitive Information with PowerShell

Mon, Aug 12, 2013 2-minute read

You might sometimes run into a situation where you’ve got a serialized object stream, and want to redact sensitive information out of that stream. For example, consider the following object:

$objectToSerialize = [PSCustomObject] @{
    Name = "Lee"
    SocialSecurityNumber = "SomeSecretNumber"
    Address = "1234 Something Road"
    GateCode = [PSCustomObject] @{
        Prefix = 1234
        Password = "SomeSecretPassword"
    }
}

In this, you want to remove any property value that says “SomeSecret”.

PowerShell makes this fairly easy, since the PSObject special property on every type gives you access to an object’s methods and properties. For each property value, you can check if it contains sensitive information - and if so, redact it.

Some properties are not simple properties, though. They might be objects with multiple writable properties themselves. In that case, you need to go down the worm hole even further.

Here’s a script that demonstrates one approach: Remove-PrivateInformation.ps1

param($objectToSerialize)
function CleanObject
{
    param($objectToClean)

    foreach($property in $objectToClean.PSObject.Properties)
    {
        ## See if there are any settable properties of this property
        $settableProperties = $property.Value.PSObject.Properties |
            ? { $_.IsSettable }
        if(@($settableProperties).Count -gt 0)
        {
            CleanObject $property.Value
        }

        ## Otherwise, we can clean it
        if($property.IsSettable -and 
            ($property.Value -match "SomeSecret"))
        {
            $property.Value = "Redacted!"
        }
    }
}

## Assuming you can't change $objectToSerialize directly. Otherwise,
## apply CleanObject to the object directly.
$serialized = [System.Management.Automation.PSSerializer]::Serialize(
    $objectToSerialize)
$objectToClean = [System.Management.Automation.PSSerializer]::Deserialize(
    $serialized)

CleanObject $objectToClean

$objectToClean

And the result:

11 [C:\windows\system32]
>> $objectToSerialize = [PSCustomObject] @{
>>         Name = "Lee"
>>         SocialSecurityNumber = "SomeSecretNumber"
>>         Address = "1234 Something Road"
>>         GateCode = [PSCustomObject] @{
>>             Prefix = 1234
>>             Password = "SomeSecretPassword"
>>         }
>>     }
>>

12 [C:\windows\system32]
>> Remove-PrivateInformation.ps1 $objectToSerialize | Format-List

Name                 : Lee
SocialSecurityNumber : Redacted!
Address              : 1234 Something Road
GateCode             : @{Prefix=1234; Password=Redacted!}

13 [C:\windows\system32]