Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add [HiddenString] Class #16921

Open
iRon7 opened this issue Feb 25, 2022 · 6 comments
Open

Add [HiddenString] Class #16921

iRon7 opened this issue Feb 25, 2022 · 6 comments
Labels
Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group.

Comments

@iRon7
Copy link

iRon7 commented Feb 25, 2022

As a scripter I want to be able to handle sensitive information as confidential and easy as possible.

As defined by Microsoft: SecureString shouldn't be used (for what?):

The general approach of dealing with credentials is to avoid them and instead rely on other means to authenticate, such as certificates or Windows authentication.

The dilemma is in its name which prentents that it is a secure string which is apparently not (completely) the case and therefore ends up which solutions that are not possible (as above "shouldn't be used" statement) rather than what is possible (and doable). A HiddenString implies that it is hidden and therefore also could be revealed. Meaning that there is also no argument against being able to construct it, or in other words: hide an existing plain text string.

This is also discussed in: #12188 Automatically convert SecureString to String in parameter binder but this request differs in the fact that I am not looking for a Secure String but a clearer way to simply hide information and prevent it from accidentally being written to the console or logs.

If a SecureString should not be used, what can I do as a PowerShell scripter? I can't just change the world, meaning that I can't easially change the applications that require (or provide) sensitive information in plain text format, but as a scripter, I can take care sensitive information is handled as secure as possible by hiding it as much as possible from start to the end of the script.

Even security through obscurity is rejected as secure, in certain situations, it better to hide the key under the doormat (or somewhere else) than just leaving the door open...

Taken StackOverflow case Powershell task: Hide not the output but the actual command containing sensitive info in devops logs as an example:
I have tried to address this issue (see also: #16502 Set-ScheduledTask shouldn't accept a plain text Password) to Microsoft for month now, but my (potential security) issue is completely ignored.
And that is Microsoft, what about all the other (legacy) applications in organizations. I am trying hard, bit I can't just dictate them to change this to certificates or Windows authentication as often it is not that feasible and therefore easer said then done.

As apposed to a SecureString, it would be nice to have a HiddenString class similar to this proto type:

I have removed the prototype and further worked out the HiddenString class idea here

With will give me the possibility to hide sensitive information at the entrance (usually a parameter) of a script and easily reveal at last moment it needs to be passed on to another application.

Example:

function MyScript([String]$TaskName, [String]$UserName, [HiddenString]$Password) {

    Start-Transcript -Path .\Transcript.txt
    
    Write-Host "Scheduling $TaskName for $UserName/$Password" # Write-Log ...
    Set-ScheduledTask -TaskName $TaskName -User $UserName -Password $Password.Reveal()

    Stop-Transcript
}

Recommended invocation of MyScript:

$SecuredString = Read-Host 'Enter Password' -AsSecuredString
MyScript NotePad.Exe JohnDoe $SecuredString

Just hiding the sensitive information inside the MyScript:

$String = 'Sensitive Information'
MyScript NotePad.Exe JohnDoe $String

Transcript started, output file is .\Transcript.txt
Scheduling NotePad.Exe for JohnDoe/HiddenString
Transcript stopped, output file is .\Transcript.txt

For passwords (as in this example), keys, secrets, tokens, etc., (qoute:)

A SecureString object should never be constructed from a String, because the sensitive data is already subject to the memory persistence consequences of the immutable String class. The best way to construct a SecureString object is from a character-at-a-time unmanaged source, such as the Console.ReadKey method

but often there is no other option, therefore it is better to at least hide them deeply.
Besides, this request is not about securing items but hiding sensitive information which might include items that are considered private like FQDNs, SIDs IP Addresses or even usernames.

@iRon7 iRon7 added Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group. labels Feb 25, 2022
@iSazonov
Copy link
Collaborator

Please look .Net proposal dotnet/designs#147

@vexx32
Copy link
Collaborator

vexx32 commented Feb 25, 2022

If all you want is to hide the data from logs etc, SecureString is likely fine for that usage in many ways. As I understand it, the guidance against using it is from a security standpoint in that it's not memory-safe, actors with access to the machine's memory can exfiltrate the password quite easily. If the goal is simply to hide it from logs and make it a bit more obscure, SecureString is fine as-is.

@iRon7
Copy link
Author

iRon7 commented Feb 25, 2022

@Vexx33

If the goal is simply to hide it from logs and make it a bit more obscure, SecureString is fine as-is.

Thanks, that means we agree on that.
The point that I am trying to make is that (quote) "the general purpose of SecureString is to avoid having secrets stored in the process memory as plain text" which means it will never get an easy and standard constuctor as (quote) "a SecureString object should never be constructed from a String" and/or get a standard method to reveal the embedded string.
The purpose of this issue enhancement is to create a standardized HiddenString class which differs from the general purpose of a SecureString and therefore might better serve a scripter with hiding sensitive informatiion.

@iRon7
Copy link
Author

iRon7 commented Feb 25, 2022

@iSazonov,

Please look .Net proposal dotnet/designs#147

Thanks for linking this, (I need to read this all a few times) but having a quick look at it, I get the impression its about a more (ultimate) secured solution (which is also good to have) where I am aiming for just easily hiding information in a script (this means that there is also a different need for PowerShell scripting than all other programming languages that depend on .Net. This shows from the resistance of the PowerShell community to completely deplete the SecureString class). From a scripting perspective: what good will it do to use all kind of security measurements (with tokens etc.) as in the end I have to send a plain text password to Set-ScheduledTask or any other application???

@iSazonov
Copy link
Collaborator

@iRon7 I tried to express my concerns in that discussion. Obviously this is a big problem for them (.Net team). Technically they already have a solution. I can assume that they are now trying to come to a consensus throughout MSFT since this will be a sensitive change (for PowerShell as well).
I hope that their solution will work for PowerShell as well.

@iRon7
Copy link
Author

iRon7 commented Apr 8, 2022

I have removed the prototype and further worked out the HiddenString class idea here

Another thing to mention is that both SecureString class and HiddenString class concepts have ways to encrypt and decrypt the embedded string (which -against all assumptions- shouldn't be used). For a scripter, the SecureString string conversions are quiet cumbersome but that doesn't change the fact that they are simply available and used anyways (as they are often required by the entity that uses the script) where the HiddenString approach has easy string conversions but pushing the responsibly of the usage of the (insecure) string conversion to the entity that actually supplies or requires the plain text strings (the user of the script) by returning automated warnings:

function Logon ([String]$Username, [HiddenString]$HiddenPassword) {
    Use-Credential $Username $HiddenPassword.Reveal() # 3rd party requirement
}
$HiddenPassword = [HiddenString]'P@ssW0rd'
WARNING: For better obscurity, use a hidden or secure string for input.
Logon 'MyName' 'P@ssW0rd'
WARNING: For better obscurity, use a secure string output.

Correct usage (prevent warnings):

function Logon ([String]$Username, [HiddenString]$HiddenPassword) {
    $Credential = New-Object System.Management.Automation.PSCredential ('UserName', $HiddenPassword)
}
$HiddenPassword = [HiddenString](Read-Host -Prompt 'Enter your password' -AsSecureString)
Logon 'MyName' $HiddenPassword

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group.
Projects
None yet
Development

No branches or pull requests

3 participants