安全性 – 使用PHP对/ etc / shadow对用户进行身份验证的最安全方法?

这个问题对我来说很重要,因为我正在建立一个部落环境,并希望使用系统帐户.做一些搜索我发现主要有4种方法,这些方法似乎都有一些缺点.现在我想知道,哪一个最安全,或者我错过了一些替代方案.

>方法1:使用PAM(PHP)

Horde提供了一个使用PAM库的auth插件.工作正常,但Web服务器需要对/ etc / shadow的读访问权限.我发现一些声明说这和发布密码文件一样安全.
>方法2:使用/ bin / su(PHP)

此外,Horde提供了一个模块,使用/ bin / su进行身份验证,方法是在/ bin / su -c / bin / true $username上调用fopen(文件打开)并将密码写入此“文件”.目前,这对我不起作用. AFAIK,这可能是因为/ bin / su配置为仅在终端中工作.
我读过可以允许使用/ bin / su,但它会不安全.
>方法3:使用外部程序(命令行)

我可以编写一个使用PAM库的小程序,并由PHP调用.使用SUID,没有人可以访问/ etc / shadow.但是,我必须将密码作为参数传递给或将其传递到我的程序中,这再次被认为是一种安全风险. (我想这就是原因,为什么/ bin / su默认不允许它.)
>方法4:使用外部程序(本地网络)

与方法3相同,但可以通过unix套接字或tcp连接完成通信.我不知道这是否比#3更安全,可能相当于在本地网络连接上监视是否比在tty上更难的问题!?

我认为很清楚,为什么第一种选择不是一个好主意.但我不知道,其他人有什么不对,所以我会对一些简短的解释感到高兴.

解决方法:

方法1:我不喜欢仅仅因为在2秒的时间内考虑这些评论基本上是正确的.您正在创建一个暴露/ etc / shadow文件的表面,无论它是否可利用,我根本不喜欢那样做.

方法2:也不好.在文件中编码密码只是愚蠢的.将它们穿过管道似乎同样危险.

方法3:可能是我的方式,我认为你不必从头开始编写自己的解决方案.在几分钟的谷歌搜索中,我发现有人使用libpam API放在一起.

c实施

> PAM authentication for fun and profit

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 );
} 

命令编译它

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

示例运行

$./chkpasswd myusername mypassword

我想,通过一点努力,这种方法可以根据你的需要进行调整.

PHP implmentation

作为这种方法的另一种替代方法,您可以在PHP中推出自己的方法.我在PECL网站上找到了这个PAM库,看起来就像你想要的那样.

> http://pecl.php.net/package/PAM

我还要看看Moodle项目是如何做到的.这是在这里讨论的.

> Tips on configuring Moodle w/ PAM Kerberos

从安全角度来看PAM

看看PAM的目的我希望API接口的设计使得不需要访问较低级别的实体,例如/ etc / shadow,以便API的用户可以使用它.在本文标题为:PAM, section: How PAM works的Gentoo wiki上对此进行了一些讨论.

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.

方法4:也是一个很好的选择.应该可以很好地访问库,以便进行必要的调用以通过网络访问类似LDAP的内容来为您进行身份验证.也可以在与Horde安装相同的系统上设置LDAP服务器,配置它以供Horde使用.

这可以让您访问底层系统的身份验证,可能是通过将其“包装”在一个LDAP服务*Horde使用.

参考

> PAM authentication for fun and profit
> Linux PAM guides
> PAM tutorial (this is fairly useful)
> PAM Fedora guide

上一篇:ssh – SFTP与MySQL用户通过而不是PAM


下一篇:linux – Active Directory UID映射到特定的Unix UID