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

ConvertFrom-SecureString is broken on Linux #1654

Closed
Krishna-Vutukuri opened this issue Aug 4, 2016 · 62 comments · Fixed by #9199
Closed

ConvertFrom-SecureString is broken on Linux #1654

Krishna-Vutukuri opened this issue Aug 4, 2016 · 62 comments · Fixed by #9199
Assignees
Labels
Issue-Bug Issue has been identified as a bug in the product OS-Linux OS-macOS Resolution-Fixed The issue is fixed. WG-Cmdlets general cmdlet issues
Milestone

Comments

@Krishna-Vutukuri
Copy link

Krishna-Vutukuri commented Aug 4, 2016

Steps to reproduce

  1. Install PowerShell on Ubuntu 14.04
  2. Launch PowerShell
  3. Run the following:
   $password = Convertto-Securestring -String "PowerShellRocks!" -AsPlainText -Force
   ConvertFrom-SecureString $password  

Expected behavior

No error

Actual behavior

The following error is thrown

PS /home/chythu/temp> ConvertFrom-SecureString $password                        ConvertFrom-SecureString : Unable to load DLL 'CRYPT32.dll': The specified
module could not be found.
 (Exception from HRESULT: 0x8007007E)
At line:1 char:1
- ConvertFrom-SecureString $password
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  - CategoryInfo          : NotSpecified: (:) [ConvertFrom-SecureString], Dl
    lNotFoundException
  - FullyQualifiedErrorId : System.DllNotFoundException,Microsoft.PowerShell
    .Commands.ConvertFromSecureStringCommand

Environment data

Name                           Value
---
PSVersion                      5.1.10032.0
PSEdition                      PowerShellCore
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   3.0.0.0
GitCommitId                    v6.0.0-alpha.7
CLRVersion
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Updates by @TravisEz13 on 2016-04-10

Environment data

> $PSVersionTable
Name                           Value                                           
----                           -----                                           
PSVersion                      6.0.2                                           
PSEdition                      Core                                            
GitCommitId                    v6.0.2                                          
OS                             Darwin 17.5.0 Darwin Kernel Version 17.5.0: M...
Platform                       Unix                                            
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                         
PSRemotingProtocolVersion      2.3                                             
SerializationVersion           1.1.0.1                                         
WSManStackVersion              3.0                                             

Workaround

The following works

# you should generate your own key
$Key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)       
$s  | ConvertFrom-SecureString -Key $Key                                      
@Krishna-Vutukuri Krishna-Vutukuri added the WG-Cmdlets general cmdlet issues label Aug 4, 2016
@Krishna-Vutukuri Krishna-Vutukuri added this to the 6.0.0-Alpha.10 milestone Aug 4, 2016
@oising
Copy link
Contributor

oising commented Aug 5, 2016

@hiteshraigandhi
Copy link
Contributor

Talked @KrishnaV-MSFT This is not needed for Azure demo. Moving it out of Alpha.10

@hiteshraigandhi hiteshraigandhi modified the milestones: Future, 6.0.0-Alpha.10 Aug 10, 2016
@jaredmichaelwilliams
Copy link

jaredmichaelwilliams commented Aug 18, 2016

Came across the same error on MacOS 10.12 Beta (16A270f)

Was just messing around got this:

PS> $User="Jared"
PS> $PWord = ConvertTo-SecureString –String "TestString" –AsPlainText -Force   
PS> $Cred = New-Object -TypeName "System.Management.Automation.PSCredential" –ArgumentList $User, $PWord
PS> ConvertFrom-SecureString -SecureString ($Cred.Password)

Result:

ConvertFrom-SecureString : Unable to load DLL 'CRYPT32.dll': The specified module could not be found.
 (Exception from HRESULT: 0x8007007E)
At line:1 char:1
+ ConvertFrom-SecureString -SecureString ($Cred.Password)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-SecureString], DllNotFoundException
    + FullyQualifiedErrorId : System.DllNotFoundException,Microsoft.PowerShell.Commands.ConvertFromSecureStringComman

@adityapatwardhan adityapatwardhan added Issue-Bug Issue has been identified as a bug in the product Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors labels Sep 20, 2016
@35359595
Copy link

35359595 commented Oct 2, 2016

Hi,

same library error when trying to use mapped cert: psdrive:

Get-ChildItem Cert:/LocalMachine/

Error:

get-childitem : Unable to load DLL 'crypt32.dll': The specified module could not be found.
(Exception from HRESULT: 0x8007007E)
At line:1 char:1

  • get-childitem Cert:/LocalMachine/
  • - CategoryInfo          : NotSpecified: (:) [Get-ChildItem], DllNotFoundException
    - FullyQualifiedErrorId : System.DllNotFoundException,Microsoft.PowerShell.Commands.GetChildItemCommand
    

@vors vors added the OS-macOS label Oct 2, 2016
@vors
Copy link
Collaborator

vors commented Oct 2, 2016

@35359595 good finding! The error definitely should be friendlier. On Linux and macOS Cert:/ provider needs some re-thinking. The way these two systems approach storing certificates are completely different from each other and windows.

@ChrisMagnuson
Copy link

Fyi, 16.04.1 with PowerShell v6 alpha 14 still has this same issue

@ngetchell
Copy link

This is holding me back from bringing my modules over to Linux. I'd like to be able to store Web API keys securely on all OSes, not just Windows.

@joeyaiello
Copy link
Contributor

This is something we'll only be able to enable with the .NET Standard 2.0 APIs that bring back SecureString:

@SteveL-MSFT SteveL-MSFT modified the milestones: 6.0.0-beta, post-6.0.0 Feb 27, 2017
@joeyaiello joeyaiello added Waiting - DotNetCore waiting on a fix/change in .NET and removed Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors labels Mar 20, 2017
@daxian-dbw
Copy link
Member

daxian-dbw commented Apr 13, 2017

ConvertFrom-SecureString and ConvertTo-SecureString depend on System.Security.Cryptography.ProtectedData, which is still not available in netstandard2.0.
So these 2 cmdlets need to be re-worked on Unix platforms.

@daxian-dbw daxian-dbw removed their assignment Apr 13, 2017
@SteveL-MSFT SteveL-MSFT modified the milestones: 6.0.0-beta2, 6.0.0-beta1 Apr 13, 2017
@joeyaiello joeyaiello removed the Waiting - DotNetCore waiting on a fix/change in .NET label Apr 14, 2017
@splatteredbits
Copy link

splatteredbits commented Jan 23, 2019

Until this gets fixed, here's code to securely pass a credential to a background job:


$credentialKey = New-Object 'byte[]' (256/8)
$rng = New-Object 'Security.Cryptography.RNGCryptoServiceProvider'
$rng.GetBytes($credentialKey)

$serializableCredential = [pscustomobject]@{ 
                                                UserName = $credential.UserName;
                                                Password = ConvertFrom-SecureString -SecureString $credential.Password -Key $credentialKey
                                            }

$job = Start-Job {
    param(
        [Parameter(Mandatory)]
        [byte[]]
        $Key
    )
    $serializedCredential = $using:serializableCredential

    $password = ConvertTo-SecureString -String $serializedCredential.Password -Key $Key
    $credential = New-Object 'PSCredential' ($serializedCredential.UserName,$password)
    [Array]::Clear($Key,0,$Key.Length)
} -ArgumentList (,$credentialKey) | Wait-Job | Receive-Job

[Array]::Clear($credentialKey,0,$credentialKey.Length)
   

@vchrizz
Copy link

vchrizz commented Feb 5, 2019

Password = ConvertFrom-SecureString -SecureString $credential.Password -Key $credentialKey

how is this supposed to work if this has an issue itself?

anyways, tried your script though but got error:

ConvertFrom-SecureString : Cannot bind argument to parameter 'SecureString' because it is null.
At /home/myusername/powershell.ps1:7 char:99
+ ... = ConvertFrom-SecureString -SecureString $credential.Password -Key $c ...
+                                              ~~~~~~~~~~~~~~~~~~~~

so i tried to define username and password in a variable but:

ConvertFrom-SecureString : Cannot bind parameter 'SecureString'. Cannot convert the "testpassword" value of type "System.String" to type "System.Security.SecureString".

autocloudarc pushed a commit to autocloudarc/0026-azure-automation-plus-dsc-lab that referenced this issue Mar 1, 2019
@KKomarov
Copy link

Why there is no separate issue for passing secure string over psremote? All opened issues closed as duplicates of this. In my opinion problem is different.
PSRemote hangs during key exchange due to lack of CryptoAPI implementation on Linux.
Who interested it hangs here

_keyExchangeCompleted.WaitOne();

Btw, we can add exception handler showing message that securestring not supported yet ^ it's quite hard to realise it related to securestrings if it hangs like that.
I think psremoting can be fixed without fixing ConvertFrom-SecureString commandlet, because we don't need to store keys on machine for later use. We need only generate rsa 2048 key pair, crypt/decrypt using rsa, crypt decrypt using AES CBC crossplatform.

Some good news there is crossplatform workaround.
Workaround for PSRemoting
Use python fresh implementation of PSRP pypsrp it supports securestrings!

@iSazonov
Copy link
Collaborator

@KKomarov Please open new issue with repo steps and your suggestion.

@SteveL-MSFT
Copy link
Member

@KKomarov the hang has been fixed in PSCore6.2-RC as part of #8723 already. The ability to actually send secure strings over for non-Windows should be a separate issue.

@iSazonov
Copy link
Collaborator

DE0001: SecureString shouldn't be used
https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md#de0001-securestring-shouldnt-be-used

@JustinGrote
Copy link
Contributor

JustinGrote commented Mar 19, 2019

@iSazonov

DE0001: SecureString shouldn't be used
https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md#de0001-securestring-shouldnt-be-used

While that's nice in a perfect ivory tower world, in Powershell we are constantly gluing things together and that requires authenticating in whatever format that application requires, be it rest API, legacy application that only supports Basic authenticaiton, etc. We can't just simply "use windows credentials or certificates" for everything as this recommendation states, that's a nice recommendation for developing a new app, but not what we use powershell for.

It's not like PSCredential is going anywhere which is an implementation of SecureString, so until we have something in .net core that can use a TPM to encrypt keys or something, we need a "good enough" option.

Something like using AES256 and having the encryption key be a 600 permission-ed file on the non-windows file system is a possible start, not much worse than using the Crypto API in Windows

@iSazonov
Copy link
Collaborator

I added the link for information only.

Essentially:

  1. It is impossible to port SecureString because System.Security.Cryptography.ProtectedData is Windows-only. There is no plans to port the API. Core team deprecate the API.
  2. We can keep backward compatibility for SecureString on Windows (including remoting)
  3. PowerShell Core must remain flexible and allow to work with legacy applications.
  4. It is acceptable to use basic authentication in protected environment
  5. Main problem how to detect protected environment vs public environment and what to do (prevent basic authentication, only warn, ...).

@SteveL-MSFT
Copy link
Member

Early on, the @PowerShell/powershell-committee discussed introducing a SensitiveString to replace the functional need of SecureString even though both are not secure (the SecureString type would still be needed for backwards compat). A type (whether "Sensitive" or "Secure" is needed to indicate to PowerShell to prompt without echoing the input so it's used more than just for remoting. As for the original issue of this bug, this has been fixed (you don't get an error anymore), just keep in mind the SecureString is internally in plain text.

Windows PowerShell compatibility (.NET Standard 2.0) automation moved this from Priority-High to Done Mar 20, 2019
@vchrizz
Copy link

vchrizz commented Mar 21, 2019

thanks for the update, looks promising!
may we ask for an approximately timeframe when to expect to be able to utilize this (e.g. in microsoft-debian-stretch-prod debian repository)?

@rmbolger
Copy link

rmbolger commented Mar 21, 2019

As for the original issue of this bug, this has been fixed (you don't get an error anymore), just keep in mind the SecureString is internally in plain text.

Does anyone have a link to the fix or know what release version it will be available in? I'm still getting crypt32.dll errors in powershell_6.1.3-1.ubuntu.16.04_amd64.deb (same deal with the 6.2.0-rc.1 preview package).

I'm also curious how this fix affects Import/Export-CliXml when the data to be serialized contains SecureString or PSCredential objects.

@iSazonov
Copy link
Collaborator

@rmbolger Could you please check with latest build (6.2.0-RC)?

@rkeithhill
Copy link
Collaborator

rkeithhill commented Mar 21, 2019

I'm seeing the same as @rmbolger

/home/hillr
03-20 23:44:55 31ms 11> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.2.0-rc.1
PSEdition                      Core
GitCommitId                    6.2.0-rc.1
OS                             Linux 4.4.0-17763-Microsoft #379-Microsoft Wed Mar 06 19:16:00 PST 2019
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

/home/hillr
03-21 00:47:45 35ms 12> ConvertFrom-SecureString -SecureString $ss
ConvertFrom-SecureString : Unable to load shared library 'CRYPT32.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libCRYPT32.dll: cannot open shared object file: No such file or directory
At line:1 char:1
+ ConvertFrom-SecureString -SecureString $ss
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [ConvertFrom-SecureString], DllNotFoundException
+ FullyQualifiedErrorId : System.DllNotFoundException,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand

@SteveL-MSFT SteveL-MSFT reopened this Mar 21, 2019
@iSazonov
Copy link
Collaborator

The cmdlets load directly the CRYPT32.dll

exportedString = SecureStringHelper.Protect(SecureString);

protectedData = ProtectedData.Protect(data, null,

if (!CAPI.CryptProtectData(new IntPtr(&dataIn),

internal static extern bool CryptProtectData(

@SteveL-MSFT SteveL-MSFT self-assigned this Mar 21, 2019
TravisEz13 added a commit that referenced this issue Mar 23, 2019
On Unix systems, fallback to plaintext manipulation instead of using the DPAPI which is not available.

## PR Context

Currently, existing scripts that use SecureString cmdlets fail with an error complaining about crypt32.dll not being available.  This change allows these cmdlets to be used, but there is no encryption of the string.
.Net already [states](https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netcore-2.1#remarks) that the contents of a SecureString are not encrypted on .Net Core.

Fix #1654

Co-authored-by: Travis Plunk <travis.plunk@microsoft.com>
@iSazonov iSazonov added the Resolution-Fixed The issue is fixed. label Mar 23, 2019
TravisEz13 added a commit that referenced this issue Mar 25, 2019
On Unix systems, fallback to plaintext manipulation instead of using the DPAPI which is not available.

## PR Context

Currently, existing scripts that use SecureString cmdlets fail with an error complaining about crypt32.dll not being available.  This change allows these cmdlets to be used, but there is no encryption of the string.
.Net already [states](https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netcore-2.1#remarks) that the contents of a SecureString are not encrypted on .Net Core.

Fix #1654

Co-authored-by: Travis Plunk <travis.plunk@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug Issue has been identified as a bug in the product OS-Linux OS-macOS Resolution-Fixed The issue is fixed. WG-Cmdlets general cmdlet issues
Development

Successfully merging a pull request may close this issue.