GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara menyembunyikan kata sandi yang diteruskan sebagai argumen baris perintah?

Solusi 1:

Sungguh, ini harus diperbaiki dalam aplikasi itu sendiri. Dan aplikasi seperti itu harus menjadi open source, sehingga memperbaiki masalah di aplikasi itu sendiri harus menjadi pilihan. Aplikasi terkait keamanan yang membuat kesalahan semacam ini mungkin membuat kesalahan lain juga, jadi saya tidak akan mempercayainya.

Pengantara sederhana

Tapi Anda meminta cara yang berbeda, jadi ini salah satunya:

#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);
}

Kompilasi ini dengan

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

lalu jalankan proses Anda dengan

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

Pustaka interposer akan menjalankan kode ini sebelum main fungsi dari aplikasi Anda dijalankan. Ini akan menggantikan argumen baris perintah terakhir dengan kata sandi aktual dalam panggilan ke main. Baris perintah seperti yang dicetak di /proc/*/cmdline (dan karenanya terlihat oleh alat seperti ps ) masih akan berisi argumen palsu. Jelas Anda harus membuat kode sumber dan perpustakaan yang Anda kompilasi darinya hanya dapat dibaca oleh Anda sendiri, jadi sebaiknya operasikan dalam chmod 0700 direktori. Dan karena kata sandi bukan bagian dari pemanggilan perintah, riwayat bash Anda juga aman.

Interposer yang lebih canggih

Jika Anda ingin melakukan sesuatu yang lebih rumit, Anda harus ingat bahwa __libc_start_main dieksekusi sebelum perpustakaan runtime diinisialisasi dengan benar. Jadi saya sarankan menghindari panggilan fungsi apa pun kecuali itu benar-benar penting. Jika Anda ingin dapat memanggil fungsi sesuka hati, pastikan Anda melakukannya tepat sebelum main itu sendiri dipanggil, setelah semua inisialisasi selesai. Untuk contoh berikut saya harus berterima kasih kepada Grubermensch yang menunjukkan cara menyembunyikan kata sandi yang diteruskan sebagai argumen baris perintah yang menghasilkan getpass untuk perhatian saya.

#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);
}

Ini meminta kata sandi, jadi Anda tidak perlu lagi merahasiakan perpustakaan interposer. Argumen placeholder digunakan kembali sebagai permintaan kata sandi, jadi aktifkan seperti ini

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

Alternatif lain akan membaca kata sandi dari deskriptor file (seperti misalnya gpg --passphrase-fd lakukan), atau dari x11-ssh-askpass , atau apa pun.

Solusi 2:

Bukan hanya sejarahnya. Itu akan muncul di ps hasil juga.

Siapa pun yang menulis perangkat lunak itu harus digantung, ditarik, dan dipotong-potong. Ini adalah TIDAK mutlak harus memberikan kata sandi pada baris perintah terlepas dari perangkat lunak apa pun itu.
Untuk proses daemon bahkan LEBIH tidak bisa dimaafkan...

Selain rm -f pada perangkat lunak itu sendiri saya tidak tahu solusi apa pun untuk ini. Jujur:Temukan perangkat lunak lain untuk menyelesaikan pekerjaan. Jangan gunakan sampah seperti itu.

Solusi 3:

Ini akan menghapus ps keluaran.

SANGAT HATI-HATI :Ini dapat merusak aplikasi. Anda sepatutnya diperingatkan bahwa di sini ada naga.

  • Proses asing tidak boleh mengutak-atik memori proses.
  • Jika proses mengandalkan wilayah ini untuk kata sandi, Anda dapat merusak aplikasi Anda.
  • Melakukan ini dapat merusak data kerja apa pun yang Anda miliki dalam proses itu.
  • Ini adalah peretasan gila.

Sekarang Anda telah diberi tahu tentang peringatan yang mengerikan ini. Ini akan menghapus output yang ditampilkan di ps . Itu tidak akan menghapus riwayat Anda, juga tidak akan menghapus riwayat pekerjaan bash (seperti menjalankan proses seperti myprocess myargs & ). Tapi ps tidak akan lagi menampilkan argumen.

#!/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)

Jalankan program dengan menyimpannya, chmod +x dia. Kemudian lakukan ./whatever <pidoftarget> Jika ini berhasil, itu tidak akan menghasilkan output. Jika gagal, ia akan mengeluh tentang sesuatu dan berhenti.

Solusi 4:

Bisakah Anda meneruskan argumen dari file, yang hanya dapat diakses oleh root atau pengguna yang diperlukan?

Sangat dilarang untuk mengetik kata sandi di konsol, tetapi jalan terakhir...mulai baris Anda dengan spasi sehingga tidak muncul dalam riwayat.

Solusi 5:

Mungkin ini berhasil (?):

darkcoind masternode start `cat password.txt`

Linux
  1. Cara Menghapus Riwayat Baris Perintah BASH di Linux

  2. Bagaimana Cara Membuat Hash Kata Sandi Sha512 Di Baris Perintah?

  3. Bagaimana Mengurai Setiap Baris File Teks Sebagai Argumen Untuk Perintah?

  1. 6 Harapkan Contoh Argumen Baris Perintah Skrip

  2. Panjang maksimum argumen baris perintah yang dapat diteruskan ke SQL*Plus?

  3. Bagaimana cara memasukkan kata sandi ke perintah git pull?

  1. Cara Mengubah Kata Sandi di Linux (perintah passwd)

  2. Cara Melewati Kata Sandi ke Perintah SCP di Linux

  3. Cara menggunakan argumen kata sandi melalui baris perintah ke openssl untuk dekripsi