0

In my Haskell application I implemented the following mechanism for passing sensitive information to the binary (without resorting to CLI parameters):

  • I use a TemplateHaskell mechanism for reading environment variables at compile time:
{-# LANGUAGE TemplateHaskell #-}
...
import Language.Haskell.TH.Env
...
myPrecious :: String
myPrecious = fromMaybe "" $$(envQ "MY_PRECIOUS")
...
  • When compiling, I pass the relevant environment variable like so: MY_PRECIOUS=<secret> stack build and it then gets bound to myPrecious on the Haskell side
  • The resulting binary has the value of MY_PRECIOUS compiled in, so it won't be visible from the operating system level (e.g. via ps aux)

Trouble is, I can now open that binary in a text editor or create a memory dump (e.g. with GDB) and with a little determination dig up the secret, especially if I know the context in which it is being used - I'm assuming that some malicious actor might have obtained access to the source code. So I've been wondering, is there any way to force GHC to produce a more obfuscated/garbled binary, in which such values would not be readily visible. I'm aware that no such protection scheme can be bulletproof, but I'm looking for a way to make the intruder's task harder.

Wojciech Gac
  • 1,538
  • 1
  • 16
  • 30
  • 5
    Security by obfuscation isn't security. – cafce25 Apr 17 '23 at 14:19
  • @cafce25 Care to elaborate in the context of the problem above? – Wojciech Gac Apr 17 '23 at 14:24
  • 3
    This is the wrong approach. If you explain what kind of secrets you're concerned about, we can tell you the right approach. – Joseph Sible-Reinstate Monica Apr 17 '23 at 14:33
  • OK, suppose I want to send notifications to a particular Telegram chat, from a particular bot. I consider both these pieces of info sensitive. How would you go about making this more secure? – Wojciech Gac Apr 17 '23 at 15:01
  • 2
    The program must be able to read the plaintext value, which means that anyone with full access to the context of the running process would, in theory, be able to read it as well. The best you can do is not make it _easier_, which your scheme does. It is easier if the attacker can access the bits of the compiled program than if they must access the running program in a context where the secret is available (e.g., by only supplying an encrypted secret at runtime). I urge you not to invent your own mechanism; use industry standard secret management techniques. – Rein Henrichs Apr 17 '23 at 15:27

1 Answers1

5

Obfuscation is a total waste of time. You'll end up spending days trying to come up with something clever only for a rookie reverse engineer to defeat it in minutes. Instead, you should set up actual security rather than security through obscurity, with something like this:

  1. Create a new UNIX group with no users in it
  2. Put your secrets in a file only readable by root and that group
  3. Code your program to read secrets from that file at startup
  4. Make your binary setgid the group that can read the file

Now opening the binary in a text editor will yield nothing, since the secrets aren't in it at all, and taking a memory dump is impossible since the kernel doesn't let you do that to a setgid process.

  • Thanks! I really like your scheme. Though it still fails in the face of compromising the root account, it adds a substantial layer of difficulty on top. – Wojciech Gac Apr 17 '23 at 16:01
  • 3
    @WojciechGac Someone with root access to the machine running your program essentially has full access to everything; all files, all programs, all memory, etc. You don't defend against that vulnerability by trying to come up with a way to block root from accessing the secret; that's pretty much futile. You defend against that vulnerability by protecting root access in the first place. – Ben Apr 17 '23 at 16:24
  • 1
    @WojciechGac This also implies that if you're installing your software onto a machine that *someone else* controls (e.g. it's designed to be installed on a user's personal computer) rather than one *you* control (like a cloud server), then you don't include anything that **has** to be secret in the software. You cannot guarantee they don't have root access to their own machine. Schemes like the above are for protecting against other users or third-party software (including malicious software). They don't protect the secret from the machine's owner. – Ben Apr 18 '23 at 01:21