Come passare una password a un processo figlio?


18

Passare una password dalla riga di comando (a un processo figlio avviato dal mio programma) è noto per essere insicuro (perché può essere visto anche da altri utenti con comando ps). Va bene invece passarlo come variabile d'ambiente?

Cos'altro posso usare per passarlo? (Tranne la variabile d'ambiente) la soluzione più semplice sembra usare una pipe, ma questa soluzione più semplice non è facile.

Io programma in Perl.


2
Perché non è facile? Non deve essere una pipe separata / denominata, solo lo stdin / out regolare farà ... che non dovrebbe essere troppo disturbo in nessuna lingua. Puoi metterlo in un semplice file di configurazione se puoi assicurarti che sia leggibile solo dai processi di interesse (che è molto più difficile di quanto sembri).
frostschutz,

1
Se non chiami exec nel figlio, hai ancora una copia della password senza dover fare nulla.
James Youngman,

Risposte:


26

Gli argomenti di processo sono visibili a tutti gli utenti, ma l'ambiente è visibile solo allo stesso utente ( almeno su Linux , e penso a ogni moderna variante unix). Quindi passare una password attraverso una variabile d'ambiente è sicuro. Se qualcuno può leggere le variabili di ambiente, può eseguire i processi come te, quindi il gioco è già finito.

Il contenuto dell'ambiente è a rischio di perdite indirette, ad esempio se si esegue psper indagare su qualcosa e si copia e si incolla accidentalmente il risultato, comprese le variabili di ambiente riservate in un luogo pubblico. Un altro rischio è che si passa la variabile di ambiente a un programma che non ne ha bisogno (compresi i figli del processo che richiede la password) e che il programma espone le sue variabili di ambiente perché non si aspettava che fossero riservate. Quanto sono gravi questi rischi di perdite secondarie dipende da cosa fa il processo con la password (per quanto tempo dura? Esegue sottoprocessi?).

È più facile garantire che la password non perda accidentalmente passandola attraverso un canale che non è progettato per essere intercettato, come una pipe. Questo è abbastanza facile da fare sul lato invio. Ad esempio, se hai la password in una variabile di shell, puoi semplicemente farlo

echo "$password" | theprogram

se si theprogramaspetta la password per il suo input standard. Si noti che questo è sicuro perché echoè incorporato; non sarebbe sicuro con un comando esterno poiché l'argomento verrebbe esposto in psoutput. Un altro modo per ottenere lo stesso effetto è con un documento qui:

theprogram <<EOF
$password
EOF

Ad alcuni programmi che richiedono una password può essere detto di leggerlo da un descrittore di file specifico. È possibile utilizzare un descrittore di file diverso dall'input standard se è necessario l'input standard per qualcos'altro. Ad esempio, con gpg:

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

Se non si può dire al programma di leggere da un descrittore di file ma si può dire di leggere da un file, si può dire di leggere da un descrittore di file usando un nome di file come `/ dev / fd / 3.

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

In ksh, bash o zsh, puoi farlo in modo più conciso attraverso la sostituzione del processo.

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

Su Solaris 9 e precedenti, /usr/ucb/psera setuid root in modo da poter leggere e visualizzare le variabili di ambiente di altri processi - questo è stato rimosso in Solaris 10, quindi la risposta "ogni altra variante Unix moderna" sopra si applica alle versioni di Solaris dal 2005 in poi.
alanc,

@alanc In effetti, al giorno d'oggi non considero Solaris <10 moderno. Solaris 9 è vecchio quasi quanto Windows XP!
Gilles 'SO- smetti di essere malvagio' il

Gilles: ci sono giorni in cui ho difficoltà a considerare Solaris 10 moderno ora che Solaris 11 è uscito da più di 5 anni, quindi capisco perfettamente e sono d'accordo, ma purtroppo alcune persone gestiscono ancora Solaris 8 o 9.
alanc

10

Invece di passare la password direttamente attraverso un argomento o una variabile di ambiente

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

utilizzare lo stesso argomento o la variabile di ambiente per passare un nome file :

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

Poi si può passare o un file regolare permesso protetto (anche se questo non vi proteggerà da altri processi in esecuzione sotto lo stesso utente), o /dev/stdine il tubo in (che AFAIK vi proteggerà da altri processi in esecuzione sotto lo stesso utente):

 echo PASSWORD | ./passwd_receiver /dev/stdin 

Se lo usi /dev/stdinqui, è indispensabile che sia una pipa . Se è un terminale, sarà leggibile da altri processi in esecuzione con lo stesso utente.

Se hai già bisogno di usare il tuo /dev/stdinper qualcos'altro, potresti usare la sostituzione di processo se sei su una shell che lo supporta, che è essenzialmente equivalente all'utilizzo di pipe:

./passwd_receiver <(echo PASSWORD)

Le pipe nominate (FIFO) potrebbero sembrare uguali, ma sono intercettabili.

Queste soluzioni non sono nemmeno perfettamente sicure , ma potrebbero essere abbastanza vicine a condizione che non ci si trovi in ​​un sistema con memoria limitata che scambia molto.

Idealmente, dovresti leggere questi file (pipe è anche un file) nella memoria contrassegnata con mlock (2) come non scambiabile, cosa che generalmente fanno i programmi di gestione delle password come gnupg.

Appunti:

  1. Passare i numeri dei filedescriptor è teoricamente buono come file che passa i nomi dei file, ma i nomi dei file sono più pratici, perché <()ti dà un nome di file, non un numero di filedescriptor (e coprocti danno i filedescriptors marcati FD_CLOEXEC , il che rende inutilizzabili quei filedescriptor in questo contesto).

  2. Se utilizzi un sistema Linux su cui
    /proc/sys/kernel/yama/ptrace_scopeè impostato 0, quindi AFAIK, non esiste un modo a prova di proiettile per proteggerti da altri processi in esecuzione con lo stesso utente (possono utilizzare ptrace per collegarsi al processo e leggere la memoria)

  3. Se hai solo bisogno di mantenere la tua password lontana dai processi in esecuzione con utenti diversi (non root), tutti gli argomenti, le variabili di ambiente, le pipe e i file protetti dalle autorizzazioni lo faranno.


7

No, anche le variabili di ambiente possono essere lette facilmente e vanno ai processi secondari. passarlo usando una pipa.


2
"variabili d'ambiente ... perdita nei processi figlio" Questo è il punto centrale dell'uso di una variabile d'ambiente. Sarebbero inutili se non fossero ereditati. "Anche le variabili d'ambiente possono essere lette facilmente", no, non lo sono.
Patrick,

2
Leggi la variabile, disattivalo. Non è difficile. E potresti usare lo stesso argomento sulla pipa. Se la pipe non viene letta, viene passata al processo figlio e il processo figlio potrebbe leggerlo e ottenere la password.
Patrick,

1
@Patrick I mezzi documentati delle variabili di ambiente disinserimento non necessariamente macchia il valore dalla posizione in cui pse /procpuò vederlo.
zwol,

1
Qualche sistema ti consente di leggere le variabili di ambiente di processi arbitrari? Non credo che Linux lo consenta per i processi di proprietà di altri, e se sei lo stesso utente puoi solo ptrace()il bersaglio e leggere la sua memoria comunque.
ilkkachu,

5
Questa risposta è sbagliata Le variabili di ambiente non possono essere lette da altri utenti.
Gilles 'SO- smetti di essere malvagio' il

1

Se non altro, considera il servizio Linux Key Retention (portachiavi del kernel).

Inizia da: security / keys.txt . Uno dei portachiavi predefiniti può essere clonato tra processi padre e figlio.

Non è la soluzione più semplice, ma è lì e sembra essere mantenuta e utilizzata (è stata anche implicata in un bug Android l'anno scorso.)

Non conosco il suo status "politico", ma avevo un bisogno simile e ho iniziato a lavorare su un legame Guile. Non ho trovato supporto Perl preesistente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.