Bagaimana cara memeriksa kata sandi dengan Linux?

22

Saya ingin memeriksa, dari baris perintah linux, apakah kata sandi cleartext yang diberikan sama dengan kata sandi yang di-crypted pada / etc / shadow

(Saya perlu ini untuk mengautentikasi pengguna web. Saya menjalankan linux tertanam.)

Saya memiliki akses ke file / etc / shadow itu sendiri.

michelemarcon
sumber
Masuk sebagai pengguna dengan kata sandi?
Kusalananda
Tes harus dilakukan secara otomatis, saya tidak bisa mengetikkan kata sandi secara manual dari server web
michelemarcon

Jawaban:

17

Anda dapat dengan mudah mengekstrak kata sandi terenkripsi dengan awk. Anda kemudian perlu mengekstrak awalan $algorithm$salt$(dengan anggapan bahwa sistem ini tidak menggunakan DES tradisional, yang sangat tidak digunakan lagi karena dapat menjadi kasar sekarang ini).

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

Untuk pemeriksaan kata sandi, fungsi C yang mendasarinya adalah crypt, tetapi tidak ada perintah shell standar untuk mengaksesnya.

Pada baris perintah, Anda dapat menggunakan Perl satu-liner untuk memanggil cryptkata sandi.

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

Karena ini tidak dapat dilakukan dalam alat shell murni, jika Anda memiliki Perl tersedia, Anda mungkin juga melakukan semuanya di Perl. (Atau Python, Ruby, ... apa pun yang Anda miliki yang dapat memanggil cryptfungsi.) Peringatan, kode yang belum diuji.

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

Pada sistem tertanam tanpa Perl, saya akan menggunakan program C kecil yang berdedikasi. Peringatan, mengetik langsung ke browser, saya bahkan belum mencoba untuk mengkompilasi. Ini dimaksudkan untuk menggambarkan langkah-langkah yang diperlukan, bukan sebagai implementasi yang kuat!

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

Pendekatan yang berbeda adalah dengan menggunakan program yang ada seperti suatau login. Bahkan, jika Anda bisa, itu akan ideal untuk mengatur aplikasi web untuk melakukan apa pun yang dibutuhkan melalui su -c somecommand username. Kesulitan di sini adalah untuk memberi makan kata sandi su; ini membutuhkan terminal. Alat yang biasa untuk meniru terminal adalah yang diharapkan , tetapi itu adalah ketergantungan besar untuk sistem embedded. Selain itu, saat suberada di BusyBox, sering kali dihilangkan karena banyak penggunaannya membutuhkan biner BusyBox untuk menjadi setuid root. Namun, jika Anda bisa melakukannya, ini adalah pendekatan yang paling kuat dari sudut pandang keamanan.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Saya suka supendekatannya.
Benjohn
6

Lihatlah man 5 shadowdan man 3 crypt. Dari yang terakhir, Anda dapat mengetahui bahwa hash dalam kata sandi /etc/shadowmemiliki formulir berikut:

 $id$salt$encrypted

di mana idmendefinisikan jenis enkripsi dan, membaca lebih lanjut, bisa menjadi salah satunya

          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)

Bergantung pada jenis hash, Anda perlu menggunakan fungsi / alat yang sesuai untuk membuat dan memverifikasi kata sandi "dengan tangan". Jika sistem berisi mkpasswdprogram, Anda dapat menggunakannya seperti yang disarankan di sini . (Anda mengambil garam dari file bayangan, jika itu tidak jelas.) Misalnya, dengan md5kata sandi:

 mkpasswd -5 <the_salt> <the_password>

akan menghasilkan string yang harus cocok dengan /etc/shadowentri.

rozcietrzewiacz
sumber
1
Pada wheezy Debian saya, saya memiliki sintaks yang sama sekali berbeda untuk perintah mkpasswd, yang harus saya instal menggunakan apt-get install whois. Baris perintah untuk garis bayangan <user>:$6$<salt>$<pwd>:adalahmkpasswd -msha-512 <password> <salt>
Daniel Alder
1

Ada pertanyaan serupa yang diajukan pada Stack Overflow . cluelessCoder menyediakan skrip menggunakan ekspektasi , yang mungkin atau mungkin tidak Anda miliki pada sistem embedded Anda.

#!/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
mr. Shu
sumber
0

Ingatlah bahwa, dengan asumsi sistem dikonfigurasikan dengan benar, program harus dijalankan sebagai root.

Solusi yang lebih baik daripada membaca file shadow secara langsung dan menulis kode Anda sendiri di sekitar crypt adalah dengan hanya menggunakan pam bindings.

The squid tarbal digunakan untuk datang dengan alat CLI sederhana untuk memverifikasi username / password menggunakan stdio - begitu sederhana untuk beradaptasi dengan menggunakan argumen - meskipun versi saya hack sebelumnya hampir tidak poster pin-up untuk pemrograman terstruktur. Google cepat dan sepertinya versi yang lebih baru telah dibersihkan secara signifikan tetapi masih ada beberapa yang ada di sana.

symcbean
sumber
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 ${@}
Alberto Salvia Novella
sumber
Muntahkan kesalahanline 61: :: syntax error: operand expected (error token is ":")
hoefling
Emulator terminal harus Bash 5, dan Anda harus menunjukkan nama pengguna dan kata sandi sebagai argumen. Saya telah menguji itu berhasil.
Alberto Salvia Novella