See this question/answer first: When calling a process from another process, Is sending stdin password more secure than sending an ENV variable?

I am a Java developer that is building an app where it needs to call a C# process from within. In my situation, the Java app is calling this C# program https://github.com/nddipiazza/SharepointOnlineCookieFetcher.

We have established that this is not secure to send the password via environment variables nor with stdin.

What is the best practice for providing the password to this app?

  • you should be able to trust your own server, or else nothing else matters. sockets are not a bad route for IPC in general. – dandavis Feb 23 '18 at 20:15
  • @dandavis Is there any way you could elaborate a bit and convert this to an answer? I'm sure others might find this useful! (including me!) – Nicholas DiPiazza Feb 23 '18 at 20:27
  • @NicholasDiPiazza It’s probably best to describe some sort of threat model. Who are you trying to protect your password against? It may be worth looking at how other applications accept passwords, for example su takes the user’s password through a tty rather than stdin, so maybe it would be worth investigating the rationale behind that decision. – Steve Feb 24 '18 at 2:07
  • Are you essentially asking how one process can authenticate the other process over some IPC? – forest Feb 24 '18 at 4:00
  • Yeah Java process has a username and password. It now needs to call a C# process that needs to use this username and password. What is the best practice here. Threat model - running on AWS ec2 instances typically but variety of uses. – Nicholas DiPiazza Feb 24 '18 at 4:05

From my understanding, this is your threat model: You have two programs, one will execute the other. The first program must pass some secret to the second program. An adversary must not be able to record, intercept, or modify this secret. Both processes trust each other and run on the same system.

The answer depends on whether or not the executable is writable by an adversary. If it is kept in a privileged system path or has at least the same level of integrity as the parent executable, you can be sure that you can trust it not to have been tampered with. When both processes are trusted, the simplest way of sending data between two processes is a pipe, such as stdin. It would also be possible to use shared memory, which is a region of memory a parent process can create that will be shared by its child, allowing for more efficient communication than over a pipe. Unauthorized parties will not be able to intercept or modify the contents of the communication, unless they are able to:

  • Modify either the parent or child executables directly.
  • Trick your program into running the wrong executable, e.g. by abusing PATH.
  • Run as the same user as your program, making it possible to compromise them.
  • Modify the environment (e.g. LD_PRELOAD) of either the parent or the child.

I would suggest not using an environmental variable. The environment is not meant to be secret and often other users are able to view the environment of various processes on the system. On Linux for example, the environment of any process can be obtained by reading the /proc/<pid>/environ file.

  • Other ways an attacker could compromise this: debug either program, read the address space (memory) of either program, open the IPC channel (such as a shared memory section) and read it out of there, read it out of physical memory... The first two require having (at least) the same privileges as the user running the apps, but not necessarily having admin/root privileges. The third depends on the channel used but may also be vulnerable to same-user attacks. Physical memory access requires either kernel-mode code or physical access to the box. – CBHacking Feb 25 '18 at 8:55
  • Indeed. Those fall under "Run as the same user as your program". – forest Feb 26 '18 at 1:52

While forest's answer is globally correct, he didn't mention an important way you can improve the level of protection between your instances.

Under windows, you can use CryptProtectMemory (and CryptProtectData) to encrypt our data with a key that is linked to the current user (and, in case of CryptProtectMemory, the key is changed every time your machine is rebooted).

This allows your to add a layer of protection into your system: you can use CryptProtectMemory (specifying the CRYPTPROTECTMEMORY_SAME_LOGON flag) to restrict access to decryption key to process running on the same machine and the same user as your own.

It will not protect your from code running in the same context as yours but, ultimately, there is nothing that will protect you against that.

Edit: I want to emphasis the fact that you should use CryptProtectMemory, not CryptProtectData. CryptProtectData is intended for data that is to be streamed to storage (and therefore will need to be retrieved and decrypted from another windows session alltogether).

  • Given that the method of communication between the processes is already confidential (i.e. only processes of the same user can access them), what benefit would this give you? Note that I know little about Windows itself so I know nothing about the specific implementation of these functions. – forest Feb 27 '18 at 8:42
  • It provides some protection against someone parsing a memory dump: unless the attacker still has access to the same running session, the content of the memory cannot be decrypted. – Stephane Feb 27 '18 at 8:45
  • That doesn't seem like it fits the OP's threat model. Also, the keys naturally have to be stored in memory as well, so a full memory dump will still allow decryption. Or does Windows create dumps of process memory like *nix coredumps and allow them to be readable by the same user? – forest Feb 27 '18 at 8:47
  • (Quick note: The OP's threat model isn't specified) The natural key is derived from the station state and the user's password. You'll have to dump the full machine's memory (including the kernel's) to be able to retrieve the key. Plus, I believe it will use the TPM chip if it's available. – Stephane Feb 27 '18 at 8:50
  • Under what circumstances would that protect the secret? Only processes of the same user can read that process' memory, and those processes could just disable the encryption if they should wish. Other processes cannot access the memory anyway. Physical access allows a full memory dump so it can't protect against that. Is there a situation where this would protect from another user trying to read the memory, somehow, like world-readable memory dumps (if Windows does that)? – forest Feb 27 '18 at 8:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.