如何在 Linux 上检查密码?

mic*_*con 33 linux command-line password embedded

我想从 linux 命令行检查给定的明文密码是否与 /etc/shadow 上的加密密码相同

(我需要这个来验证网络用户的身份。我正在运行一个嵌入式 linux。)

我可以访问 /etc/shadow 文件本身。

Gil*_*il' 24

您可以使用 awk 轻松提取加密的密码。然后,您需要提取前缀$algorithm$salt$(假设该系统不使用传统的 DES,强烈反对使用传统的 DES,因为现在它可以被暴力破解)。

correct=$(</etc/shadow awk -v user=bob -F : 'user == $1 {print $2}')
prefix=${correct%"${correct#\$*\$*\$}"}
Run Code Online (Sandbox Code Playgroud)

对于密码检查,底层的 C 函数是crypt,但没有标准的 shell 命令来访问它。

在命令行上,您可以使用 Perl one-liner 来调用crypt密码。

supplied=$(echo "$password" |
           perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "$prefix")
if [ "$supplied" = "$correct" ]; then …
Run Code Online (Sandbox Code Playgroud)

由于这不能在纯 shell 工具中完成,如果您有可用的 Perl,您也可以在 Perl 中完成所有操作。(或 Python、Ruby ……任何可以调用该crypt函数的可用方法。)警告,未经测试的代码。

#!/usr/bin/env perl
use warnings;
use strict;
my @pwent = getpwnam($ARGV[0]);
if (!@pwent) {die "Invalid username: $ARGV[0]\n";}
my $supplied = <STDIN>;
chomp($supplied);
if (crypt($supplied, $pwent[1]) eq $pwent[1]) {
    exit(0);
} else {
    print STDERR "Invalid password for $ARGV[0]\n";
    exit(1);
}
Run Code Online (Sandbox Code Playgroud)

在没有 Perl 的嵌入式系统上,我会使用一个小的、专用的 C 程序。警告,直接在浏览器中输入,我什至没有尝试编译。这是为了说明必要的步骤,而不是作为一个健壮的实现!

/* Usage: echo password | check_password username */
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <shadow.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
    char password[100];
    struct spwd shadow_entry;
    char *p, *correct, *supplied, *salt;
    if (argc < 2) return 2;
    /* Read the password from stdin */
    p = fgets(password, sizeof(password), stdin);
    if (p == NULL) return 2;
    *p = 0;
    /* Read the correct hash from the shadow entry */
    shadow_entry = getspnam(username);
    if (shadow_entry == NULL) return 1;
    correct = shadow_entry->sp_pwdp;
    /* Extract the salt. Remember to free the memory. */
    salt = strdup(correct);
    if (salt == NULL) return 2;
    p = strchr(salt + 1, '$');
    if (p == NULL) return 2;
    p = strchr(p + 1, '$');
    if (p == NULL) return 2;
    p[1] = 0;
    /*Encrypt the supplied password with the salt and compare the results*/
    supplied = crypt(password, salt);
    if (supplied == NULL) return 2;
    return !!strcmp(supplied, correct);
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用现有程序,例如sulogin。事实上,如果可以,最好安排 Web 应用程序通过su -c somecommand username. 这里的困难是将密码提供给su; 这需要一个终端。模拟终端的常用工具是expect,但它对嵌入式系统来说是一个很大的依赖。此外,虽然su在 BusyBox 中,但它经常被省略,因为它的许多用途要求 BusyBox 二进制文件是 setuid root。尽管如此,如果你能做到,从安全的角度来看,这是最可靠的方法。

  • 我喜欢“su”方法。 (2认同)

roz*_*acz 12

看看man 5 shadowman 3 crypt。从后者,您可以了解到密码哈希/etc/shadow具有以下形式:

 $id$salt$encrypted
Run Code Online (Sandbox Code Playgroud)

whereid定义加密类型,进一步阅读,可以是其中之一

          ID  | Method
          ---------------------------------------------------------
          1   | MD5
          2a  | Blowfish (not in mainline glibc; added in some
              | Linux distributions)
          5   | SHA-256 (since glibc 2.7)
          6   | SHA-512 (since glibc 2.7)
Run Code Online (Sandbox Code Playgroud)

根据散列的类型,您需要使用适当的函数/工具来“手动”生成和验证密码。如果系统包含mkpasswd程序,您可以按照此处的建议使用。(如果这不明显,您可以从影子文件中取出。)例如,使用md5密码:

 mkpasswd -5 <the_salt> <the_password>
Run Code Online (Sandbox Code Playgroud)

将生成应匹配/etc/shadow条目的字符串。

  • 在我的 Debian wheezy 上,命令 `mkpasswd` 的语法完全不同,我必须使用 `apt-get install whois` 安装它。影子行 `&lt;user&gt;:$6$&lt;salt&gt;$&lt;pwd&gt;:` 的命令行是 `mkpasswd -msha-512 &lt;password&gt; &lt;salt&gt;` (2认同)