Comment vérifier le mot de passe avec Linux?

Je veux vérifier, à partir de la command line linux, si un mot de passe en clair est le même qu'un mot de passe crypté sur un / etc / shadow

(J'ai besoin de cela pour authentifier les users web. J'exécute un Linux embedded.)

J'ai access au file / etc / shadow lui-même.

Vous pouvez facilement extraire le mot de passe crypté avec awk. Vous devez ensuite extraire le préfixe $algorithm$salt$ (en supposant que ce système n'utilise pas le DES traditionnel, ce qui est fortement déconseillé car il peut être forcé par la force ces jours-ci).

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

Pour la vérification du mot de passe, la fonction C sous-jacente est crypt , mais il n'y a pas de command shell standard pour y accéder.

Sur la command line, vous pouvez utiliser une ligne Perl pour appeler crypt sur le mot de passe.

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

Comme cela ne peut pas être fait avec des outils shell purs, si Perl est disponible, vous pouvez tout aussi bien le faire en Perl. (Ou Python, Ruby, … tout ce que vous avez disponible qui peut appeler la fonction crypt .) Attention, code non testé.

 #!/usr/bin/env perl use warnings; use ssortingct; 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); } 

Sur un système embarqué sans Perl, j'utiliserais un petit programme C dédié. Attention, tapé directement dans le browser, je n'ai même pas essayé de comstackr. Ceci est destiné à illustrer les étapes nécessaires, pas comme une implémentation robuste!

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

Une approche différente consiste à utiliser un programme existant tel que su ou login . En fait, si vous le pouvez, il serait idéal de faire en sorte que l'application Web exécute tout ce dont elle a besoin via le su -c somecommand username . La difficulté ici est de fournir le mot de passe à su ; cela nécessite un terminal. L'outil habituel pour émuler un terminal est attendu , mais c'est une grande dépendance pour un système embarqué. En outre, bien que su soit dans BusyBox, il est souvent omis car beaucoup de ses utilisations nécessitent que le binary BusyBox soit défini comme root. Pourtant, si vous pouvez le faire, c'est l'approche la plus robuste du sharepoint vue de la security.

Jetez un oeil à l' man 5 shadow et l' man 3 crypt . De ce dernier, vous pouvez apprendre que les hachages de mot de passe dans /etc/shadow ont la forme suivante:

  $id$salt$encrypted 

id définit le type de encryption et, en lisant plus loin, peut être l'un des

  ID | Method --------------------------------------------------------- 1 | MD5 2a | Blowfish (not in mainline glibc; added in some | Linux dissortingbutions) 5 | SHA-256 (since glibc 2.7) 6 | SHA-512 (since glibc 2.7) 

Selon le type de hachage, vous devez utiliser la fonction / l'outil approprié pour générer et vérifier le mot de passe «à la main». Si le système contient le programme mkpasswd , vous pouvez l'utiliser comme suggéré ici . (Vous prenez le sel du file shadow, si ce n'était pas évident.) Par exemple, avec les passwords md5 :

  mkpasswd -5 <the_salt> <the_password> 

va générer la string qui doit correspondre à l'input /etc/shadow .

Il y avait une question similaire posée sur Stack Overflow . cluelessCoder a fourni un script utilisant expect , que vous pouvez ou non avoir sur votre système embarqué.

 #!/bin/bash # # login.sh $USERNAME $PASSWORD #this script doesn't work if it is run as root, since then we don't have to specify a pw for 'su' if [ $(id -u) -eq 0 ]; then echo "This script can't be run as root." 1>&2 exit 1 fi if [ ! $# -eq 2 ]; then echo "Wrong Number of Arguments (expected 2, got $#)" 1>&2 exit 1 fi USERNAME=$1 PASSWORD=$2 #since we use expect inside a bash-script, we have to escape tcl-$. expect << EOF spawn su $USERNAME -c "exit" expect "Password:" send "$PASSWORD\r" #expect eof set wait_result [wait] # check if it is an OS error or a return code from our command # index 2 should be -1 for OS erro, 0 for command return code if {[lindex \$wait_result 2] == 0} { exit [lindex \$wait_result 3] } else { exit 1 } EOF 

Gardez à l'esprit que, en supposant que le système est correctement configuré, le programme devra être exécuté en tant que root.

Une meilleure solution que de lire directement le file shadow et d'écrire votre propre code autour de crypt serait d'utiliser simplement les bindings pam.

Le tarball de calmar était fourni avec un simple outil de CLI pour vérifier les noms d'users / passwords en utilisant stdio – si simple à adapter à l'aide d'arguments – bien que la version que j'avais piratée auparavant n'était guère une affiche pin-up pour la programmation structurée. Un rapide google et il semble que les versions plus récentes ont été nettoyées de manière significative, mais encore quelques "goto est là.