我想从linux命令行检查给定的明文密码是否与/ etc / shadow上的加密密码相同
(我需要使用它来对Web用户进行身份验证。我正在运行嵌入式Linux。)
我可以访问/ etc / shadow文件本身。
您可以使用awk轻松提取加密的密码。然后,您需要提取前缀$algorithm$salt$
(假设该系统未使用传统的DES,因为现在可以强行使用它,因此强烈建议不要使用该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);
}
另一种方法是使用现有程序,例如su
或login
。实际上,如果可以的话,最好是通过安排Web应用程序执行所需的任何操作su -c somecommand username
。这里的困难是将密码提供给su
;这需要一个终端。通常的工具来模拟一个终端是预期,但它是一个嵌入式系统一个很大的依赖性。另外,虽然su
在BusyBox中,但由于许多用途要求将BusyBox二进制文件设置为setuid根,因此通常将其省略。尽管如此,从安全的角度来看,这是最可靠的方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句