Шифрование паролей для скриптов на Linux с помощью OpenSSL

Быстрые ссылки
Пароли и скрипты
Установка OpenSSL и sshpass
Шифрование в командной строке
Использование OpenSSL в скрипте
Ваш пароль остаётся приватным
Пароли и скрипты
Хранить пароли прямо в shell-скриптах — плохая идея. Скрипт могут прочитать другие пользователи, резервные копии или система контроля версий. Если скрипт должен работать без участия человека (unattended), вводить пароль вручную невозможно. Одно из практических решений — хранить зашифрованный пароль в отдельном файле и расшифровывать его только во время выполнения скрипта. Для шифрования можно использовать OpenSSL, а для передачи расшифрованного пароля в ssh — утилиту sshpass.
Опорная идея: мы защищаем пароль удалённого аккаунта (публично неизвестный секрет) с помощью другого пароля (секрет для расшифровки). Файл с зашифрованным паролем хранится отдельно и имеет строгие права доступа.
Ключевые определения в одну строку:
- OpenSSL — набор инструментов для шифрования и криптографии.
- PBKDF2 — функция выработки ключа из пароля, замедляющая перебор паролей.
- Salt — случайное значение, добавляемое к паролю перед хешированием, чтобы выход отличался при тех же входных данных.
- sshpass — утилита для автоматической передачи пароля в ssh.
Важно: при наличии возможности лучше использовать SSH-ключи, ssh-agent, оркестраторы секретов (HashiCorp Vault, Ansible Vault) или менеджеры паролей. Описанный метод полезен, когда вы не контролируете целевую систему и обязаны использовать пароль.
Установка OpenSSL и sshpass
OpenSSL часто уже установлен. Если нет — вот корректные команды для популярных дистрибутивов.
На Ubuntu/Debian:
sudo apt update
sudo apt install opensslУстановка sshpass на Debian/Ubuntu:
sudo apt install sshpassНа Fedora:
sudo dnf install openssl
sudo dnf install sshpassНа Manjaro/Arch:
sudo pacman -Sy openssl
sudo pacman -Sy sshpassПримечание: пакеты и названия могут отличаться в специализированных репозиториях. Убедитесь, что устанавливаете из доверенных источников.
Шифрование в командной строке
Прежде чем внедрять в скрипт, попробуем зашифровать пароль вручную. Предположим, пароль удалённого аккаунта:
rusty!herring.pitshaftКоманда OpenSSL для симметричного шифрования (пример с AES-256-CBC и PBKDF2):
echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'Объяснение ключевых параметров:
- enc -aes-256-cbc: алгоритм AES-256 в режиме CBC.
- -md sha512: хеш-функция для выработки ключа.
- -a: base64-кодирование вывода (удобно хранить в текстовом файле).
- -pbkdf2: использовать PBKDF2 вместо устаревших KDF.
- -iter 100000: количество итераций для PBKDF2 (увеличьте для большей стойкости; влияет на производительность).
- -salt: добавляет случайный salt, поэтому каждый шифротекст уникален.
- -pass pass:’…’: пароль, используемый для шифрования (замените на надёжный).
Команда вернёт зашифрованную строку (base64). Чтобы расшифровать — используйте тот же набор опций и флаг -d:
echo U2FsdGVkX19iiiRNhEsG+wm/uKjtZJwnYOpjzPhyrDKYZH5lVZrpIgo1S0goZU46 | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'Если всё сделано правильно, команда вернёт исходный пароль.
Запись зашифрованного пароля в файл
Вместо вывода в терминал обычно записывают зашифрованный текст в скрытый файл с жёсткими правами доступа:
echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' > .secret_vault.txtПроверим расшифровку из файла (используем cat, а не echo, чтобы обработать переносы корректно):
cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password'Ограничим доступ к файлу:
chmod 600 .secret_vault.txt
ls -l .secret_vault.txtПрава 600 означают доступ только владельцу файла (чтение и запись).
Использование OpenSSL в скрипте
Ниже — минимальный пример скрипта, который расшифровывает пароль и подключается по SSH, записывая метку времени в удалённый файл “script.log”.
#!/bin/bash
# имя удалённого аккаунта
REMOTE_USER=geek
# пароль удалённого аккаунта (расшифровываем из скрытого файла)
REMOTE_PASSWD=$(cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password')
# адрес удалённой машины
REMOTE_LINUX=fedora-34.local
# подключаемся и добавляем метку времени в /home/geek/script.log
sshpass -p $REMOTE_PASSWD ssh -T $REMOTE_USER@$REMOTE_LINUX << _remote_commands
echo $USER "-" $(date) >> /home/$REMOTE_USER/script.log
_remote_commandsКомментарии к шагам в скрипте:
- REMOTE_USER — имя пользователя на удалённой системе.
- REMOTE_PASSWD — результат расшифровки, получаемый из .secret_vault.txt.
- REMOTE_LINUX — адрес удалённого хоста.
- sshpass принимает пароль и передаёт его ssh.
- ssh -T отключает аллокацию псевдо-TTY, что удобно в неинтерактивных сессиях.
Сохраняем в файл go-remote.sh и делаем исполняемым:
chmod +x go-remote.sh
./go-remote.shПроверяем журнал на удалённой машине:
cat script.log
Важные замечания по безопасности
Важно: сам по себе метод решает проблему “пароль не в скрипте” но добавляет новые риски. Ниже — основные из них и как их смягчить.
- Процесс-обзор (ps): передача пароля через аргументы командной строки (sshpass -p) может отобразиться в списке процессов и быть видима другим пользователям в тот промежуток времени. Лучше использовать методы, которые не выставляют пароль в argv.
- Временные файлы: создание временных файлов с паролем требует строгих прав и немедленного удаления.
- Кража скрытого файла: если атакующий получит доступ к файлу .secret_vault.txt и знает пароль для расшифровки, он извлечёт реальный пароль. Поэтому храните пароль расшифровки (ключ для OpenSSL) отдельно и защитите машину, на которой вы запускаете скрипт.
- Журналы и окружение: убедитесь, что вывод скрипта и переменные окружения не записывают реальные пароли в логи.
Рекомендации:
- Используйте sshpass -f или sshpass -e вместо -p, чтобы избежать отображения в ps.
- Храните пароль для расшифровки в защищённом рантайме (например, экспортируйте временно переменную SSHPASS и затем очищайте её).
- Ограничьте доступ к скрипту и к файлу с шифротекстом (chmod 700 для каталога, 600 для файлов).
- По возможности используйте SSH-ключи или решение для управления секретами.
Более безопасные варианты передачи пароля sshpass
Вариант с временным файловым хранилищем (более безопасно, чем -p):
# создаём временный файл с паролем
tmpfile=$(mktemp)
cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' > "$tmpfile"
chmod 600 "$tmpfile"
sshpass -f "$tmpfile" ssh -T $REMOTE_USER@$REMOTE_LINUX << _remote_commands
echo $USER "-" $(date) >> /home/$REMOTE_USER/script.log
_remote_commands
# удаляем временный файл как можно быстрее
shred -u "$tmpfile" || rm -f "$tmpfile"Вариант с переменной окружения SSHPASS (sshpass поддерживает флаг -e):
export SSHPASS=$(cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password')
sshpass -e ssh -T $REMOTE_USER@$REMOTE_LINUX << _remote_commands
echo $USER "-" $(date) >> /home/$REMOTE_USER/script.log
_remote_commands
# сразу очищаем переменную
unset SSHPASSЗамечание: хотя вариант с env переменной скрывает пароль из argv, некоторые системы мониторинга и дампы памяти могут помочь злоумышленнику. Удаляйте переменную сразу после использования.
Альтернативы
Если вы можете выбирать другой подход, рассмотрите эти безопаснее варианты:
- SSH-ключи с passphrase и ssh-agent: приватный ключ защищён passphrase и загружается в агент; скрипт использует агент без пароля.
- Ansible Vault или pass или gpg: инструменты для управления секретами с возможностью интеграции в автоматизацию.
- HashiCorp Vault: централизованное управление секретами, выдача краткоживых токенов.
- GPG симметричное шифрование: gpg -c для создания зашифрованного файла и gpg –decrypt для получения пароля.
- expect: автоматизация интерактивных программ (имеет свои риски хранения паролей в сценариях).
Пример шифрования через GPG (симметрично):
# шифруем
printf '%s
' "rusty!herring.pitshaft" | gpg --symmetric --cipher-algo AES256 -o .secret_vault.gpg
# расшифровываем
gpg --decrypt .secret_vault.gpgGPG удобен, если у вас уже есть инфраструктура GPG.
Когда описанный подход не годится
- Если на целевой системе можно настроить SSH-клиент (пример: добавить ключ) — используйте ключи.
- Если политика безопасности запрещает хранение каких-либо паролей на диске.
- Если система под управлением стороннего провайдера, где любая утилита, записывающая секреты, недопустима.
Пошаговый чеклист внедрения (Role-based)
Для разработчика/инженера:
- Оценить, можно ли заменить пароль на SSH-ключ.
- Создать зашифрованный файл .secret_vault.txt с OpenSSL или GPG.
- Настроить скрипт на безопасную расшифровку (использовать sshpass -f/-e или временный файл).
- Ограничить права доступа (директория 700, файлы 600).
- Удалять временные файлы и переменные сразу после использования.
Для администратора безопасности:
- Провести ревизию прав на каталог и файл.
- Настроить мониторинг доступа к файлу .secret_vault.txt.
- Внедрить процедуру ротации ключей/паролей.
План действий при компрометации
- Немедленно смените пароль удалённого аккаунта.
- Отозвите/переиздайте любые связанные учетные данные или ключи.
- Проведите анализ доступа: какие хосты/пользователи могли читать файл .secret_vault.txt или просмотреть процессы.
- Пересоздайте новый зашифрованный файл и обновите скрипты.
- Проверьте логи на предмет неавторизованных подключений.
Критерии приёмки
- Скрипт успешно подключается к удалённой системе автоматически.
- Зашифрованный файл хранится в скрытом файле с правами 600.
- Временные файлы и переменные среды очищаются сразу после использования.
- Отсутствие видимых паролей в логах и выводе ps во время нормальной работы.
- Документированы процедуры ротации и аварийного отклика.
Тестовые случаи
- Тест 1: Запуск скрипта при правильном пароле для расшифровки — в log должна появиться запись с меткой времени.
- Тест 2: Неправильный пароль для расшифровки — скрипт должен аварийно завершиться, не отправляя пустой пароль.
- Тест 3: Права доступа к .secret_vault.txt изменены на 644 — скрипт должен уведомить администратора о небезопасных правах.
- Тест 4: Смоделировать отказ доступа к удалённому хосту — скрипт должен выйти с понятной ошибкой и записать причину.
Риски и смягчающие меры (матрица)
- Риск: раскрытие пароля расшифровки — Смягчение: хранить пароль расшифровки в защищённой среде, не в репозитории.
- Риск: отображение пароля в ps при использовании -p — Смягчение: использовать -f или -e и временные файлы.
- Риск: компрометация локальной машины — Смягчение: мониторинг, обновления, защита доступа.
Короткая методология внедрения
- Оцените возможность использования SSH-ключей или менеджера секретов.
- Если необходима симметричная схема — зашифруйте пароль OpenSSL с PBKDF2 и солением.
- Храните шифротекст отдельно и с правами 600.
- В скрипте расшифровывайте пароль в памяти или в строго ограниченном временном файле и передавайте в SSH безопасным способом.
- Обеспечьте ротацию и логи аудита.
Заключение
Метод с OpenSSL и sshpass даёт практическую альтернативу прямому хранению паролей в скриптах: реальный пароль скрыт, а доступ к нему контролируется правами на файл и паролем для расшифровки. Это не заменяет полноценное управление секретами, но работает в сценариях, где невозможно изменить целевую систему или использовать SSH-ключи. Всегда оценивайте угрозы и выбирайте вариант, соответствующий вашей модели риска.
Важно: регулярно пересматривайте настройки безопасности и практики хранения секретов.
Краткое резюме:
- Храните зашифрованные пароли отдельно и ограничивайте доступ.
- Используйте PBKDF2 и современный алгоритм (AES-256) в OpenSSL.
- Избегайте передачи пароля через argv; используйте sshpass -f/-e с осторожностью.
- По возможности используйте SSH-ключи или менеджеры секретов.