Bir kullanıcı için parola bash üzerinde bir programın stdin parçası olmak için en güvenli ve en basit yolu nedir?


12

Bir kullanıcı bir bash kabuk isteminde bir parola yazın ve bu parola bir programa stdin parçası olmak için (1) en güvenli ve (2) en basit yolu arıyorum.

Bu Stdin ihtiyaçları gibi görünmek için ne: {"username":"myname","password":"<my-password>"}nerede <my-password>neydi istemi kabuğu içine yazılan edilir. Eğer stdin programı üzerinde kontrol sahibi olsaydım, o zaman güvenli bir şifre istemek ve yerine koymak için değiştirebilirdim, ancak aşağı akış standart bir genel amaçlı komuttur.

Aşağıdakileri kullanan yaklaşımları düşündüm ve reddettim:

  • şifreyi komut satırına yazan kullanıcı: şifre ekranda gösterilir ve "ps" ile tüm kullanıcılar tarafından görülebilir
  • kabuk değişkeni harici bir programın argümanına enterpolasyonu (örn. ...$PASSWORD...): şifre hala "ps" ile tüm kullanıcılar tarafından görülebilir
  • ortam değişkenleri (çevrede kalırlarsa): parola tüm alt işlemler tarafından görülebilir; güvenilir süreçler bile, bir tanılamanın parçası olarak çekirdek değişkenleri veya ortam değişkenlerini dökerse şifreyi ortaya çıkarabilir
  • bir dosyada uzun süre oturan şifre, sıkı izinlere sahip bir dosya bile: kullanıcı yanlışlıkla şifreyi açığa çıkarabilir ve kök kullanıcı yanlışlıkla şifreyi görebilir

Mevcut çözümümü aşağıda bir cevap olarak koyacağım, ancak birisi bir cevap bulursa daha iyi bir cevap seçeceğim. Daha basit bir şey olması gerektiğini düşünüyorum, ya da belki birileri kaçırdığım bir güvenlik endişesi görür.


(Tam kullanım durumu şifrenin bir HTTPS sunucusuna POST gövdesinin bir parçası olması gerektiğidir, ancak bu soruyu aşırı derecede özel yapmak istemiyorum. Stdin curl ile POST gövdesi olacak "-d @ - ".)
Jim Hoagland

Yanıtlar:


14

İle bashya zsh:

unset -v password # make sure it's not exported
set +o allexport  # make sure variables are not automatically exported
IFS= read -rs password < /dev/tty &&
  printf '{"username":"myname","password":"%s"}\n' "$password" | cmd

Olmadan IFS=, readyazdığınız paroladaki önde gelen ve sondaki boşlukları çıkarırdı.

Olmadan -r, ters eğik çizgileri tırnak işareti olarak işleyecekti.

Sadece terminalden okuduğunuzdan emin olmak istiyorsunuz.

echogüvenilir bir şekilde kullanılamaz. In bashve zsh, printfyerleşiktir, böylece komut satırının çıktısında gösterilmez ps.

İçinde bash, $passwordaksi takdirde split + glob operatörü uygulandığından alıntı yapmanız gerekir .

Bu dizeyi JSON olarak kodlamanız gerektiğinden, bu yine de yanlıştır. Örneğin, çift tırnak ve ters eğik çizgi en azından bir sorun olabilir. Muhtemelen bu karakterlerin kodlanması konusunda endişelenmeniz gerekir. Programınız UTF-8 dizeleri bekliyor mu? Terminaliniz ne gönderiyor?

Şunları içeren bir bilgi istemi dizesi eklemek için zsh:

IFS= read -rs 'password?Please enter a password: '

İle bash:

IFS= read -rsp 'Please enter a password: ' password

printf - perl invokasyonunu önlemek için ihtiyacımız olan şey bu - iyi bir ipucu. Eğer sahip olduğu iyidir unset passwordve set +ageçerli kabuğu hakkında daha fazla varsayımlar yapabilirsiniz eğer atlanabilir olsa orada. IFS=Çeşitli şifreler ile daha iyi genellik için okuma ve önündeki -r seçeneği hakkında iyi bir nokta . Terminalden girişi zorlamak için / dev / tty'den gitmek iyidir.
Jim Hoagland

1
evet, hala çift-alıntı ve ters eğik çizgi ile ilgili bir sorun var ve belki birkaç karakter. JSON blobundaki çift tırnaklı alanın içine koymadan önce bunları kodlamamız gerekir. Kıvrılmanın UTF-8 beklediğinden emin değilim.
Jim Hoagland

1
python3 -c 'import json; print(json.dumps({"username": "myname", "password": input()}))', etrafta Python varsa. Python 2 için, s / input / raw_input /. Parolayı bu komuta bağlarsanız, uygun JSON tükürür.
Kevin

Kevin, şifreyi stdin'e güvenli bir şekilde alabilirsek ve python'u çağırmayı umursamazsak iyi bir öneri olur. Bu, JSON'u anında oluşturur. Saklanan parolayı tekrar tekrar kullanmaya devam edememekle birlikte, Python içinde getpass.getpass () kullanılırsa bu iyi çalışır.
Jim Hoagland

2

İşte sahip olduğum çözüm (test edildi):

$ read -s PASSWORD
<user types password>
$ echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"'

Açıklama:

  1. read -ssatırı ekrana yansıtmadan bir stdin (şifre) satırı okur. Depolar PASSWORD kabuk değişkenindedir.
  2. echo -n $PASSWORDşifreyi yeni satır olmadan stdout'a koyar. (echo bir kabuk yerleşik komutudur, bu nedenle yeni bir işlem oluşturulmadığından (AFAIK) echo argümanı olarak şifre ps'de gösterilmez.)
  3. perl çağrılır ve stdin'den $_
  4. perl parolayı $_tam metne yerleştirir ve stdout'a yazdırır

Bu bir HTTPS POST'a gidecekse, ikinci satır şöyle olacaktır:

echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"' | curl -H "Content-Type: application/json" -d@- -X POST <url-to-post-to>

3
Bu oldukça iyi görünüyor. Sadece perl'i çağırmak için hiçbir neden olmadığını not edeceğim; printf '{"username":"myname","password":"%s"}' $PASSWORDaynı güvenlik özelliklerini koruyan ve size harici bir işlem kaydeden mükemmel bir şey yapabilirsiniz .
Tom Hunt

2
Çözümü read-s bayrağını desteklemeyen komutlar için genelleştirmek isterseniz, "stty -echo; PASSWORD okuyun; stty echo" kullanabilirsiniz
Jeff Schaller

2
Boru, her iki taraf için bir tane olmak üzere iki yeni işlem başlatır. Yerine burada-dize kullanın: perl -e '...' <<< "$PASSWORD".
chepner

2
@chepner, <<<in bashiçeriği daha kötü olan geçici bir dosyada saklar.
Stéphane Chazelas

1
TLDP'ye göre bir dosya oluşturur, ancak diğer işlemler tarafından okunamaz. "Burada belgeler geçici dosyalar oluşturur, ancak bu dosyalar açıldıktan sonra silinir ve diğer işlemlere erişilemez." tldp.org/LDP/abs/html/here-docs.html Örnek 19-12'den hemen sonra.
dragon788

0

Sürümünüz readdesteklenmiyorsa -s, bu yanıtta görülen POSIX uyumlu yolu deneyin .

echo -n "USERNAME: "; read uname
echo -n "PASSWORD: "; set +a; stty -echo; read passwd; command <<<"$passwd"; set -a; stty echo; echo
passwd= # get rid of passwd possibly only necessary if running outside of a script

set +aÇevre için bir değişkenin auto "ihracat" önlemek gerekiyordu. Man sayfalarını kontrol etmelisiniz stty, birçok seçenek var. <<<"$passwd"İyi şifreleri boşluk çünkü alıntılanmıştır. Geçen echoetkinleştirdikten sonra stty echoyeni bir satıra sonraki komut / çıkış başlangıç sahip olmaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.