Чи безпечно використовувати ехо для передачі чутливих даних у chpasswd?


17

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

Наївно, я би робив це так

{
  echo student1:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
  echo student2:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
} | tee >(chpasswd)

Однак я переживаю за те, щоб передати новий пароль як аргумент командного рядка echo, оскільки аргументи зазвичай видно іншим користувачам у ps -aux(хоча я ніколи не бачив, щоб жодна echoрядок відображалась у ps).

Чи є альтернативний спосіб попередньо задати значення моєму поверненому паролю та передати його в chpasswd?


6
echoце вбудована оболонка. Це не відображатиметься в таблиці процесів.
Кусалаланда

Відповіді:


15

Ваш код повинен бути безпечним, оскільки echoвін не відображатиметься в таблиці процесів, оскільки це вбудована оболонка.

Ось альтернативне рішення:

#!/bin/bash

n=20
paste -d : <( seq -f 'student%.0f' 1 "$n" ) \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

Це створює nз них імена та паролі учнів , не передаючи паролі в жодному командному рядку будь-якої команди.

У pasteпідсобному склеює кілька файлів в вигляді стовпців і вставляє роздільник в проміжку між ними. Тут ми використовуємо :як роздільник і надаємо йому два "файли" (підстановки процесу). Перший містить вихід seqкоманди, яка створює 20 імен користувачів учнів, а другий містить вихід конвеєра, який створює 20 випадкових рядків довжиною 13.

Якщо у вас є файл із вже створеними іменами користувачів:

#!/bin/bash

n=$(wc -l <usernames.txt)

paste -d : usernames.txt \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

Вони дозволять зберегти паролі та імена користувачів у файл, secret.txtа не відображати згенеровані паролі в терміналі.


2
Це розумне рішення, яке не потрібно echoабо printf, проте, код трохи незручно розшифрувати
Нілс Вернер

@NilsWerner Додано трохи більше пояснень. Дайте мені знати, чи є конкретна річ, яку ви хотіли б, щоб я розширив далі.
Kusalananda

1
Ви не повинні покладатися на echoте, що він побудований у корпусі. На більшості снарядів це є, але абсолютно немає вимоги, що це.
Остін Хеммельгарн

1
@Kusalananda Просто цікаво, чи є ефективна різниця між tee secret.txt > >(chpasswd)і tee secret.txt | chpasswd? Останнє здається набагато поширенішим, тому мені цікаво, чому ви вирішили використовувати заміну процесу замість простої труби
Крістофер Шроба

1
@ChristopherShroba Немає інших причин, ніж він подібний до коду, про який вже йшлося у запитанні (використовуючи заміну процесу на tee). Тепер, коли ви це вказали, я думаю, що я фактично його зміню (це виглядає краще). Спасибі.
Kusalananda

8

echoдуже ймовірно, вбудований в оболонку, тому він не відображатиметься psяк окремий процес.

Але вам не потрібно використовувати підстановку команд, ви можете просто отримати вихід з конвеєра безпосередньо на chpasswd:

{  printf "%s:" "$username";
   head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''
} | chpasswd 

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

genpws() {
    for user in "$@"; do
        printf "%s:" "$user";
        head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
        echo
    done
}
genpws username1 username2... | chpasswd 

Як осторонь: це head /dev/urandomздається дивним, оскільки urandomне орієнтоване на лінію. Він може прочитати надмірну кількість байт з нього, що вплине на уявлення ядра про доступну ентропію, що, в свою чергу, може призвести до /dev/randomблокування. Можливо, буде чистіше просто читати фіксовану кількість даних і використовувати щось на кшталт base64перетворення випадкових байтів у друковані символи (замість того, щоб просто відкинути приблизно 3/4 байтів, які ви отримаєте).

Щось подібне дало б вам бл. 16 символів і цифр:

head -c 12 /dev/urandom | base64 | tr -dc A-Za-z0-9 

(тобто на 16 менше кількості +та /символів на виході base64. Шанс того чи іншого становить 1/32 на символ, тож якщо я отримаю право на свою комбінаторику, це дає приблизно 99% шансу залишити принаймні 14 символів, і 99,99% шанс виїхати принаймні 12.)


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

@NilsWerner, ну, я хоч розширення для кількох користувачів очевидно. Але незалежно від того, ми могли б створити функцію створення імені користувача: паролів для декількох користувачів за один раз. (див. редагування)
ilkkachu

3
Ви дійсно не можете покластися на перші 10 "рядків" з урадону, що містять достатню кількість потрібних символів. Просто замість цього запустіть urandom безпосередньо через tr.
Кусалаланда

@Kusalananda, ти маєш на увазі мій head -c 10 | base64трубопровід чи Нілс head | tr? 10 "рядків" випадкових байтів, ймовірно, становлять сотні байтів (якщо врахувати, що лише 1 на 256 буде новим рядком), хоча теоретично це може бути рівно 10 байт, але шанси на це зовсім незначні. Аналогічно при використанні base64, якщо випадкові байти будуть сказані просто \xff, тоді base64 буде просто рядком косої риси, але це теж малоймовірно. Якщо вам все одно, ви можете прочитати більше 10 байт, зменшити шанси на це, а потім скоротити довжину отриманого результату.
ilkkachu

1
@ilkkachu Я маю на увазі обидва коди. Якщо ви читаєте випадкові байти і хочете щось певної довжини після фільтрації того, що не хочете, не відключайте джерело даних, поки не будете впевнені, що отримали те, що вам потрібно. Як ви кажете, навряд чи ви отримаєте рядок з десяти нових рядків /dev/urandom, але ризик не становить 0%.
Кусалаланда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.