Nascondere il segreto dal parametro della riga di comando su Unix

Ho uno script che lancia dentro di sé un comando con un parametro che è un segreto. Per esempio:

#!/bin/bash command-name secret 

Durante l’esecuzione del comando posso leggere attraverso ps -ef | grep command-name ps -ef | grep command-name che è il segreto.

C’è un modo per hide il segreto in un modo che attraverso ps -ef , il parametro della riga di comando viene offuscato?

Se il segreto non cambia tra le esecuzioni, usa uno speciale file di configurazione, ".appsecrets" . Imposta le autorizzazioni del file in sola lettura dal proprietario. All’interno del file viene impostata una variabile di ambiente per il segreto. Il file deve trovarsi nella directory home dell’utente che esegue il comando.

 #!/bin/bash #filename: .appsecrets set SECRET=polkalover 

Carica il file di configurazione in modo da impostare la variabile di ambiente.

 . ~/.appsecrets 

Quello che ho visto fatto:

1)
echo $SECRET | command

funziona se il comando richiede la password da stdin E se ‘echo’ è un builtin della shell. Stavamo usando Korn.

2)
password=$ENV{"SECRET"};

funziona se hai il controllo del codice (ad esempio in perl o C ++)

3)
. ./.app.config #sets the environment variables
isql -host [host] -user [user] -password < ${SQLPASSWORD}
SECRET

funziona se il comando può accettare il segreto da std-in. Una limitazione è che la stringa << deve essere l'ultimo argomento assegnato al comando. Questo potrebbe essere problematico se c'è un argomento non opzionale che deve apparire dopo -password

Il vantaggio di questo approccio è che puoi organizzarlo in modo che il segreto possa essere nascosto nella produzione. Utilizzare lo stesso nome file in produzione ma sarà nella directory home dell'account che esegue il comando in produzione. Puoi quindi bloccare l'accesso al segreto come se avessi accesso all'account di root. Solo alcune persone possono 'su' per l'account prod per visualizzare o mantenere il segreto mentre gli sviluppatori possono ancora eseguire il programma perché usano il proprio file '.appsecret' nella loro home directory.

È ansible utilizzare questo approccio per archiviare informazioni protette per qualsiasi numero di applicazioni, a condizione che utilizzino nomi di variabili di ambiente diversi per i loro segreti.

(STRADA SBAGLIATA)
Un vecchio metodo che ho visto utilizzare i DBA era impostare SYBASE su "/opt/././././././././././././././././././././././././././././././././././sybase/bin" . Quindi le loro linee di comando erano così lunghe che il ps l'ha troncato. Ma in Linux penso che potresti essere in grado di annusare l'intera linea di comando da / proc.

  1. Innanzitutto, NON puoi hide un argomento della riga di comando. È visibile tramite ps aux e cat /proc/$YOUR_PROCESS_PID/cmdline . La buona notizia è che puoi ancora avere un segreto usando le alternative:

  2. Usa le variabili d’ambiente. Se il tuo programma può leggerli, fai questo:

     mySecret='hello-neo' myCommand 
  3. Usa input standard:

     mySecret='hello-neo' printenv mySecret | myCommand 
  4. Usa il file temporaneo [descrittore]:

     myCommand <( mySecret='hello-neo' printenv mySecret ) 

Nell'ultimo caso il tuo programma verrà lanciato come myCommand /dev/fd/67 , dove il contenuto di /dev/fd/67 è il tuo segreto ( hello-neo in questo esempio).


In tutti gli approcci precedenti, ~/.bash_history attenzione a lasciare il comando nella cronologia dei comandi di bash ( ~/.bash_history ). Puoi evitarlo eseguendo il comando da uno script (file) o chiedendo ogni volta la password in modo interattivo:

  read mySecret myCommand # approach 2 printenv mySecret | myCommand # approach 3 myCommand <( printenv mySecret ) # approach 4 

L’unico modo per hide il tuo argomento segreto da ps non è quello di fornire il segreto come argomento. Un modo per farlo è posizionare il segreto in un file e redirect il descrittore di file 3 per leggere il file, e quindi rimuovere il file:

 echo secret > x.$$ command 3 

Non è del tutto chiaro che questo è un modo sicuro per salvare il segreto; il comando echo è un built-in di shell, quindi non dovrebbe apparire nell'output di 'ps' (e qualsiasi aspetto sarebbe fugace). Una volta tanto tempo fa, echo non era un built-in - anzi, su MacOS X, c'è ancora un /bin/echo anche se è un built-in per tutte le shell.

Ovviamente, questo presuppone che tu abbia l'origine da command e possa modificarlo per leggere il segreto da un descrittore di file pre-aperto anziché dall'argomento della riga di comando. Se non riesci a modificare il comando, sei completamente bloccato: l'elenco "ps" mostrerà le informazioni.

Un altro trucco che potresti ottenere se sei il proprietario del comando: puoi catturare l'argomento (segreto), scriverlo in una pipe o in un file (che è immediatamente scollegato) per te stesso, quindi rieseguire il comando senza l'argomento segreto; la seconda invocazione sa che dal momento che il segreto è assente, dovrebbe guardare ovunque la prima invocazione nascondesse il segreto. La seconda invocazione (meno il segreto) è ciò che appare nell'output di 'ps' dopo l'intervallo minimo necessario per hide il segreto. Non buono come avere il canale segreto istituito fin dall'inizio. Ma questi sono indicativi delle lunghezze a cui devi andare.

Zapping di un argomento dall'interno del programma - sovrascrittura con zeri, ad esempio - non nasconde l'argomento da 'ps'.

La libreria expect stata creata in parte per questo tipo di cose, quindi è ancora ansible fornire una password / altre informazioni sensibili a un processo senza doverlo passare come argomento. Supponendo che quando il “segreto” non viene dato, il programma lo richiede ovviamente.

L’ho visto su un altro post. Questo è il modo più semplice sotto Linux.

Questo modifica la parte di memoria della riga di comando che tutti gli altri programmi vedono.

 strncpy(argv[1], "randomtrash", strlen(argv[1])); 

Puoi anche cambiare il nome del processo, ma solo quando letto dalla riga di comando. Programmi come top mostreranno il vero nome del processo:

 strncpy(argv[0], "New process name", strlen(argv[0])); 

Non dimenticare di copiare i byte max strlen(argv[0]) perché probabilmente non c’è più spazio allocato.

Penso che gli argomenti possano essere trovati solo nella parte della memoria che modifichiamo quindi penso che funzioni come un incantesimo. Se qualcuno sa qualcosa di preciso su questo, si prega di commentare.

Nota di VasyaNovikov : la password può ancora essere intercettata dopo che il programma ha invocato, ma prima di iniziare a fare le modifiche che hai descritto.

Non c’è un modo semplice. Dai un’occhiata a questa domanda che ho chiesto qualche tempo fa:

Nascondi argomenti da ps

Comanda il tuo programma? Potresti provare a crittografare il segreto e farlo decrittare prima dell’uso.

Se lo script è progettato per essere eseguito manualmente, il modo migliore è leggerlo da STDIN

 #!/bin/bash read -s -p "Enter your secret: " secret command "$secret" 

potrebbe essere che tu possa fare così:

 #include  void hide(int argc, char** argv, std::string const & arg){ for(char** current = argv; current != argv+ argc ;++current){ if(boost::algorithm::starts_with(*current, "--"+arg)){ bzero(*current, strlen(*current)); } } } int main(int argc, char** argv){ hide(argc, argv, "password"); } 

È ansible utilizzare LD_PRELOAD per fare in modo che una libreria manipoli gli argomenti della riga di comando di alcuni binari all’interno del processo di quel file binario stesso, in cui ps non lo raccoglie. Vedi questa mia risposta su Server Fault per i dettagli.