4

This question became important to me, since I'm setting up a Horde environment and want to use the system accounts. Doing some search I found mainly 4 ways of doing that, which all seem to have some drawbacks. Now I'm wondering, which one is most secure or if I'm missing some alternatives.

  • Method 1: Use PAM (PHP)

    Horde offers an auth plugin that makes use of the PAM library. Works fine, but the webserver needs read access to /etc/shadow. I found some statements saying this is as secure as publishing the password file for download.

  • Method 2: Use /bin/su (PHP)

    In addition, Horde provides a module that uses /bin/su to authenticate by calling fopen (file open) on /bin/su -c /bin/true $username and writing the password to this "file". Currently, this does not work for me. AFAIK, this is probably because /bin/su is configured to only work in a terminal. I read it was possible to allow this usage of /bin/su, but it would be insecure.

  • Method 3: Use external program (command line)

    I could write a small program that makes use of the PAM library and is invoked by PHP. Using SUID, no one could access /etc/shadow. However, I have to pass the password as an argument to or pipe it into my program, which again is said to be a security risk. (I guess that's the reason, why /bin/su does not allow it by default.)

  • Method 4: Use external program (local network)

    Same as method 3, but the communication could be done via unix sockets or tcp connections. I don't know whether this is more secure than #3, probably equivalent to the question whether it's harder to spy on local network connections than on tty!?

I think it is clear, why the first option isn't a good idea. But I don't know, what's wrong with the others, so I would be glad about some short explanations.

  • Have you considered alternatives such as using LDAP as your authentication mechanisms (both system and horde would auth to LDAP)? – casey Dec 14 '13 at 3:07
  • Yes, I thought about using LDAP. But I had the feeling, that it was too much effort for my purpose. My setup is meant to be used by only a couple of people. – xwst Dec 14 '13 at 22:25
3

Method 1: I don't like simply because in 2 seconds of thinking about it those comments are essentially correct. You're creating a surface that exposes your /etc/shadow file, whether it's exploitable or not, I simply don't like that having to do that.

Method 2: is also bad. Encoding passwords in a file is just dumb. Passing them through a pipe seems equally dangerous.

Method 3: is probably the way I'd go, and I don't think you'd have to write your own solution from scratch. In a couple of minutes of googling I found this implementation that someone put together using the libpam API.

c implementation

excerpt of C implementation - pam.c

#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct pam_response *reply;

int null_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {

        *resp = reply;
        return PAM_SUCCESS;

}

static struct pam_conv conv = { null_conv, NULL };

int main(int argc, char *argv[]) {

        int retval;
        char *user, *pass;   

        if(argc == 3) {

                user = argv[1];
                pass = strdup(argv[2]);

        } else { 

                fprintf(stderr, "Usage: login [username] [password]\n");
                exit(1);

        }

        return authenticate("system-auth", user, pass);

}   

int authenticate(char *service, char *user, char *pass) {

        pam_handle_t *pamh = NULL;
        int retval = pam_start(service, user, &conv, &pamh);

        if (retval == PAM_SUCCESS) {

                reply = (struct pam_response *)malloc(sizeof(struct pam_response));
                reply[0].resp = pass;
                reply[0].resp_retcode = 0;

                retval = pam_authenticate(pamh, 0);

                if (retval == PAM_SUCCESS)
                        fprintf(stdout, "Authenticated\n");

                else
                        fprintf(stdout, "Not Authenticated\n");

                pam_end(pamh, PAM_SUCCESS);

                return ( retval == PAM_SUCCESS ? 0:1 );

        }

        return ( retval == PAM_SUCCESS ? 0:1 );
} 

command to compile it

$ gcc -g -lpam -o chkpasswd pam.c

example run

$ ./chkpasswd myusername mypassword

I would imagine that with a little effort this approach could be adapted to suit your needs with Horde.

PHP implmentation

As another alternative to this approach you could potentially roll your own in PHP. I found this PAM library on the PECL website that looks like what you'd want.

I'd also take a look at how the Moodle project does it. It's discussed here.

PAM from a security perspective

Looking at the purpose of PAM I would expect that the API interface was designed so that no access to lower level entities, such as the /etc/shadow, would need to be required so that users of the API can use it. This is discussed a bit on the Gentoo wiki in this article titled: PAM, section: How PAM works.

exerpt from How PAM works

So when a user wants to authenticate itself against, say, a web application, then this web application calls PAM (passing on the user id and perhaps password or challenge) and checks the PAM return to see if the user is authenticated and allowed access to the application. It is PAMs task underlyingly to see where to authenticate against (such as a central database or LDAP server).

The strength of PAM is that everyone can build PAM modules to integrate with any PAM-enabled service or application. If a company releases a new service for authentication, all it needs to do is provide a PAM module that interacts with its service, and then all software that uses PAM can work with this service immediately: no need to rebuild or enhance those software titles.

Method 4: Also a good alternative. There should be good accessibility to libraries and such to make the calls necessary to access something like LDAP over the wire to do your authentication for you. An LDAP server could also be setup on the same system as the Horde installation, configuring it for just Horde's use.

This would gain you access to the underlying system's authentication, potentially, by "wrapping" it in an LDAP service for Horde to consume.

References

  • Thank you, this was helpful. But I think you misunderstood #2: It's not saving passwords in files, but the PHP equivalent of /bin/su -c /bin/true $user < $(echo $pass). Keeping this in mind, I'm not sure, if #3 is better than #2. And regarding the PHP implementation: Wouldn't that mean (again), that the webserver needs access to the shadow file? – xwst Dec 14 '13 at 22:42
  • @Stephan - I still do not fully understand what that su command will be doing then. Is it not passing the password into the su command when executed for user $user? As to your Q regarding access to shadow. No I do not believe so, since you'll be accessing shadow indirectly through the PAM API, which is how it's meant to be. I believe this API provides protected methods for performing authentication queries w/o having to give full read/write access to the actual shadow file. – slm Dec 15 '13 at 3:08
  • #2 is what you said. Running su ... and passing the password to it by writing it into the corresponding pipe. Correct me if I'm wrong, but even if I use the PAM API, it's still just a library, not a daemon. So the process making use of this API will need the rights to read the shadow file!? – xwst Dec 15 '13 at 15:38
  • @Stephan - Ah on #2, I see what you meant. I'm not sure about the pipe option. It seems dangerous to me still though. As to the API, I would expect that the API would be able to deal with security a little bit better. See here for issues w/ that approach: linux-pam.org/Linux-PAM-html/old/pam_appl-4.html – slm Dec 15 '13 at 17:01
  • @Stephan - added more details to A about su and PAM. – slm Dec 15 '13 at 17:09

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.