GNU/Linux >> Linux Esercitazione >  >> Linux

Come nascondere una password passata come argomento della riga di comando?

Soluzione 1:

Davvero, questo dovrebbe essere risolto nell'applicazione stessa. E tali applicazioni dovrebbero essere open source, quindi la risoluzione del problema nell'app stessa dovrebbe essere un'opzione. Un'applicazione correlata alla sicurezza che commette questo tipo di errore potrebbe commettere anche altri errori, quindi non mi fiderei.

Semplice interposer

Ma stavi chiedendo un modo diverso, quindi eccone uno:

#define _GNU_SOURCE
#include <dlfcn.h>

int __libc_start_main(
    int (*main) (int, char * *, char * *),
    int argc, char * * ubp_av,
    void (*init) (void),
    void (*fini) (void),
    void (*rtld_fini) (void),
    void (* stack_end)
  )
{
  int (*next)(
    int (*main) (int, char * *, char * *),
    int argc, char * * ubp_av,
    void (*init) (void),
    void (*fini) (void),
    void (*rtld_fini) (void),
    void (* stack_end)
  ) = dlsym(RTLD_NEXT, "__libc_start_main");
  ubp_av[argc - 1] = "secret password";
  return next(main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}

Compilalo con

gcc -O2 -fPIC -shared -o injectpassword.so injectpassword.c -ldl

quindi esegui il tuo processo con

LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start fakepasshrase

La libreria interposer eseguirà questo codice prima del main funzione dall'applicazione viene eseguita. Sostituirà l'ultimo argomento della riga di comando con la password effettiva nella chiamata a main. La riga di comando come stampata in /proc/*/cmdline (e quindi visto da strumenti come ps ) conterrà comunque l'argomento falso. Ovviamente dovresti rendere il codice sorgente e la libreria che compili da esso leggibili solo a te stesso, quindi è meglio operare in un chmod 0700 directory. E poiché la password non fa parte dell'invocazione del comando, anche la tua cronologia bash è al sicuro.

Interposer più avanzato

Se vuoi fare qualcosa di più elaborato, tieni presente che __libc_start_main viene eseguito prima che la libreria di runtime sia stata correttamente inizializzata. Quindi suggerirei di evitare qualsiasi chiamata di funzione a meno che non sia assolutamente essenziale. Se vuoi essere in grado di chiamare le funzioni a tuo piacimento, assicurati di farlo appena prima del main stesso viene richiamato, dopo che tutta l'inizializzazione è stata eseguita. Per il seguente esempio devo ringraziare Grubermensch che mi ha fatto notare come nascondere una password passata come argomento della riga di comando che riportava getpass alla mia attenzione.

#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>

static int (*real_main) (int, char * *, char * *);

static int my_main(int argc, char * * argv, char * * env) {
  char *pass = getpass(argv[argc - 1]);
  if (pass == NULL) return 1;
  argv[argc - 1] = pass;
  return real_main(argc, argv, env);
}

int __libc_start_main(
    int (*main) (int, char * *, char * *),
    int argc, char * * ubp_av,
    void (*init) (void),
    void (*fini) (void),
    void (*rtld_fini) (void),
    void (* stack_end)
  )
{
  int (*next)(
    int (*main) (int, char * *, char * *),
    int argc, char * * ubp_av,
    void (*init) (void),
    void (*fini) (void),
    void (*rtld_fini) (void),
    void (* stack_end)
  ) = dlsym(RTLD_NEXT, "__libc_start_main");
  real_main = main;
  return next(my_main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}

Ciò richiede la password, quindi non è più necessario mantenere segreta la libreria dell'interposer. L'argomento segnaposto viene riutilizzato come richiesta di password, quindi invocalo come

LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start "Password: "

Un'altra alternativa potrebbe leggere la password da un descrittore di file (come ad esempio gpg --passphrase-fd fa), o da x11-ssh-askpass , o qualsiasi altra cosa.

Soluzione 2:

Non è solo la storia. Verrà visualizzato in ps anche l'output.

Chiunque abbia scritto quel software dovrebbe essere impiccato, disegnato e squartato. È un NO assoluto dover fornire una password sulla riga di comando indipendentemente dal software.
Per un processo demone è ancora PIÙ imperdonabile...

Oltre a rm -f sul software stesso non conosco alcuna soluzione per questo. Onestamente:trova altri software per portare a termine il lavoro. Non usare questa spazzatura.

Soluzione 3:

Questo cancellerà il ps uscita.

SIATE MOLTO CONSAPEVOLI :Questo potrebbe interrompere l'applicazione. Sei debitamente avvertito che qui ci sono draghi.

  • I processi estranei non dovrebbero armeggiare nella memoria dei processi.
  • Se il processo si basa su questa regione per la password, potresti interrompere la tua applicazione.
  • In questo modo potresti corrompere tutti i dati di lavoro che hai in quel processo.
  • Questo è un trucco folle.

Ora sei debitamente informato di questi terribili avvertimenti. Questo cancellerà l'output visualizzato in ps . Non cancellerà la tua cronologia, né cancellerà la cronologia dei processi bash (come l'esecuzione del processo come myprocess myargs & ). Ma ps non mostrerà più gli argomenti.

#!/usr/bin/python
import os, sys
import re

PAGESIZE=4096

if __name__ == "__main__":
  if len(sys.argv) < 2:
    sys.stderr.write("Must provide a pid\n")
    sys.exit(1)

  pid = sys.argv[1]

  try:
    cmdline = open("/proc/{0}/cmdline".format(pid)).read(8192)

    ## On linux, at least, argv is located in the stack. This is likely o/s
    ## independent.
    ## Open the maps file and obtain the stack address.
    maps = open("/proc/{0}/maps".format(pid)).read(65536)
    m = re.search('([0-9a-f]+)-([0-9a-f]+)\s+rw.+\[stack\]\n', maps)
    if not m:
      sys.stderr.write("Could not find stack in process\n");
      sys.exit(1)

    start = int("0x"+m.group(1), 0)
    end = int("0x"+m.group(2), 0)

    ## Open the mem file
    mem = open('/proc/{0}/mem'.format(pid), 'r+')
    ## As the stack grows downwards, start at the end. It is expected
    ## that the value we are looking for will be at the top of the stack
    ## somewhere
    ## Seek to the end of the stack minus a couple of pages.
    mem.seek(end-(2*PAGESIZE))

    ## Read this buffer to the end of the stack
    stackportion = mem.read(8192)
    ## look for a string matching cmdline. This is pretty dangerous.
    ## HERE BE DRAGONS
    m = re.search(cmdline, stackportion)
    if not m:
      ## cause this is an example dont try to search exhaustively, just give up
      sys.stderr.write("Could not find command line in the stack. Giving up.")
      sys.exit(1)

    ## Else, we got a hit. Rewind our file descriptor, plus where we found the first argument.
    mem.seek(end-(2*PAGESIZE)+m.start())
    ## Additionally, we'll keep arg0, as thats the program name.
    arg0len = len(cmdline.split("\x00")[0]) + 1
    mem.seek(arg0len, 1)

    ## lastly overwrite the remaining region with nulls.
    writeover = "\x00" * (len(cmdline)-arg0len)
    mem.write(writeover)

    ## cleanup
    mem.close()

  except OSError, IOError:
    sys.stderr.write("Cannot find pid\n")
    sys.exit(1)

Invoca il programma salvandolo, chmod +x esso. Poi facendo ./whatever <pidoftarget> Se funziona, non produrrà alcun output. Se fallisce, si lamenterà di qualcosa e si chiuderà.

Soluzione 4:

Puoi passare l'argomento da un file, accessibile solo da root o dall'utente richiesto?

È un ENORME no-no digitare le password nella console, ma ultima risorsa... inizia la tua riga con uno spazio in modo che non appaia nella cronologia.

Soluzione 5:

Forse funziona (?):

darkcoind masternode start `cat password.txt`

Linux
  1. Come passare un argomento della riga di comando in uno script di shell?

  2. Come creare hash della password Sha512 sulla riga di comando?

  3. Come analizzare ogni riga di un file di testo come argomento di un comando?

  4. 6 Aspettatevi esempi di argomenti della riga di comando dello script

  5. Come posso passare un argomento della riga di comando durante l'avvio di GDB in Linux?

3 gestori di password per la riga di comando di Linux

Come utilizzare il proxy sulla riga di comando di Linux?

Come avviare la riga di comando di Linux

Come passare la password al comando SSH in Linux

Come trovare l'indirizzo IP nella riga di comando di Linux

Come posso fornire una password SSH a SVN sulla riga di comando?