Search code examples
javac#sshputtyplink

Securely pass password to PuTTY process on start


I am maintaining an application in our company (written in C#), which runs on a jumphost and provides the functionality to search across different servers and initiate a PuTTY connection to that server. For this the application currently starts the PuTTY process and passes arguments, like the hostname, username and password. The password for each server is retrieved from a password manager service. The arguments are passed to PuTTY through the command line interface. So the purpose of the application is to automate password retrieval and login to different servers.

The problem with the current approach is, that in the Windows Task Manager its possible for an administrator to see all started PuTTY instances and the corresponding credentials as command line arguments.

So far I haven't found any practical solution to circumvent this. These are the things I researched so far:

  • Instead of passing password argument, using SendKeys to type password into the promt: Unreliable, as there is no way to read the PuTTY output and know when the application is ready for the input to be typed in.
  • Using Plink instead of PuTTY and passing arguments through stdin: Plink supports stdin / stdout communication, however the terminal functionality is very limited and not usable in practice after the login was successful.
  • Modifying PuTTY to mask password: I have seen some suggestions, to modify the PuTTY source code, to overwrite the password in the main args, once the application started. However, this solution seems to only work on Linux, not Windows.
  • Using SSH.NET library to provide my own SSH terminal implementation: The SSH.NET library seems to be similarly to Plink more suitable for issuing commands programmatically, but not for opening a terminal for the user. I guess it would require a lot of work to implement a full terminal.

Some ideas, that might work:

  • Modify the PuTTY code, so that arguments can be passed through stdin: Could work, but I don't know how easy that would be, as I don't have very good C knowledge.
  • Use an alternate client, that supports stdin output. The Java library JSch looks quite powerful and seems to already include a terminal. Would it be possible to create a standalone application, that can a receive stdin and use that to open a terminal and auto login?

Any further suggestions would be greatly appreciated. Are you aware of any other Windows alternative to PuTTY, which supports passing credentials in a more secure way?


Solution

  • Following the suggestion of Martin Prikryl I was able to create a minimal example, which creates a NamedPipe in C# and passes it as a pwfile argument to PuTTY:

    public void CreatePipe()
    {
        var server = new NamedPipeServerStream("SecretPipe");
        server.WaitForConnection();
        StreamWriter writer = new StreamWriter(server);
        writer.Write("top!!secret");
        writer.Flush();
        server.Dispose();
    }
    

    Then PuTTY can be started as follows with the pipe as pwfile argument:

    putty.exe -l testuser -pwfile "\\.\PIPE\SecretPipe" hostname