Maneira mais segura de autenticar usuários em relação ao / etc / shadow usando PHP?

3

Essa questão tornou-se importante para mim, pois estou configurando um ambiente da Horda e quero usar as contas do sistema. Fazendo alguma pesquisa, encontrei principalmente 4 maneiras de fazer isso, que parecem ter algumas desvantagens. Agora estou pensando, qual é o mais seguro ou se estou perdendo algumas alternativas.

  • Método 1: Use o PAM (PHP)

    A Horde oferece um plugin de autenticação que faz uso da biblioteca PAM. Funciona bem, mas o servidor da Web precisa de acesso de leitura para / etc / shadow. Eu encontrei algumas declarações dizendo que isso é tão seguro quanto publicar o arquivo de senha para download.

  • Método 2: Use / bin / su (PHP)

    Além disso, a Horde fornece um módulo que usa /bin/su para autenticar chamando fopen (arquivo aberto) em /bin/su -c /bin/true $username e gravando a senha neste "arquivo". Atualmente, isso não funciona para mim. AFAIK, isso é provavelmente porque /bin/su está configurado para funcionar somente em um terminal. Eu li que era possível permitir esse uso de /bin/su , mas seria inseguro.

  • Método 3: Use o programa externo (linha de comando)

    Eu poderia escrever um pequeno programa que faz uso da biblioteca PAM e é invocado pelo PHP. Usando o SUID, ninguém poderia acessar /etc/shadow . No entanto, tenho que passar a senha como um argumento para o meu programa, o que novamente é considerado um risco de segurança. (Eu acho que essa é a razão, por que /bin/su não permite isso por padrão).

  • Método 4: Use o programa externo (rede local)

    Igual ao método 3, mas a comunicação pode ser feita por meio de soquetes unix ou conexões tcp. Não sei se isso é mais seguro que o número 3, provavelmente equivalente à questão de saber se é mais difícil espionar conexões de rede locais do que em tty!?

Eu acho que está claro, porque a primeira opção não é uma boa ideia. Mas eu não sei, o que há de errado com os outros, então eu ficaria feliz com algumas breves explicações.

    
por xwst 14.12.2013 / 00:40

1 resposta

1

Método 1: Eu não gosto simplesmente porque em 2 segundos pensando nisso, esses comentários são essencialmente corretos. Você está criando uma superfície que expõe seu arquivo /etc/shadow , seja ele explorável ou não, eu simplesmente não gosto disso.

Método 2: também é ruim. Codificar senhas em um arquivo é simplesmente idiota. Passá-los através de um cano parece igualmente perigoso.

Método 3: é provavelmente o jeito que eu iria, e eu não acho que você teria que escrever sua própria solução do zero. Em alguns minutos de googling eu encontrei esta implementação que alguém montou usando a API libpam.

implementação c

excerto da implementação de C - 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 );
} 

comando para compilá-lo

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

exemplo executado

$ ./chkpasswd myusername mypassword

Eu imagino que com um pouco de esforço essa abordagem poderia ser adaptada para atender às suas necessidades com a Horda.

implementação do PHP

Como uma outra alternativa para essa abordagem, você poderia potencialmente fazer o seu próprio no PHP. Eu encontrei esta biblioteca PAM no site da PECL que parece com o que você gostaria.

Eu também dou uma olhada em como o projeto Moodle faz isso. É discutido aqui.

PAM de uma perspectiva de segurança

Olhando para o propósito do PAM, eu esperaria que a interface da API fosse projetada de forma que nenhum acesso a entidades de nível inferior, como o /etc/shadow , precisaria ser necessário para que os usuários da API possam usá-lo. Isso é discutido um pouco no wiki do Gentoo neste artigo intitulado: PAM, seção: Como o PAM funciona .

tirado de Como o PAM funciona

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.

Método 4: Também é uma boa alternativa. Deve haver boa acessibilidade às bibliotecas e tal para fazer as chamadas necessárias para acessar algo como o LDAP através da rede para fazer sua autenticação para você. Um servidor LDAP também pode ser configurado no mesmo sistema que a instalação do Horde, configurando-o apenas para o uso da Horde.

Isso permitiria o acesso à autenticação do sistema subjacente, potencialmente, "agrupando-a" em um serviço LDAP para o Horde consumir.

Referências

por 14.12.2013 / 04:09