Як передати пароль до дочірнього процесу?


18

Передача пароля в командному рядку (дочірньому процесу, розпочатому з моєї програми), як відомо, є небезпечним (тому що його можуть бачити навіть інші користувачі з командою ps). Чи правильно передавати це як змінну середовища?

Що ще я можу використати для передачі? (За винятком змінної середовища) найпростішим рішенням, здається, є використання труби, але це найпростіше рішення не з легких.

Я програмую в Perl.


2
Чому це непросто? Це не повинно бути окремою / названою трубою, просто регулярні stdin / out будуть робити ... це не повинно створювати особливих проблем на будь-якій мові. Ви можете помістити його у звичайний конфігураційний файл, якщо переконаєтесь, що його читають лише процеси, що цікавлять (що набагато важче, ніж це звучить).
frostschutz

1
Якщо ви не зателефонували до програми exec у дитини, у вас все ще є копія пароля, не вимагаючи нічого робити.
Джеймс Янгмен

Відповіді:


26

Аргументи процесу видно всім користувачам, але середовище видно лише тому ж користувачеві ( принаймні, в Linux , і я думаю, що у кожному сучасному варіанті Unix). Тому передача пароля через змінну середовища безпечна. Якщо хтось може прочитати ваші змінні середовища, він може виконувати процеси, як ви, тож це вже гра.

Вміст навколишнього середовища є певним ризиком непрямого протікання, наприклад, якщо ви psхочете щось розслідувати і випадково скопіювати і вставити результат, включаючи конфіденційні змінні середовища в публічному місці. Інший ризик полягає в тому, що ви передаєте змінну оточення програмі, яка їй не потрібна (включаючи дітей процесу, який потребує пароля), і ця програма відкриває свої змінні середовища, оскільки не очікувала їх конфіденційності. Наскільки погані ці ризики вторинного витоку, залежить від того, що робить процес із паролем (як довго він працює? Чи запускається підпроцес?).

Простіше переконатися, що пароль не просочиться випадково, передаючи його через канал, який не призначений для підслуховування, наприклад, труба. Це досить легко зробити з боку відправки. Наприклад, якщо у вас є пароль у змінній оболонки, ви можете просто зробити

echo "$password" | theprogram

якщо theprogramочікує пароля на його стандартному вході. Зауважте, що це безпечно, оскільки echoце вбудований; це не було б безпечно із зовнішньою командою, оскільки аргумент буде викритий у psвиході. Ще один спосіб досягти такого ж ефекту - це документ тут:

theprogram <<EOF
$password
EOF

Деякі програми, яким потрібен пароль, можуть сказати, щоб прочитати його з певного дескриптора файлу. Ви можете використовувати дескриптор файлу, який не є стандартним входом, якщо вам потрібно стандартне введення для чогось іншого. Наприклад, за допомогою gpg:

get-encrypted-data | gpg --passphrase-fd 3 --decrypt … 3<<EOP >decrypted-data
$password
EOP

Якщо програмі не можна сказати читати з дескриптора файлу, але її можна сказати читати з файлу, ви можете сказати, що вона читає з дескриптора файлу, використовуючи ім'я файлу типу `/ dev / fd / 3.

theprogram --password-from-file=/dev/fd/3 3<<EOF
$password
EOF

У ksh, bash або zsh ви можете це зробити більш стисло, шляхом заміни процесу.

theprogram --password-from-file=<(echo "$password")

У програмі Solaris 9 та /usr/ucb/psпізніших версіях був встановлений корінь, тому він міг читати та відображати змінні середовища інших процесів - це було видалено в Solaris 10, тому відповідь "кожен інший сучасний варіант Unix" вище стосується випусків Solaris з 2005 року та пізніше.
alanc

@alanc Дійсно, я не вважаю Solaris <10 сучасним. Solaris 9 майже така ж стара, як Windows XP!
Жил "ТАК - перестань бути злим"

Джилз: є дні, коли я важко розглядаю "Соляріс 10" сучасного, коли Соляріс 11 вийшов більше 5 років, тому я цілком розумію і погоджуюся, але, на жаль, знаю, що деякі люди все ще керують "
Солярісом

10

Замість передачі пароля безпосередньо через аргумент або змінну середовища

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $1"

використовувати той самий аргумент або змінну середовища, щоб передати ім'я файлу :

#!/bin/bash
#filename: passwd_receiver
echo "The password is: $(< "$1")"

Потім ви можете передати або дозвіл захищеного звичайного файлу (хоча це не захистить вас від інших процесів , що працюють під тим же користувачем), або /dev/stdinі труба його в (який AFAIK захистить вас від інших процесів , запущених під тим же користувачем):

 echo PASSWORD | ./passwd_receiver /dev/stdin 

Якщо ви /dev/stdinтут використовуєте , то обов’язково це труба . Якщо це термінал, його можна читати іншими процесами, що працюють під тим самим користувачем.

Якщо вам вже потрібно використовувати своє /dev/stdinдля чогось іншого, ви можете використовувати підстановку процесу, якщо ви знаходитесь на оболонці, яка його підтримує, що по суті еквівалентно використанню труб:

./passwd_receiver <(echo PASSWORD)

Названі труби (FIFO) можуть виглядати так, як вони однакові, але вони перехоплюючі.

Ці рішення також не є абсолютно безпечними , але вони можуть бути досить близькими за умови, що ви не в системі з обмеженою пам’яттю, яка сильно обмінюється.

В ідеалі, ви б прочитали ці файли (труба теж файл) у пам'яті, позначеній mlock (2), як незамінювану, що зазвичай роблять такі програми обробки паролів, як gnupg.

Примітки:

  1. Передача номерів fileescriptor теоретично так само добре, як і файл, як передача імен файлів, але імена файлів є більш практичними, оскільки <()дає вам ім’я файлу, а не номер fileescriptor (і coprocs дає вам файли-сценарії з позначкою FD_CLOEXEC , що робить ці файлописники непридатними в цьому контексті).

  2. Якщо ви працюєте в системі Linux, де
    /proc/sys/kernel/yama/ptrace_scopeвстановлено налаштування 0, тоді AFAIK, немає захисного способу захисту від інших процесів, що працюють під тим самим користувачем (вони можуть використовувати ptrace для приєднання до вашого процесу та читання вашої пам'яті)

  3. Якщо вам потрібно лише не захищати свій пароль від процесів, що працюють під різними користувачами (non-root), тоді це будуть робити аргументи, змінні середовища, файли та файли, захищені дозволом.


7

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


2
"змінні середовища ... просочуються до дочірніх процесів" У цьому вся суть використання змінної середовища. Вони були б марними, якби не успадкували їх. "змінні середовища теж легко читаються", ні вони не є.
Патрік

2
Прочитайте змінну, скасуйте її. Це не важко. І ти міг би використати той же аргумент щодо труби. Якщо труба не зчитується, вона передається дочірньому процесу, і дочірній процес може її прочитати та отримати пароль.
Патрік

1
@Patrick Документально кошти невстановленого змінних оточення не обов'язково вичистити значення від місця , де psі /procможна побачити.
zwol

1
Чи дозволяє якась система читати змінні середовища довільних процесів? Я не думаю, що Linux дозволяє це для процесів, які належать іншим, і якщо ви той самий користувач, ви можете просто ptrace()націлити ціль і прочитати пам'ять.
ilkkachu

5
Ця відповідь неправильна. Змінні середовища не можуть читати інші користувачі.
Жил "ТАК - перестань бути злим"

1

Якщо нічого іншого не підходить, розгляньте службу збереження ключів Linux (брелоки ядра).

Почніть з: security / keys.txt . Один з брелоків за замовчуванням може бути клонований між процесами батьків та дітей.

Це не найпростіше рішення, але воно є і, здається, підтримується та використовується (воно також було пов'язане з помилкою Android минулого року.)

Я не знаю про його "політичний" статус, але в мене була схожа потреба, і я почав працювати над прив'язкою до Guile. Я не натрапив на попередню підтримку Perl.

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