我正在为 Linux 中的一些恶意软件检测脚本制作一个 GUI 工具,以便服务器管理员能够在网络中分析该脚本的结果。
据我所知 /etc/shadow 中使用的加密很强大,我想在我的应用程序中的 root 中使用相同的密码,并检查 /etc/shadow 中的更改并同步 db 中的 root 密码并允许管理员登录使用 root 凭据。
我将用 PHP 来开发它。我想知道这到底使用了什么加密,是否可以在 php 中实现相同的功能,这样我就可以让人们使用 root 凭据登录到我的 php 中的 gui?
答案1
密码字段中的值要么以$XY$
X 为数字开头,要么是两个 DES 之一(标准或扩展,取决于长度)。
DES 很少受到支持,因为它不再安全。是Y
可选的,具体取决于X
指定以下内容(第二个之后$
):
1
: CRYPT_MD5 (Y
空)
2
: CRYPT_BLOWFISH (Y
可以是a
,x
或y
)
5
: CRYPT_SHA256
6
: CRYPT_SHA512
您最有可能遇到的$6$
情况是,计算是基于重复(标准 5000 次)应用res = sha(res + salt)
从 开始进行的res = password
。盐跟随第二个$
到第三个,$
除非也可以指定不同的轮数,然后将其存储在盐之前:
$6$salt$result
$6$rounds=N$salt$result
(其中第一个意味着 5000 轮)。
你当然可以自己实现这一点,但我会检查 PHP 的 crypt 是否支持指定要使用的算法,或者以其他方式查看调用(例如在Ubuntu 上的包mkpasswd
中)whois
鉴于所有这些都有效,我建议不要使用 root 帐户和密码,即使不是通过 HTTPS。如果您的 PHP 受到威胁,注入一些东西来窥探系统的 root 密码将非常容易。
答案2
我可以让人们使用 root 凭据登录到我的 php 中的 gui 吗?
如果您的意思是 GUI 进程具有 root 凭据,那么是的。 这是一个要求。 passwd
和其他这样做的事情有setuid 位设置并由 root 拥有。有关如何使用 php 执行此操作的说明看这里。
首先要确保有关密码的基本事实很清楚——我想您可能已经知道这一点,但是:密码不是存储在系统中。它们的单向哈希是。单向哈希是可以使用加密算法从源字符串(例如实际密码)创建的字符串,但是无法从哈希重新创建源。
这意味着即使有人掌握了/etc/shadow
,他们也无法重建用户密码。加密是一种方法,无法逆转。但是,您可以获取一个字符串,以相同的方式对其进行加密,然后将其与哈希值进行比较。这就是密码验证的发生方式。
中的哈希字符串的结构/etc/shadow
解释如下安东的回答很好。下面是用C语言演示的身份验证的基本过程。PHP有一个包装器getpwnam()
或者你可以/etc/shadow
自己解析和存储。要了解crypt()
字符串的作用(正如 Anthon 提到的,它包括所使用算法的指示以及用于创建哈希的“盐”),请参阅注释 -> Glibc 注释在man 3 crypt
。 PHP 的crypt()
尽管文档不太清楚,但似乎以相同的方式工作。
唯一重要的函数是getpwnam()
和crypt()
,其他函数只是基本的输入、输出和字符串操作。
#define _XOPEN_SOURCE // Important.
#include <errno.h>
#include <crypt.h>
#include <shadow.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main (int argc, const char *argv[]) {
if (argc < 2) {
puts("Username required.");
return 1;
}
// Get shadow password.
struct spwd *spw = getspnam(argv[1]);
if (!spw) {
if (errno == EACCES) puts("Permission denied.");
else if (!errno) puts("No such user.");
else puts(strerror(errno));
return 1;
}
// Read password from user.
fprintf(stderr, "%s> ", argv[1]);
char buffer[4096];
int len = read(0, buffer, 4095);
// Ditch the newline.
buffer[len - 1] = '\0';
// Hash and report.
char *hashed = crypt(buffer, spw->sp_pwdp);
printf("%s\n%s\n", spw->sp_pwdp, hashed);
if (!strcmp(spw->sp_pwdp, hashed)) puts("Password matched.");
else puts("Password DID NOT match.");
return 0;
}
你可以这样编译:
gcc --std=c99 whatever.c -o testpw -lcrypt
您需要以 root 身份运行它,否则您将收到“权限被拒绝”的消息。您需要指定一个真实的用户名:
./testpw me
请注意,回显未禁用,因此在您键入密码时密码将可见。
答案3
对于 /etc/shadow 的结构请参见http://www.cyberciti.biz/faq/understanding-etcshadow-file/ 至于加密,我很确定linux使用Crypt算法(参见http://linux.die.net/man/3/crypt和http://php.net/manual/en/function.crypt.php)
答案4
密码未加密。它们用盐进行哈希处理。
通过将算法规范作为字符串的一部分,该格式用于/etc/passwd
或/etc/shadow
支持各种不同的哈希算法。哈希字符串的生成和验证都是使用该crypt
函数完成的,该函数根据输入字符串自动选择适当的算法。
php 中有一个crypt
函数,但对于您的用例,我不建议使用它。
使用 root 权限在 Web 服务器上运行代码是极其危险的。只需犯一个小错误,您的系统就会容易受到攻击。
相反,我建议您的 php 脚本仅通过在系统上执行标准 suid 实用程序之一来获得 root 权限,如果给定 root 密码,该实用程序就可以授予 root 权限。该su
命令可能最适合您。
如果系统配置为将散列根密码存储在 中/etc/passwd
,则您的脚本可以读取它并使用 crypt 来验证用户输入的密码。但没有太多理由这样做,而且如果/etc/shadow
使用的话也不起作用。相反,只需传递用户输入的任何密码su
,并从响应中了解su
密码是否正确。