Как проверить введенный пароль является допустимым для этого пользователя паролем?

Сценарий:

В сценарии bash я должен проверить, является ли пароль, заданный пользователем, допустимым паролем пользователя.

Предположим, у меня есть пользователь A с паролем PA .. В сценарии я попросил пользователя A ввести его пароль. Итак, как проверить, действительно ли введенная строка является его паролем? ... [!d3 ]

1
задан 7 May 2015 в 14:46

2 ответа

Вы можете использовать sudo для этого. sudo имеет опцию -l для проверки привилегий sudo, которые пользователь имеет, и -S для чтения в пароле из stdin. Однако независимо от того, какой уровень привилегий у пользователя есть, если он успешно прошел проверку подлинности, sudo возвращается с статусом завершения 0. Таким образом, вы можете принять любой другой статус выхода в качестве индикатора того, что аутентификация не сработала (если предположить, что sudo

Что-то вроде:

#! /bin/bash
IFS= read -rs PASSWD
sudo -k
if sudo -lS &> /dev/null << EOF
$PASSWD
EOF
then
    echo 'Correct password.'
else 
    echo 'Wrong password.'
fi

Этот сценарий немного зависит от того, конфигурации sudoers. Я предполагал установку по умолчанию. Вещи, которые могут привести к сбою:

targetpw или runaspw установлено listpw is never и т. Д.

Другие проблемы включают (спасибо Eliah):

targetpw или runaspw установлено sudo должно выполняться как пользователь, для которого вы аутентифицируетесь. Если у вас нет привилегий sudo, чтобы вы могли запускать sudo -u foo sudo -lS, это означает, что вам нужно будет запустить сценарий в качестве целевого пользователя.

Теперь, причина, по которой я здесь использовал, - это препятствовать подслушиванию. Переменная, используемая как часть командной строки, легче обнаружить с помощью top или ps или других инструментов для проверки процессов.

8
ответ дан 23 May 2018 в 21:13
  • 1
    Этот способ выглядит превосходно. Хотя он не будет работать с системами с необычными конфигурациями sudo (как вы говорите) и помехами /var/log/auth.log с записями каждой попытки, это быстро, просто и использует существующую утилиту, а не изобретать колесо (так что говорить). Я предлагаю установить IFS= для read, чтобы предотвратить ложные успехи для ввода пользователем с пробелами и непереполненные пароли, а также ложные сбои для ввода с пропущенным пользователем ввода и запаздывающих паролей. (У моего решения была аналогичная ошибка.) Вы также можете объяснить, как он должен запускаться как пользователь, пароль которого проверяется. – Eliah Kagan 11 May 2015 в 22:02
  • 2
    @EliahKagan каждая неудачная попытка регистрируется, но да, вы правы во всем остальном. – muru 11 May 2015 в 22:07
  • 3
    Успешная аутентификация также регистрируется. sudo -l заставляет запись записываться с помощью «COMMAND=list». Btw (несвязанный), в то время как это не объективно лучше, использование здесь строки вместо данного документа достигает той же цели безопасности и является более компактным. Поскольку скрипт уже использует базисы read -s и &>, использование if sudo -lS &>/dev/null <<<"$PASSWD"; then не менее переносимо. Я не предлагаю вам изменить то, что у вас есть (это просто отлично). Скорее, я упоминаю об этом, поэтому читатели знают, что у них есть этот вариант. – Eliah Kagan 11 May 2015 в 22:11
  • 4
    @EliahKagan ах. Я думал, что sudo -l отключил что-то - возможно, он сообщал, когда пользователь пытается запустить команду, которой им не разрешено. – muru 11 May 2015 в 22:14
  • 5
    @EliahKagan Действительно. Я использовал herstrings так, как раньше . Здесь я работал под неправильным представлением, что привело к heredocs, но потом я решил сохранить их в любом случае. – muru 11 May 2015 в 22:17

Другой способ (возможно, более интересен для его теоретического содержания, чем для его пратических приложений).

Пользовательские пароли хранятся в /etc/shadow.

Пароли, хранящиеся здесь, зашифрованы, в последних выпусках Ubuntu с использованием SHA-512.

В частности, при создании пароля пароль в открытом тексте солен и зашифрован через SHA-512.

Одно из решений было бы тогда солить / зашифровать данный пароль и сопоставить его с зашифрованным паролем пользователя, хранящимся в записи /etc/shadow данного пользователя.

Чтобы быстро описать, как пароли хранятся в каждой записи пользователя /etc/shadow , вот пример /etc/shadow для пользователя foo с паролем bar:

foo:$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:16566:0:99999:7:::
foo: имя пользователя 6: тип шифрования пароля lWS1oJnmDlaXrx1F: соль шифрования пароля [ f18]: SHA-512 засоленный / зашифрованный пароль

Чтобы соответствовать данному паролю bar для данного пользователя foo, первое, что нужно сделать, это получить соль:

$ sudo getent shadow foo | cut -d$ -f3
lWS1oJnmDlaXrx1F

Затем следует получить полную соль ed / encrypted password:

$ sudo getent shadow foo | cut -d: -f2
$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/

Затем данный пароль можно солить / зашифровать и сопоставить с паролем засоленного / зашифрованного пользователя, хранящимся в /etc/shadow:

$ python -c 'import crypt; print crypt.crypt("bar", "$6$lWS1oJnmDlaXrx1F")'
$6$lWS1oJnmDlaXrx1F$h4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/

Они совпадение! Все, что помещено в скрипт bash:

#!/bin/bash

read -p "Username >" username
IFS= read -p "Password >" password
salt=$(sudo getent shadow $username | cut -d$ -f3)
epassword=$(sudo getent shadow $username | cut -d: -f2)
match=$(python -c 'import crypt; print crypt.crypt("'"${password}"'", "$6$'${salt}'")')
[ ${match} == ${epassword} ] && echo "Password matches" || echo "Password doesn't match"

Выход:

$ ./script.sh 
Username >foo
Password >bar
Password matches
$ ./script.sh 
Username >foo
Password >bar1
Password doesn't match
3
ответ дан 23 May 2018 в 21:13
  • 1
    sudo getent shadow & gt; [F2]. В противном случае, хорошо. Это то, о чем я думал изначально, а потом слишком ленив. – muru 11 May 2015 в 22:58
  • 2
    @muru Спасибо. Definetly чувствует себя лучше, так обновляется, но все же я не уверен, что в этом случае getent + grep + cut & gt; [F4] + [F5] – kos 11 May 2015 в 23:07
  • 3
    Ик. getent может выполнить поиск. Я освобождался от редактирования. – muru 11 May 2015 в 23:09
  • 4
    @muru Да, вы должны иметь на самом деле, теперь я вижу точку! – kos 11 May 2015 в 23:10
  • 5
    Я думаю, что это на самом деле довольно практично, хотя я могу быть предвзятым: это тот же метод, который я использовал. Ваша реализация и презентация совершенно разные, но это определенно ценный ответ. В то время как я использовал mkpasswd для генерации хэша из пользовательского ввода и существующей соли (и включил дополнительные функции и диагностику), вы вместо этого закодировали простую программу Python, реализующую наиболее важные функции mkpasswd и использовали ее. Я рекомендую вам установить IFS= при чтении ввода пароля и указать ${password} с ", так что попытки пароля с пробелами не нарушают сценарий. – Eliah Kagan 12 May 2015 в 00:18

Другие вопросы по тегам:

Похожие вопросы: