У цій статті розбирається реальний випадок, коли звичайна команда SSH призвела до потенційного витоку доступів. Пояснюється, чому аргументи команд можуть бути небезпечними, де саме система «підсвічує» введені паролі та як сторонні процеси можуть їх побачити без злому сервера.
Коли можна щось спростити і пришвидшити, хтось часто жертвує безпеку за швидкість. Це особливо помітно в командах інфраструктури, бо їм щодня доводиться вирішувати проблеми на ходу. Та швидкість працює лише доки не з’являються паролі. Ми зіткнулися з випадком, який показав це ясно. На перший погляд це виглядає дрібницею, проте паролі могли привести до серйозних наслідків. Я бачив, як безпека відступає, коли швидкість стає головним.
Звичайний робочий день. Я переглядаю запущені процеси на сервері (використовуючи ps aux), коли раптом помічаю:
bash sshpass -p 'Qwerty123' ssh [email protected]
Це пароль, у відкритому вигляді, просто в командному рядку.
Тож я підходжу до колеги:
– «Слухай, а в чому тут магія?»
– «Ми зробили невеликий скрипт, щоб можна було швидко підключатися до віддаленого хоста і не вводити пароль щоразу».
– «Ти розумієш, що будь-який користувач, який може виконати команду ps на сервері, побачить цей пароль?»
– «Ну ми ж усередині мережі».
-«Доти, доки хтось перший не виконає ps, або доки це не потрапить у логи».
Через кілька годин вже була непланова перевірка. Перевірка відбулася без плану.
Передавання пароля як параметра команді – це антипатерн, який існує вже дуже давно.
Аргументи, передані команді, видно в ps, /proc/[PID]/cmdline, диспетчері завдань Windows тощо.
CI/CD-інструменти записують їх у логи. Системи моніторингу й аудиту теж записують їх у логи. CI/CD-інструменти і системи моніторингу й аудиту потрапляють у ці логи.
Я бачу, що багато інструментів, наприклад sshpass, plink, WinSCP CLI, rsync, mysql, curl, mRemoteNG, дозволяють передавати пароль у такий спосіб. Пароль у такому вигляді легко спокушає використати швидкий «хак».
У результаті пароль можна отримати, навіть жодного разу не взаємодіючи безпосередньо з SSH.
powershell
$insecureProcs = Get-CimInstance Win32_Process | Where-Object {
$_.CommandLine -match '\-p\s' -or $_.CommandLine -match '\-pw\s' -or $_.CommandLine -match '--password=' -or $_.CommandLine -match '/password='
} | Select-Object ProcessId, Name, CommandLine
$insecureProcs | Format-Table -AutoSize
bash
ps -eo pid,user,command --no-header | while read PID USER CMD; do
if [[ "$CMD" =~ -p ]] || [[ "$CMD" =~ -pw ]] || [[ "$CMD" =~ --password= ]] || [[ "$CMD" =~ /password= ]]; then
echo "PID=$PID USER=$USER CMD=$CMD"
fi
done
Виявилося, що ми запускали щоденне завдання резервного копіювання через cron із такою командою:
bash sshpass -p 'MySecret123' ssh [email protected]
На той момент на сервері працювали й інші користувачі, які запускали свої завдання. Пароль відображався в моніторі процесів.
Jenkins залишив ту ж команду в логах пайплайна, і їх бачили всі учасники проєкту. Я швидко змінив ключі, прибрав проблемні завдання і додав новий контроль.
Міні-довідник з уразливих інструментів
Linux – сканери Cron, Ansible, shell-скрипти.
Windows – PowerShell + логування.
CI/CD – лінтери та сканери (Checkov, KICS, Semgrep).
IDE – pre-commit хуки, які забороняють команди з паролями в аргументах.
Приклад правила Checkov:
yaml pattern: sshpass -p $PASS ... message: 'Пароль передається в командному рядку - це небезпечно.' severity: ERROR
Просто використовуй ssh-agent ключі в скриптах без пароля.
Тримайте секрети у Vault, у AWS Secrets Manager, у Ansible Vault. Секрети важливі.
Приховуйте облікові дані в .pgpass, .my.cnf, .netrc (права доступу 600).
Обмежте доступ. Лише root бачить процеси інших користувачів. Інші користувачі не бачать процеси інших користувачів.
Видаліть або обмежте небезпечні інструменти, наприклад sshpass.
Коли треба зберігати секрети в файлах, кодуй секрети в файлах.
Одна проста зміна могла викликати великий витік. Команда виявила проблему, виправила проблему, ввела часті перевірки, а наш колега перейшов на ключі.
Порада: проведіть перевірку своїх серверів уже сьогодні. Якщо десь паролі передаються через аргументи команд, негайно приберіть ці аргументи. Такі дрібні проблеми можуть коштувати значно дорожче, ніж п’ять хвилин налаштування.