Безпечний спосіб передачі пароля для> 1 програми в bash


21

Я пишу bashсценарій, і мені потрібно запитати у користувача його пароль і передати його openssl. Хоча я opensslможу прочитати сам пароль, мені потрібно два запуски програми, і я не хочу двічі запитувати користувача. Ось сценарій:

cp file{,.old}
read -sp 'Enter password. ' PASS; echo
export PASS

# decode | edit | encode
openssl enc -d -aes-256-cbc -k "$PASS" -in file.old | \
  sed ... | openssl enc -e -aes-256-cbc -k "$PASS" -out file

unset PASS

Це не безпечно, оскільки пароль легко доступний, переглядаючи командний рядок; хтось може прочитати це ps, наприклад.

opensslможе прочитати пароль з змінної оточення, так що я можу замінити -k "$PASS"з -pass env:PASS, але це по - , як і раніше небезпечно; змінні середовища будь-якого процесу можна читати вільно (знову ж, psможна це зробити).

Отже, як я можу безпечно передати пароль двом opensslекземплярам?


комбінацію GnuPG та PinEntry можна використовувати тут gnupg.org/related_software/pinentry/index.en.html
Nikhil Mulley

"змінні середовища будь-якого процесу можна читати вільно" - це не зовсім правильно. psзчитує середовище процесу з /proc/<pid>/environ, але цей файл має 0600дозволи, тому лише root та користувач, що керує процесом, мають змогу читати оточення процесу. Я б сказав, що це досить безпечно.
Мартін фон Віттіч

Відповіді:


16

Передайте пароль на окремий дескриптор файлу із вхідних даних (двічі, один раз для шифрування та один раз для розшифровки). Не експортуйте PASSв навколишнє середовище.

read -sp 'Enter password. ' PASS
printf '%s\n' "$PASS" |
openssl enc -d -aes-256-cbc -kfile /dev/stdin -in file.old |
sed ... | {
  printf '%s\n' "$PASS" |
  openssl enc -e -aes-256-cbc -kfile /dev/stdin -in /dev/fd/3 -out file;
} 3<&0

Якщо у вашій системі немає /dev/fd, ви можете використовувати -passаргумент, щоб сказати opensslчитати парольну фразу з відкритого дескриптора файлу.

printf '%s\n' "$PASS" | {
  printf '%s\n' "$PASS" |
  openssl enc -d -aes-256-cbc -pass fd:0 -in file.old |
  tr a-z A-Z | tee /dev/tty | {
  openssl enc -e -aes-256-cbc -pass fd:3 -out file; }
} 3<&0

Як я розумію з іншої вашої відповіді , у bashверсії з env:PASSбезпечно також.

printf '%s\n' "$PASS"не безпечно. Хтось може прочитати командний рядок, psнаприклад.

6
@ user14284 Ні, і ні. env:PASSне є безпечним, оскільки пароль з’явиться в середовищі opensslпроцесу (він не відображатиметься в середовищі bashпроцесу, але цього недостатньо). Використання printfбезпечно, тому що це вбудований баш.
Жиль "ТАК - перестань бути злим"

echo - це вбудований удар, тож чи не була б простою командою echo бути безпечною? echo $PASS | openssl .... Він не відображатиметься в списку ps. Єдине місце, куди ти можеш пройти, - це пам'ять процесора bash. Я думаю ?
gaoithe

1
@gaoithe Так, echoбуло б безпечно з тієї ж причини printfє безпечним (і printfне було б безпечним у оболонці, де він не вбудований). Причиною, яку я використовую, printfа ні, echoє те, що вони echoможуть заблукати зворотніми косою рисою (залежно від варіантів удару).
Жил "ТАК - перестань бути злим"

8

Використання Bash можна зробити без використання printf '%s\n' "$PASS", пов'язуючи так звану тут рядок з дескрипторами файлів за допомогою команди Bash вбудована exec.

Для отримання додаткової інформації див: Захист пароля скрипту параметрів командного рядка .

(

# sample code to edit password-protected file with openssl
# user should have to enter password only once
# password should not become visible using the ps command

echo hello > tmp.file

#env -i bash --norc   # clean up environment
set +o history
unset PASS || exit 1

read -sp 'Enter password. ' PASS; echo

# encrypt file and protect it by given password
exec 3<<<"$PASS"
openssl enc -e -aes-256-cbc -pass fd:3  -in tmp.file -out file

cp file{,.old}

# decode | edit | encode
exec 3<<<"$PASS" 4<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file.old | 
   sed 's/l/L/g' | 
   openssl enc -e -aes-256-cbc -pass fd:4 -out file

exec 3<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file

rm -P tmp.file file.old
unset PASS

)

1

Вибачте, моя попередня відповідь була від чоловіка openssl, а не документів openssl enc.

Це рішення не є конвеєрним, але я вважаю, що це рішення запобігає видимості пароля для ps.

Використовуючи тут документ, тільки openssl бачить текст пароля.
Поки ви впевнені в усуненні проміжного файлу, не залишається жодного сліду. Можливо, хтось може допомогти зробити це в конвеєрі та усунути проміжний файл?

# cp file{,.old}  don't need this anymore since intermediate becomes same
read -sp 'Enter password. ' PASS; echo
#no need to export, env's are readable, as mentioned

# decode into intermediate file
openssl <<HERE 2>&1 >/dev/null
enc -d -aes-256-cbc -k "$PASS" -in file -out intermediate
HERE

# edit intermediate

# encode intermediate back into file
openssl <<HERE 2>&1 >/dev/null
enc -e -aes-256-cbc -k "$PASS" -in intermediate -out file 
HERE
unset PASS
rm -f intermediate

Це було б кращою відповіддю, якби це пояснило, як користуватися перемикачем. Це не помиляється (за винятком того, що encкоманда не має -knкомутатора, принаймні у поточних версіях, це -pass), але не дуже інформативна. (Оцінка не моя.)
"SO- перестань бути злим"

Дякую @Gilles, подивився на документи і побачив мою помилку, оновлену відповідь з іншим підходом.
bsd
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.