Linux ile şifre nasıl kontrol edilir?


22

Linux komut satırından belirli bir açık metin şifresinin / etc / shadow üzerindeki şifreli bir şifreyle aynı olup olmadığını kontrol etmek istiyorum

(Web kullanıcılarının kimliklerini doğrulamak için buna ihtiyacım var. Katıştırılmış bir linux kullanıyorum.)

/ Etc / shadow dosyasının kendisine erişebiliyorum.


Şifre ile kullanıcı olarak giriş yap?
Kusalananda

Test otomatik olarak yapılmalı, şifreyi web sunucusundan el ile
yazamıyorum

Yanıtlar:


17

Şifreli şifreyi awk ile kolayca çıkarabilirsiniz. Daha sonra ön eki çıkarmanız gerekir $algorithm$salt$(bu sistemin, bugünlerde kaba bir şekilde zorlanabileceği için kesinlikle kullanımdan kaldırılmış olan geleneksel DES'i kullanmadığı varsayılarak).

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

Parola kontrolü için, temel C işlevidir crypt, ancak erişmek için standart bir kabuk komutu yoktur.

Komut satırında, cryptşifreyi çağırmak için bir Perl bir liner kullanabilirsiniz .

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

Bu saf kabuk araçlarında yapılamadığından, eğer Perl varsa, her şeyi Perl'de de yapabilirsin. (Veya Python, Ruby,… ne cryptfonksiyon varsa çağırabiliyorsanız .) Uyarı, denenmemiş kod.

#!/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 olmayan gömülü bir sistemde küçük, özel bir C programı kullanırdım. Doğrudan tarayıcıya yazılan uyarı, derlemeye bile çalışmadım. Bu, sağlam bir uygulama olarak değil, gerekli adımları göstermek içindir!

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

Farklı bir yaklaşım, suya da gibi mevcut bir programı kullanmaktır login. Aslında, yapabiliyorsanız, web uygulamasının ihtiyacı olan her şeyi yapmasını sağlamak için ideal olacaktır su -c somecommand username. Buradaki zorluk, şifreyi şu şekilde beslemektir su; bu bir terminal gerektirir. Bir terminali taklit eden normal araç beklenir , ancak gömülü bir sistem için büyük bir bağımlılıktır. Ayrıca, suBusyBox içerisindeyken, çoğu zaman ihmal edilir, çünkü kullanımlarının çoğu, BusyBox ikilisinin setuid root olmasını gerektirir. Yine de, bunu yapabiliyorsanız, güvenlik açısından en sağlam yaklaşım budur.


1
Ben suyaklaşımı severim .
Benjohn

6

Göz at man 5 shadowve man 3 crypt. İkincisi, şifre hashlesinin /etc/shadowaşağıdaki forma sahip olduğunu öğrenebilirsiniz :

 $id$salt$encrypted

burada idşifreleme türünü tanımlar ve bundan başka, okuma biri olabilir

          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)

Karma türüne bağlı olarak, "elle" şifresini oluşturmak ve doğrulamak için uygun işlevi / aracı kullanmanız gerekir. Sistem mkpasswdprogram içeriyorsa , burada önerildiği şekilde kullanabilirsiniz . ( Açık değilse , tuzu gölge dosyasından alırsınız .) Örneğin, md5şifrelerle:

 mkpasswd -5 <the_salt> <the_password>

/etc/shadowgirişle eşleşmesi gereken dizeyi oluşturur .


1
Debian wheezy'imde mkpasswd, kullanmam gereken komut için tamamen farklı bir sözdizim vardı apt-get install whois. Gölge hattı için komut satırı <user>:$6$<salt>$<pwd>:oldumkpasswd -msha-512 <password> <salt>
Daniel Alder

1

Bir yoktu Yığın taşması sorulan benzer soru . cluelessCoder , gömülü sisteminizde bulunabilecek ya da bulunmayabilecek beklentisini kullanan bir komut dosyası sağladı .

#!/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

0

Sistemin uygun şekilde yapılandırıldığı varsayılarak, programın root olarak çalıştırılması gerekeceğini unutmayın.

Gölge dosyasını doğrudan okumaktan ve kendi kodunuzu crypt üzerine yazmaktan daha iyi bir çözüm, sadece pam ciltlemelerini kullanmak olacaktır.

Kalamar argümanları kullanarak adapte kadar basit - - arşivini stdio kullanarak kullanıcı adları / şifreler doğrulamak için basit bir CLI aracıyla gelirdi girildi sürümü daha önce pek yapılandırılmış programlama için bir pin-up afiş olmasına rağmen. Hızlı bir google ve daha yeni sürümler önemli ölçüde temizlenmiş gibi gözüküyor, ancak yine de birkaç tane var.


0
#! /bin/bash
#  (GPL3+) Alberto Salvia Novella (es20490446e)


passwordHash () {
    password=${1}
    salt=${2}
    encryption=${3}

    hashes=$(echo ${password} | openssl passwd -${encryption} -salt ${salt} -stdin)
    echo $(substring ${hashes} "$" "3")
}


passwordIsValid () {
    user=${1}
    password=${2}

    encryption=$(secret "encryption" ${user})
    salt=$(secret "salt" ${user})
    salted=$(secret "salted" ${user})
    hash=$(passwordHash ${password} ${salt} ${encryption})

    [ ${salted} = ${hash} ] && echo "true" || echo "false"
}


secret () {
    secret=${1}
    user=${2}
    shadow=$(shadow ${user})

    if [ ${secret} = "encryption" ]; then
        position=1
    elif [ ${secret} = "salt" ]; then
        position=2
    elif [ ${secret} = "salted" ]; then
        position=3
    fi

    echo $(substring ${shadow} "$" ${position})
}


shadow () {
    user=${1}
    shadow=$(cat /etc/shadow | grep ${user})
    shadow=$(substring ${shadow} ":" "1")
    echo ${shadow}
}


substring () {
    string=${1}
    separator=${2}
    position=${3}

    substring=${string//"${separator}"/$'\2'}
    IFS=$'\2' read -a substring <<< "${substring}"
    echo ${substring[${position}]}
}


passwordIsValid ${@}

Bir hata line 61: :: syntax error: operand expected (error token is ":")
spews

Terminal emülatörü, Bash 5 olmalıdır ve hem kullanıcı adını hem de parolayı argüman olarak belirtmeniz gerekir. İşe yaradığını test ettim.
Alberto Salvia Novella
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.