Чи є спосіб передачі конфіденційних даних у bash за допомогою підказки для будь-якої команди?


40

Припустимо, що я використовував sha1passдля генерування хеша чутливого пароля в командному рядку. Я можу використовувати sha1pass mysecretдля створення хешу, mysecretале це має той недолік, який mysecretзараз є в історії башів. Чи є спосіб досягти кінцевої мети цієї команди, уникаючи виявлення mysecretу простому тексті, можливо, використовуючи passwdпідказку -style?

Мене також цікавить узагальнений спосіб зробити це для передачі конфіденційних даних будь-якій команді. Метод зміниться, коли конфіденційні дані передаються як аргумент (наприклад, в sha1pass) або STDIN до якоїсь команди.

Чи є спосіб досягти цього?


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

  • Відповідно до відповіді @ Kusalananda , в ідеалі ніколи не доведеться вводити пароль або секрет як аргумент командного рядка для утиліти. Це є вразливим декількома способами, як описано ним, і слід використовувати краще розроблену утиліту, яка здатна приймати секретний вклад на STDIN
  • @ vfbsilva відповідь описує, як запобігти збереженню речей у історії баш
  • @ Відповідь Джонатана описує ідеально хороший спосіб досягти цього, доки програма може приймати свої секретні дані про STDIN. Як такий, я вирішив прийняти цю відповідь. sha1passв моєму ОП був лише прикладом, але дискусія встановила, що існують кращі інструменти, які беруть дані про STDIN.
  • як зазначає @R .. у своїй відповіді , використання розширення команд на змінній не є безпечним.

Отже, підводячи підсумок, я прийняв відповідь @ Джонатана, оскільки це найкраще рішення, враховуючи, що у вас є добре розроблена і добре сприйнята програма, з якою можна працювати. Хоча передача пароля або секрету як аргументу командного рядка принципово небезпечна, інші відповіді пропонують способи пом'якшення простих проблем безпеки.


6
Мало того: кожен на одній машині з дозволом перераховувати запущені процеси потенційно може бачити, що sha1pass mysecretпрацює, і, отже, знати, що mysecretтаке. (Це працює лише протягом кількох секунд, поки програма насправді працює, звичайно ...)
MathematicalOrchid

@MathematicalOrchid Цього можна уникнути, працюючи в приватній віртуальній машині. Але це може бути занадто великою роботою, щоб створити лише один пароль ... :-)
Kusalananda

5
@Kusalananda Моя думка полягала в тому, що "ніколи не кладіть конфіденційні дані в командний рядок, навіть якщо ви з'ясуєте, як вимкнути історію команд" ...
MathematicalOrchid

2
Так що ви знаєте, SHA-1 застарілий для хешування ключів або паролів уже доволі багато років.
Девід Фоерстер

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

Відповіді:


20

Якщо ви використовуєте zshабо bashshell, використовуйте параметр -s для readвбудованої оболонки, щоб прочитати рядок з термінального пристрою, не повторюючи його.

IFS= read -rs VARIABLE < /dev/tty

Тоді ви можете скористатися певним перенаправленням, щоб використовувати змінну як stdin.

sha1pass <<<"$VARIABLE"

Якщо хтось біжить ps, все, що вони побачать, - це "sha1pass".

Це передбачає, що sha1passчитає пароль зі stdin (на одному рядку, ігноруючи роздільник рядка), коли не задано жодного аргументу.


Я вважаю, що ми встановили, що sha1passне використовує стандартний потік введення.
Kusalananda

@Kusalananda Добре, але цей метод буде працювати для програм, які читають зі stdin.
Джонатан

Отже, якщо припустити, що утиліта може взяти таємний внесок на STDIN, це надійне і безпечне рішення, безпечне?
cemulate

Я вирішив прийняти цю відповідь, враховуючи, що це найкраще рішення, враховуючи, що у вас є добре розроблена програма, з якою ви працюєте. sha1passбув лише прикладом у моїй ОП, і явно не найкращим вибором для цього.
cemulate

1
@cemulate, ... не безпечно в командному рядку . У контексті гередока чи герестрингу (як у відповіді тут) він не піддається впливу ps, але може бути записаний у тимчасовий файл - якщо хтось хоче цього уникнути, то sshpass < <(printf '%s\n' "$VARIABLE")може бути розглянутий (бо printfце вбудований, а не зовнішня команда, вона не передається execvі доступ через неї ps).
Чарльз Даффі

35

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

Сказавши це, безумовно, є способи приховання фактичного пароля від історії команд оболонки.

sha1pass "$( head -n 1 )"

Потім введіть пароль і натисніть Enter. headКоманда , яка використовується тут приймає рівно один рядок введення і останній символ нового рядка , що ви типу не буде частиною даних , який передається sha1pass.

Щоб запобігти відлуння символів:

sha1pass "$( stty -echo; head -n 1; stty echo )"

У stty -echoкоманді відключає відлуння з надрукованих символів на терміналі. Потім відлуння відновлюється за допомогою stty echo.

Для передачі стандартного вводу ця остання команда може бути змінена (ви б це зробили, якби sha1passприйняті дані на стандартному вході, але виглядає так, ніби ця конкретна утиліта ігнорує її стандартний ввід):

{ stty -echo; head -n 1; stty echo; } | somecommand

Якщо вам потрібно багаторядкове введення (вище припускається, що один рядок повинен бути переданий, без символу нового рядка в кінці), тоді замініть всю headкоманду на catі somecommandзавершіть введення (припускаючи, що він читає до кінця файлу) на Ctrl+D( наступне, Returnякщо ви хочете включити символ нового рядка у вхід, або двічі, якщо ні).

Це буде працювати незалежно від оболонки, яку ви використовували (доки це була оболонка, подібна до Bourne або rc).

Деякі оболонки можуть бути зроблені так, щоб не зберігати введені команди у своїх файлах історії, якщо команді передує пробіл. Зазвичай це означає, що потрібно встановити HISTCONTROLзначення ignorespace. Це підтримується принаймні bashта kshна OpenBSD, але не, наприклад, ksh93або dash. zshкористувачі можуть використовувати histignorespaceпараметр або їх HISTORY_IGNOREзмінну для визначення шаблону, який слід ігнорувати.

У оболонках, які підтримують читання, readбез повторення символів до терміналу, ви також можете використовувати

IFS= read -rs password     # -s turns off echoing in bash or zsh
                           # -r for reading backslashes as-is,
                           # IFS= to preserve leading and trailing blanks
sha1pass "$password"

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

Якщо утиліта читає зі стандартного вводу та якщо оболонка підтримує "тут-рядки", вищезазначене може бути змінено на

IFS= read -rs password
somecommand <<<"$password"

Короткий зміст коментарів нижче:

  • Виконання команди з паролем, вказаним у командному рядку, що виконує всі наведені вище команди, крім тієї, яка передає дані команді, потенційно зробить пароль видимим для всіх, хто працює psодночасно. Однак жодна з наведених вище команд не збереже введений пароль у файл історії оболонки, якщо виконаний з інтерактивної оболонки.

  • Добре поводиться програми, які читають паролі з чітким текстом, роблять це, читаючи зі свого стандартного вводу, з файлу або безпосередньо з терміналу.

  • sha1pass дійсно вимагає пароль в командному рядку, або вводиться безпосередньо, або використовуючи якусь форму підстановки команд.

  • Якщо це взагалі можливо, використовуйте інший інструмент.


11
Це неправильно. Результат розширення команди $(...)буде частиною командного рядка і видно у psвисновку, за винятком системи із загартованим / процесом.
Р ..

3
@Kusalananda, навіть перезапис аргументу після того, як ви почали, залишає вразливе вікно до того, як відбудеться перезапис; це пом'якшення, а не виправлення.
Чарльз Даффі

5
@Kusalananda, жодна добре розроблена програма для хешування паролів не потребуватиме введення в командному рядку, так що умовне в основному є заданим - якщо це не так , слід вибрати інший інструмент.
Чарльз Даффі

4
@CharlesDuffy: Інструмент тут здається принципово зламаним. sha1passзапуск без пароля в командному рядку, здається, дає результат, не читаючи нічого ... Тому OP потрібно вибрати інший інструмент.
Р ..

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

25

Якщо ви встановите HISTCONTROLтак:

HISTCONTROL=ignorespace

і запустіть команду з пробілу:

~$  mycommand

він не зберігатиметься в історії.


10

Передайте конфіденційні дані через трубку або тут:

command_with_secret_output | command_with_secret_input

або:

command_with_secret_input <<EOF
$secret
EOF

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

Як зазначив Кусалаланда в коментарі, якщо ви вводите команди в інтерактивну оболонку, рядки, які ви вводите для документа тут, будуть зберігатися в історії оболонки, тому вводити там пароль не безпечно, але все одно він повинен бути безпечні для використання змінні оболонки, що містять секрети; історія буде містити текст, $secretа не те, що $secretрозширено на.

Використання розширень команд не є безпечним :

command_with_secret_input "$(command_with_secret_output)"

тому що вихід буде включений у командний рядок і буде видно у psвисновку (або вручну читання з / proc), за винятком систем із загартованим / proc.

Призначення змінної теж добре:

secret=$(command_with_secret_output)

Що я шукаю - це фактична команда, command_with_secret_outputяка дозволяє мені набрати секретний вихід. Чи існує така команда, яку можна замінити тут?
cemulate

Зауважте, що введення документа тут у інтерактивному bash сеансі збереже документ у файлі історії.
Кусалаланда

@cemulate: просто використовуйте вбудовану оболонку read, наприклад read -r secret. Тоді ваш секрет $secret. Ви можете запустити stty до / після нього, щоб приховати вхід, якщо хочете.
Р ..

3
@Kusalananda: sha1passздається принципово зламаним / непридатним / небезпечним, оскільки він не може прочитати пароль із stdin чи файлу. Я думаю, що для вирішення проблеми потрібна інша утиліта.
Р ..

1
@cemulate Ваш останній коментар до R саме на місці. Ось чому це не допоможе. read -rsзробить цю роботу (якщо ви включите -rможливість мати паролі з косою косою рисою), але потім ви знову зможете демонструвати пароль у списку процесів (і залежно від того, включений обліковий запис процесу та як це налаштовано , а також у журналах обліку процесів).
Kusalananda

6

Просто запишіть значення у файл та передайте файл:

$ cat > mysecret
Big seecreeeet!
$ cat mysecret | sha1pass 

Я не впевнений, як це sha1passпрацює, якщо він може приймати файл як вхід, ви можете використовувати sha1pass < mysecret. Якщо ні, використання catможе бути проблемою, оскільки воно включає остаточний новий рядок. Якщо це так, використовуйте (якщо headпідтримуєте -c):

head -c-1 mysecret | sha1pass 

2
Навіщо писати пароль на диск у своєму першому прикладі, коли ви просто можете це зробити cat | sha1pass? cat mysecret | sha1passі sha1pass < mysecretмають таку саму поведінку стосовно останніх рядків. catне додає нові рядки. У будь-якому випадку, якщо sha1passпідтримується передача пароля через стандартний ввід, я би сподівався, що він ігнорує остаточний новий рядок сам. Файли з рядками, які не закінчуються новими рядками, є неприродними в unix, тому було б незручно очікувати, що файл не закінчується новим рядком.
JoL

@JoL i) тому що я не думав про це: / Але як би це діяло? cat | sha1passздається, працює sha1passперед тим, як дати мені можливість ввести будь-які дані. ii) Ні, звичайно cat mysecret, не додається новий рядок, я ніколи не сказав, що catдодає його, тільки що він включає його.
тердон

Я бачу, але це не так, як < mysecretвидаляє. :)
JoL

Не звертай уваги. Тепер, коли я перечитав, я бачу, що ви сказали це, щоб пізніше запропонувати head -c-1. Я думаю, що я просто заплутався, чому користуватися, cat mysecret | sha1passа потім пропоную sha1pass < mysecret. Я думаю, що турбує те, що sha1pass може скаржитися на регулярні файли для stdin; Я не впевнений, чому.
JoL

@JoL це більше , тому що я ніколи не використовував sha1passі не зміг знайти керівництво або -hабо будь-яку іншу форму документації в протягом декількох хвилин я провів пошук і тому не міг зрозуміти, якщо працює sha1pass fooлікування в fooякості вхідного рядка або в якості вхідного файлу . Тому я дав варіанти розібратися з кожною можливістю.
terdon

1

Якщо те, що зробив тердон, можливо, то це найкраще рішення, пройшовши стандартний ввід. Єдина проблема, яка залишилася - він записав пароль на диск. Ми можемо зробити це замість цього:

stty -echo
echo -n "password: "
head -1 | sha1pass
stty echo

Як сказав Кусалаланда, stty -echoте, що ви вводите, не бачиться, поки ви не зробите це stty echoзнову. head -1отримає один рядок зі стандартного вводу та передасть його на sha1pass.


0

Я б користувався

sha1pass "$(cat)"

catбуде читати від stdin до EOF, що може бути викликано натисканням клавіш Ctrl + D. Потім результат буде переданий як аргументsha1pass


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