2

I have this problem:

  • My console app needs to connect to a server. However, the server requires passwords in plain text per HTTP POST for login. The connection is HTTPS.
  • The app is only called now and then, but does not run permanently.

Now, I don't want the user to enter his or her password for every run of the app. My idea was:

  • When the user starts the app for the first time, the user is being asked for a password. A new deamon is being started (i.e. a program executed by the user, which can run for mulitple weeks), and the entered password is passed directly to the deamon.
  • To login to the homepage, the app only tells the demon "login". The demon, which has the password in RAM, calls wget to login to the website [1].

My main worry is that the deamon has the password in RAM. What dangers could arrise from this?

I see three risks:

  • Someone could access the RAM. Probably by forcing your computer to swap it out, then pressing the power button, and then investigating you hard disk. It's possible, but probably not effective.
  • The deamon could use temporary files to store it's memory. Probably true for bash? However, if I'll write a C program, this should not be possible?
  • Someone could use a script which says "Hi deamon, I'm wget/the internet, give me the password". As long as I'll call "/usr/bin/wget", and as long as the user isn't root, I think that won't be possible?

Any other issues?

Notes: [1] wget gets the password via a file, so the password is not in the ps-table. The file would be constructed by the demon with read-rights only for the user, and would be deleted after the login.

Johannes
  • 165
  • 3
  • 3
    #1, instead of using wget, I think you should have the daemon call the website over HTTPS directly. #2, Instead of storing the password, store a session token. The session token keeps you logged in, but can be revoked at any time by the server. See http://security.stackexchange.com/a/92123/95555 – Nateowami Dec 20 '16 at 14:20
  • @Nateowami Agreed. Calling `wget` directly almost certainly means putting the password in the command line invocation, which is orders of magnitude worse than merely storing it in RAM. – Stephen Touset Dec 20 '16 at 18:54

1 Answers1

3

Any other issues?

Yes, you are overcomplicating it.

I'd suggest you should just setup a ramfs or a LUKS mount and set permission so that only your application have read access to that directory. The application should be setuid to the special user, or you should have a sudoers rule that allows running sudo -u specialuser secureapp.

Security is the same or better than what you're proposing, and it would be much simpler to implement.

As to your concern that someone can dump the RAM, if your attacker have the privilege to dump RAM, you're already screwed. Leaking the password is the least of your worries.

If you can't leak the password anyway even if the attacker can dump RAM, then you should not be using passwords for login. Instead, I'd suggest alternative form of authentication like access token, or PKI with client certificate, possibly in a hardware security module (e.g. x.509 or OpenPGP smartcard).

If you want to write a daemon anyway, and you have an area in the RAM that contains sensitive data, you should use the mmap(MAP_LOCKED)/mlock() to allocate unpageable memory or to prevent a part of the memory from being paged out.

To your third concern, rather than the daemon listening on HTTP via TCP (AF_INET), I'd suggest the daemon should listen on Unix domain socket (AF_LOCAL). With Unix socket, you can apply file permission to restrict who can communicate with the socket, this gives you much finer access control than TCP. Examples: ssh-agent and gpg-agent are implemented using Unix sockets.

Lie Ryan
  • 31,089
  • 6
  • 68
  • 93
  • 1
    Suid/sudoers aren't as simple. There are many cases of privilege escalation like malicious $PATH attacks. Maybe sudo is a bit better, but still, I would not consider it as clear win over the daemon approach. Even though not needing any background process sounds tempting. – v6ak Dec 20 '16 at 17:26
  • Mlock is IMHO tricky. It does some best-effort job, but, for example, if you send/receive the data, you will probably leak them to a memory that is not mlock-ed. I suggest having an encrypted swap, maybe encrypted by a random key. – v6ak Dec 20 '16 at 17:28
  • 1
    @v6ak: Can you please give an example of what you mean by malicious $PATH attacks? – Johannes Dec 20 '16 at 17:53
  • @Lie Ryan, many thanks so far. Since I can't access the server (and can't talk to the people owning it), I guess access tokens are not feasible? Other than that, the setuid solutions sounds nice, though v6ak had security concerns... – Johannes Dec 20 '16 at 17:55
  • @Johannes if you call some command using system(…), it might search the executable in $PATH. Since attacker can provide her own $PATH, she can force such suid executable to run her executable. (Note that this is probably not exhaustive. I remember it is a minefield, but I don't operate there much.) – v6ak Dec 20 '16 at 18:56
  • @v6ak I just read [this link about setuid] (http://www.cis.syr.edu/~wedu/Teaching/IntrCompSec/LectureNotes_New/Set_UID.pdf). It shows a lot of difficulties, but looks doable. I think I'll try this out, but thanks for addressing these risks. – Johannes Dec 20 '16 at 20:32
  • @Lie Ryan: I am not root on that machine, so I can not create file systems. Is the setuid solution still possible? – Johannes Dec 20 '16 at 20:48
  • I agree it is doable. I just disagree that it is an easier than the original approach if security is a requirement. – v6ak Dec 20 '16 at 21:05