Сценарий:
В скрипте bash я должен проверить, является ли пароль, заданный пользователем, действительным паролем пользователя.
Т.е. предположим, у меня есть пользователь A с паролем PA .. В сценарии я попросил пользователя A ввести свой пароль, так как проверить, действительно ли введенная строка является его паролем? ...
expect
в stackoverflow.com/a/1503831/320594 .Ответы:
Поскольку вы хотите сделать это в сценарии оболочки, пара вкладов в Как проверить пароль в Linux? (на Unix.SE , предложенный AB ) особенно актуальны:
/etc/shadow
дает часть решения.mkpasswd
команды , присутствующие в Debian (и Ubuntu).Чтобы вручную проверить, является ли строка действительно паролем какого-либо пользователя, вы должны хешировать его с помощью того же алгоритма хеширования, что и в теневой записи пользователя, с той же солью, что и в теневой записи пользователя. Затем его можно сравнить с хешем пароля, хранящимся там.
Я написал полный рабочий скрипт, демонстрирующий, как это сделать.
chkpass
, вы можете запустить, и он будет читать строку из стандартного ввода и проверять, если это пароль.chkpass user
user
mkpasswd
утилиту, от которой зависит этот скрипт.Примечания по безопасности
Это может быть не правильный подход.
Вопрос о том, следует ли считать такой подход безопасным и иным ли уместным, зависит от деталей вашего варианта использования, которые вы не предоставили (на момент написания статьи).
Это не было проверено.
Хотя я пытался проявлять осторожность при написании этого сценария, он не был должным образом проверен на наличие уязвимостей в безопасности . Он предназначен для демонстрации и будет "альфа" программным обеспечением, если будет выпущен как часть проекта. Более того...
Другой пользователь, который «смотрит», может обнаружить соль пользователя .
Из-за ограничений в том, как
mkpasswd
принимать соленые данные, этот сценарий содержит известный недостаток безопасности , который вы можете или не можете считать приемлемым в зависимости от варианта использования. По умолчанию пользователи в Ubuntu и большинстве других систем GNU / Linux могут просматривать информацию о процессах, выполняемых другими пользователями (включая root), включая их аргументы командной строки. Ни ввод пользователя, ни сохраненный хэш пароля не передаются в качестве аргумента командной строки какой-либо внешней утилите. Но соль , извлеченная изshadow
базы данных, будет дана в качестве аргумента командной строки дляmkpasswd
, так как это единственный способ , которым утилита принимает соль в качестве входных данных.Если
www-data
) запустить свой код, или/proc
)может проверить аргументы командной строки,
mkpasswd
поскольку он запускается этим сценарием, затем они могут получить копию соли пользователя изshadow
базы данных. Они , возможно , должны быть в состоянии угадать , когда эта команда выполняется, но иногда достижимо.Атакующий с вашей солью не так плох, как атакующий с вашей солью и хэшем , но это не идеально. Соль не дает достаточно информации, чтобы кто-то мог найти ваш пароль. Но это позволяет кому-то генерировать радужные таблицы или предварительно вычисленные хеши словаря, специфичные для этого пользователя в этой системе. Это изначально бесполезно, но если ваша безопасность будет скомпрометирована на более позднем этапе и будет получен полный хэш, его можно будет взломать быстрее, чтобы получить пароль пользователя, прежде чем он получит возможность изменить его.
Таким образом, этот недостаток безопасности является обостряющим фактором в более сложном сценарии атаки, а не полностью уязвимой уязвимостью. И вы могли бы рассмотреть вышеуказанную ситуацию надуманным. Но я не хочу рекомендовать любой метод для общего, реального использования, который пропускает любые непубличные данные от
/etc/shadow
пользователя без полномочий root.Вы можете полностью избежать этой проблемы:
Будьте осторожны, как вы называете этот сценарий.
Если вы позволяете ненадежному пользователю запускать этот сценарий от имени пользователя root или запускать любой процесс от имени пользователя root, который вызывает этот сценарий, будьте осторожны . Изменяя среду, они могут заставить этот скрипт - или любой скрипт, который запускается от имени root - делать что угодно . Если вы не можете предотвратить это, вы не должны разрешать пользователям повышенные привилегии для запуска сценариев оболочки.
Смотрите 10.4. Языки сценариев оболочки (производные sh и csh) в книге Дэвида А. Уилера по безопасному программированию для Linux и Unix HOWTO для получения дополнительной информации об этом. Хотя его презентация сосредоточена на сценариях setuid, другие механизмы могут стать жертвами некоторых из тех же проблем, если они неправильно очищают среду.
Другие заметки
Он поддерживает чтение хэшей только из
shadow
базы данных.Для работы этого скрипта пароли должны быть затенены (т. Е. Их хеши должны находиться в отдельном
/etc/shadow
файле, который может прочитать только пользователь root, а не в нем/etc/passwd
).Это всегда должно быть в Ubuntu. В любом случае, если необходимо, скрипт может быть тривиально расширен для чтения хешей паролей,
passwd
а такжеshadow
.Имейте
IFS
в виду, когда модифицируете этот скрипт.Я установил
IFS=$
в начале, так как три данных в хэш-поле теневой записи разделены$
.$
, поэтому хэш-тип и соль есть"${ent[1]}"
и,"${ent[2]}"
а не"${ent[0]}"
и"${ent[1]}"
, соответственно.Единственные места в этом скрипте, где
$IFS
определяется, как оболочка разделяет или объединяет слова,когда эти данные разбиваются на массив, инициализируя его из
$(
)
подстановки команды без кавычек в:когда массив восстанавливается в строку для сравнения с полным полем из
shadow
,"${ent[*]}"
выражение в:Если вы модифицируете скрипт и выполняете его деление слов (или объединение слов) в других ситуациях, вам нужно будет установить
IFS
разные значения для разных команд или разных частей скрипта.Если вы не помните об этом и предполагаете,
$IFS
что установлен обычный пробел ($' \t\n'
), вы можете в конечном итоге заставить свой скрипт вести себя довольно странным образом.источник
Вы можете неправильно использовать
sudo
для этого.sudo
имеет-l
опцию для проверки привилегий sudo, которые есть у пользователя, и-S
для чтения пароля из stdin. Однако, независимо от того, какой уровень привилегий имеет пользователь, в случае успешной аутентификацииsudo
возвращается со статусом выхода 0. Таким образом, вы можете использовать любой другой статус выхода в качестве указания на то, что аутентификация не работает (при условии, чтоsudo
сама по себе не имеет никаких проблем, например, ошибки разрешения или невернаяsudoers
конфигурация).Что-то вроде:
Этот скрипт довольно сильно зависит от
sudoers
конфигурации. Я принял настройки по умолчанию. Вещи, которые могут привести к сбою:targetpw
илиrunaspw
установленlistpw
являетсяnever
Другие проблемы включают (спасибо Элия):
/var/log/auth.log
sudo
должен быть запущен как пользователь, для которого вы аутентифицируетесь. Если у вас нетsudo
привилегий для запускаsudo -u foo sudo -lS
, это означает, что вам придется запускать скрипт в качестве целевого пользователя.Теперь причина, по которой я использовал здесь-документы, состоит в том, чтобы препятствовать подслушиванию. Переменный используются как часть командной строки более легко выявлено с помощью
top
илиps
или других инструментов для проверки процессов.источник
sudo
конфигами (как вы говорите) и загромождает/var/log/auth.log
записи каждой попытки, это быстро, просто и использует существующую утилиту, а не изобретает колесо (так сказать). Я предлагаю установитьIFS=
дляread
, чтобы предотвратить ложные успехи для пользовательского ввода с пробелами и не дополненными паролями, а также ложные сбои для пользовательского ввода и паролей с пробелами. (У моего решения была похожая ошибка.) Вы также можете объяснить, как его следует запускать как пользователь, чей пароль проверяется.sudo -l
заставляет запись быть написанной с "COMMAND=list
". Между прочим (хотя это и не связано), хотя объективно лучше это делать, использование строки здесь вместо документа здесь позволяет достичь той же цели безопасности и является более компактным. Поскольку скрипт уже использует bashismsread -s
и&>
, использованиеif sudo -lS &>/dev/null <<<"$PASSWD"; then
не менее переносимо. Я не предлагаю вам изменить то, что у вас есть (это нормально). Скорее, я упоминаю об этом, чтобы читатели знали, что у них тоже есть эта опция.sudo -l
что отключил что-то - возможно, он сообщал, когда пользователь пытается выполнить команду, что ему не разрешено.Другой метод (вероятно, более интересный для его теоретического содержания, чем для его практического применения).
Пароли пользователей хранятся в
/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/
:SHA-512
соленый / зашифрованный парольЧтобы соответствовать данному паролю
bar
для данного пользователяfoo
, первое, что нужно сделать, это получить соль:Затем нужно получить полный зашифрованный / зашифрованный пароль:
Затем данный пароль может быть засолен / зашифрован и сопоставлен с посоленным / зашифрованным паролем пользователя, хранящимся в
/etc/shadow
:Они совпадают! Все положить в
bash
сценарий:Выход:
источник
sudo getent shadow
>>sudo grep ...
. В остальном приятно. Это то, о чем я думал изначально, потом стало лень.getent
+grep
+cut
>grep
+cut
getent
могу сделать поиск для вас. Я взял на себя смелость редактирования.mkpasswd
для создания хеша из пользовательского ввода и существующей соли (и включал дополнительные функции и диагностику), вы вместо этого написали простую программу на Python, реализующуюmkpasswd
наиболее важные функции, и использовали ее. Я рекомендую вам установитьIFS=
при чтении ввода пароля, и цитаты${password}
с"
, поэтому попытки ввода пароля с пробелами не нарушают сценарий.