Linux

如何使用 Linux 檢查密碼?

  • September 14, 2021

我想從 linux 命令行檢查給定的明文密碼是否與 /etc/shadow 上的加密密碼相同

(我需要這個來驗證網路使用者。我正在執行嵌入式 linux。)

我可以訪問 /etc/shadow 文件本身。

您可以使用 awk 輕鬆提取加密密碼。然後你需要提取前綴$algorithm$salt$(假設這個系統沒有使用傳統的 DES,因為它現在可以被暴力破解,所以強烈反對)。

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

對於密碼檢查,底層 C 函式是crypt,但沒有標準的 shell 命令可以訪問它。

在命令行上,您可以使用 Perl 單行程式碼來呼叫crypt密碼。

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

由於這不能在純 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);
}

在沒有 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);
}

另一種方法是使用現有程序,例如sulogin。事實上,如果可以的話,最好安排 Web 應用程序通過su -c somecommand username. 這裡的困難是將密碼提供給su; 這需要一個終端。模擬終端的常用工具是expect,但它對嵌入式系統來說是一個很大的依賴項。此外,雖然su在 BusyBox 中,但它經常被省略,因為它的許多用途要求 BusyBox 二進製文件是 setuid root。儘管如此,如果你能做到,從安全的角度來看,這是最可靠的方法。

引用自:https://unix.stackexchange.com/questions/21705