कमांड लाइन तर्क के रूप में पारित पासवर्ड को कैसे छिपाएं?


43

मैं एक सॉफ़्टवेयर डेमॉन चला रहा हूँ, जिसमें कुछ विशेषताओं के लिए पासफ़्रेज़ दर्ज करने के लिए कुछ विशेषताओं की आवश्यकता होती है, जो इस तरह के उदाहरण के लिए दिखता है:

$ darkcoind masternode start <mypassphrase>

अब मुझे अपने हेडलेस डेबियन सर्वर पर कुछ सुरक्षा चिंताओं का सामना करना पड़ा।

जब भी मैं उदाहरण के लिए अपना बैश इतिहास खोजता हूं तो मैं Ctrl+Rइस सुपर मजबूत पासवर्ड को देख सकता हूं। अब मुझे लगता है कि मेरे सर्वर से छेड़छाड़ की गई है और कुछ घुसपैठियों के पास शेल एक्सेस है और Ctrl+Rवे इतिहास में अपना पासफ़्रेज़ ढूंढ सकते हैं ।

क्या बैश इतिहास में ps, /procया कहीं और दिखाए जाने के बिना पासफ़्रेज़ में प्रवेश करने का कोई तरीका है?


अद्यतन 1 : डेमॉन के लिए कोई पासवर्ड पास करना एक त्रुटि फेंकता है। यह कोई विकल्प नहीं है।


अपडेट 2 : मुझे सॉफ़्टवेयर या अन्य सहायक संकेत जैसे डेवलपर्स को लटकाने के लिए हटाने के लिए न कहें। मुझे पता है कि यह एक सर्वोत्तम अभ्यास उदाहरण नहीं है, लेकिन यह सॉफ्टवेयर बिटकॉइन पर आधारित है और सभी बिटकॉइन आधारित क्लाइंट कुछ प्रकार के json rpc सर्वर हैं जो इन आदेशों को सुनते हैं और इसके एक ज्ञात सुरक्षा मुद्दे पर अभी भी चर्चा की जा रही है ( , बी , सी ) ।


अद्यतन 3 : डेमॉन पहले से ही चालू है और कमांड के साथ चल रहा है

$ darkcoind -daemon

करना psकेवल स्टार्टअप कमांड को दर्शाता है।

$ ps aux | grep darkcoin
user     12337  0.0  0.0  10916  1084 pts/4    S+   09:19   0:00 grep darkcoin
user     21626  0.6  0.3 1849716 130292 ?      SLl  May02   6:48 darkcoind -daemon

तो पासफ़्रेज़ के साथ आदेशों को पारित करने में psया बिल्कुल भी नहीं दिखाई देता है /proc

$ darkcoind masternode start <mypassphrase>
$ ps aux | grep darkcoin
user     12929  0.0  0.0  10916  1088 pts/4    S+   09:23   0:00 grep darkcoin
user     21626  0.6  0.3 1849716 130292 ?      SLl  May02   6:49 darkcoind -daemon

यह सवाल छोड़ देता है कि इतिहास कहां दिखाई देता है? केवल में .bash_history?


1
पहला सवाल यह है: यदि आप पासफ़्रेज़ तर्क के बिना डेमॉन शुरू करते हैं तो क्या होगा। क्या यह सिर्फ इसके लिए संकेत देता है?
MadHatter

31
मुझे नहीं लगता कि कोई जवाब है जो काम करेगा। पासफ़्रेज़ के लिए संकेत देने में असमर्थता डेमॉन में एक बड़ी कमी है। यदि यह मुफ़्त सॉफ़्टवेयर है, तो इसमें प्रोग्रामर प्राप्त करें और इसे ठीक करें; अपने परिवर्तनों को प्रकाशित करना न भूलें। यदि यह मालिकाना सॉफ्टवेयर है, तो विक्रेता को रिंग करें और उन पर चिल्लाएं (जो कुछ भी ठीक नहीं करेगा, लेकिन यह आपको बेहतर महसूस कराएगा)।
MadHatter

4
अपने प्रलेखन की जाँच करें, यह सिस्टम पर्यावरण चर से उस पासवर्ड को पढ़ने का समर्थन कर सकता है।
इलियट फ्रिश

3
यहां तक ​​कि अगर डेमॉन को कमांड लाइन पर पासवर्ड नहीं दिया गया है, तो भी इसे किसी अन्य कमांड की कमांड लाइन पर देने के लिए समस्याग्रस्त है। यह केवल बहुत कम समय के लिए पीएस आउटपुट में दिखाई देता है, लेकिन पृष्ठभूमि में चलने वाली एक प्रक्रिया अभी भी इसे उठा सकती है। लेकिन यह निश्चित रूप से अभी भी सार्थक है कि पासवर्ड को चुनना मुश्किल है।
कैस्परर्ड

2
इस प्रश्न के उत्तर को देखें , वे इस मुद्दे से बिल्कुल निपटते हैं।
डॉटान्चेन

जवाबों:


68

वास्तव में, यह आवेदन में ही तय किया जाना चाहिए । और ऐसे अनुप्रयोगों को खुला स्रोत होना चाहिए , ताकि ऐप में समस्या को ठीक करना ही एक विकल्प हो। एक सुरक्षा संबंधी एप्लिकेशन जो इस तरह की गलती करता है, अन्य गलतियाँ भी कर सकता है, इसलिए मुझे इस पर भरोसा नहीं होगा।

सरल अन्तःप्रेरणा

लेकिन आप एक अलग तरह से पूछ रहे थे, इसलिए यहां एक है:

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

इसके साथ संकलित करें

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

फिर अपनी प्रक्रिया को चलाएं

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

इंटरपोज़र लाइब्रेरी mainआपके एप्लिकेशन से कार्य निष्पादित होने से पहले इस कोड को चलाएगी । यह मुख्य कमांड कॉल तर्क को कॉल में वास्तविक पासवर्ड को मुख्य में बदल देगा। हालांकि /proc/*/cmdline(और जैसे उपकरण के द्वारा देखा गया ps) के रूप में कमांड लाइन में अभी भी नकली तर्क शामिल होंगे। जाहिर है कि आपको स्रोत कोड और पुस्तकालय का निर्माण करना होगा, जिसे आप केवल स्वयं से पढ़ सकते हैं, इसलिए एक chmod 0700निर्देशिका में सबसे अच्छा काम करते हैं । और चूंकि पासवर्ड कमांड मंगलाचरण का हिस्सा नहीं है, इसलिए आपका बैश इतिहास सुरक्षित है।

अधिक उन्नत इंटरपोज़र

यदि आप कुछ अधिक विस्तृत करना चाहते हैं, तो आपको ध्यान रखना चाहिए कि __libc_start_mainरनटाइम लाइब्रेरी को ठीक से आरंभ करने से पहले निष्पादित किया जाता है। इसलिए मेरा सुझाव है कि जब तक वे बिल्कुल आवश्यक न हों, किसी भी फ़ंक्शन कॉल से बचें। यदि आप अपने दिल की सामग्री के लिए कार्यों को कॉल करने में सक्षम होना चाहते हैं, तो सुनिश्चित करें कि आप ऐसा करने से ठीक पहले mainखुद को आह्वान करने से पहले करते हैं। निम्नलिखित उदाहरण के लिए मुझे ग्रुबर्मेंस का धन्यवाद करना होगा जिन्होंने बताया कि कैसे पासवर्ड को छिपाने के लिए कमांड लाइन तर्क के रूप में पारित किया गया जो getpassमेरे ध्यान में लाया गया।

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

यह पासवर्ड के लिए संकेत देता है, इसलिए अब आपको इंटरपोज़र लाइब्रेरी को गुप्त नहीं रखना होगा। प्लेसहोल्डर तर्क को पासवर्ड प्रॉम्प्ट के रूप में पुन: उपयोग किया जाता है, इसलिए इसे इस तरह से लागू करें

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

एक अन्य विकल्प पासवर्ड को फ़ाइल डिस्क्रिप्टर (जैसे कि gpg --passphrase-fdकरता है), या से x11-ssh-askpass, या जो कुछ भी है, से पढ़ेगा ।


4
हालाँकि मुझे समझ नहीं आ रहा है और मैं कोड का परीक्षण नहीं कर सकता, लेकिन मुझे इसकी जानकारी मिलती है, और यह एक वास्तविक उत्तर की तरह दिखता है और शीर्ष उत्तर होना चाहिए।
मार्क हेंडरसन

यह वाकई कमाल है।
वकार लिम

बहुत बढ़िया। जहाँ तक मैं यह काम करने के लिए कहना चाहिए। बेशक आपको स्रोत तक पहुंच की आवश्यकता है और फिर से संगठित होने में सक्षम होना चाहिए। पासवर्ड स्रोत और संकलित फ़ाइल (ओं) में पठनीय है यदि आप "स्ट्रिंग्स" या कुछ इसी तरह का उपयोग करते हैं तो बेहतर यह सुनिश्चित करें कि कोई और उन्हें नहीं पढ़ सकता है।
Tonny

1
एसटीडीआईएन पर पासवर्ड लेना संभव होना चाहिए और अभी भी यह काम है, जो stringsभेद्यता को दूर करता है। SO देखें : टर्मिनल पर पासवर्ड इनपुट छिपाएँ
ग्रुबमेन्सच

1
@ mulg0r: स्टैण्डर्ड एक्सटर्नल "C" को संबंधित फंक्शन के लिए मैनबलिंग नाम दबाने की ट्रिक करनी चाहिए __libc_start_main
एमवीजी

28

यह सिर्फ इतिहास नहीं है। यह पीएस आउटपुट में भी दिखाने जा रहा है ।

जिसने भी लिखा है कि सॉफ्टवेयर का टुकड़ा लटका, खींचा और चौथाई होना चाहिए। यह कमांड-लाइन पर एक पासवर्ड की आपूर्ति करने के लिए एक पूर्ण सं।
एक डेमन प्रक्रिया के लिए यह और भी अक्षम्य है ...

सॉफ्टवेयर पर rm -f के अलावा मुझे इसके लिए कोई समाधान नहीं पता है। ईमानदारी से: काम पूरा करने के लिए अन्य सॉफ़्टवेयर ढूंढें। ऐसे कबाड़ का उपयोग न करें।


9
मददगार नहीं होने के लिए धन्यवाद। यह एक लंबी चर्चा की गई सुरक्षा समस्या है , अभी भी अनसुलझी है और मुझे rm -fअब से बेहतर समाधान की आवश्यकता है ।
वकार लिम

17
दरअसल, वह बहुत मददगार साबित हो रहा है। यदि आप पासफ़्रेज़ को एक तर्क के रूप में पारित कर रहे हैं, तो यह दिखाई देगा ps। इसलिए जब तक देव उसे ठीक कर सकता है, वह कुछ और उपयोग करने का सुझाव दे रहा है।
Safado

3
फिर आप एक और ऑपरेटिंग सिस्टम लिखना बेहतर शुरू करते हैं। वर्तमान में कोई अन्य समाधान उपलब्ध नहीं है जिससे मैं अवगत हूं। भगवान की इच्छा से मैं वहाँ गया था। आप इस समस्या के साथ ही नहीं हैं।
टॉनी

8
चक्कर, झपकी लेना नहीं है। आप इसे कागज की छोटी पर्चियों पर पारित करने का तरीका पूछ सकते हैं, लेकिन इसका मतलब यह नहीं है कि ऐसा कोई भी तरीका अपने आप मौजूद है। read_x ठीक है, लेकिन अभी भी उदाहरण के माध्यम से पासफ़्रेज़ को उजागर करता है ps, इसलिए यह rmसमाधान से बेहतर नहीं है ।
MadHatter

7
इससे पहले कि तुम सब लोग जा सकते हैं और यह नहीं-सच-एक-जवाब पर एक और +1 फेंक और शिकायत करते हैं कि यह असंभव है, मैं सुझाव है कि आप की समीक्षा नीचे MVG का जवाब
मार्क हेंडरसन

19

इससे psआउटपुट क्लियर हो जाएगा ।

बहुत सावधान : यह आवेदन तोड़ सकता है। आपको विधिवत चेतावनी दी जाती है कि यहां ड्रेगन रहें।

  • विदेशी प्रक्रियाओं को स्मृति प्रक्रियाओं में नहीं होना चाहिए।
  • यदि यह प्रक्रिया पासवर्ड के लिए इस क्षेत्र पर निर्भर करती है, तो आप अपना आवेदन तोड़ सकते हैं।
  • ऐसा करना उस प्रक्रिया में आपके पास मौजूद किसी भी डेटा को दूषित कर सकता है।
  • यह एक पागल हैक है।

अब आपको इन सख्त चेतावनियों की विधिवत सूचना दी गई है। इससे प्रदर्शित आउटपुट साफ़ हो जाएगा ps। यह आपके इतिहास को स्पष्ट नहीं करेगा, और न ही यह बैश जॉब के इतिहास (जैसे प्रक्रिया को चलाना myprocess myargs &) को स्पष्ट करेगा । लेकिन psअब तर्कों को नहीं दिखाएंगे।

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

इसे सेव करके प्रोग्राम इंज्वाय करें chmod +x। फिर ./whatever <pidoftarget> अगर यह काम करता है, तो यह कोई आउटपुट नहीं देगा। यदि यह विफल रहता है, तो यह किसी चीज़ के बारे में शिकायत करेगा और छोड़ देगा।


18
। । । यह रचनात्मक और भयावह दोनों है।
voretaq7

EEK! अब मुझे डर लग रहा है।
जने पिक्कारेनैन

Yikkes, यह काम कर सकता है ... मुझे यकीन नहीं है कि AppArmor ऐसा कुछ पकड़ लेगा? इसके अलावा virusscanner संभावित रूप से इसे पकड़ सकता है और आपत्तिजनक खाते को अवरुद्ध करके कहर पैदा कर सकता है जो कि 'जड़' होगा। वास्तव में ड्रेगन हो सकता है ....
टन

@ सुरक्षित डोमेन के लिए, SELinux इसे रोकेगा। आपकी मूल यूनिक्स अनुमतियाँ (डीएसी) में इस व्यवहार से किसी भी सुरक्षा की पेशकश करने के लिए पर्याप्त विषयवस्तु की कमी है (समान यूआईडी के भीतर प्रक्रियाओं की स्मृति में संशोधन की अनुमति देता है)। वैसे भी, यह एक बग नहीं है - इसकी एक विशेषता है। मेरा मानना ​​है कि यह कैसे gdbचल रही प्रक्रियाओं की स्मृति को संशोधित कर सकता है (इससे अधिक सर्जिकल परिशुद्धता के साथ मैं इसे जोड़ सकता हूं)।
मैथ्यू इफ

11

क्या आप एक फ़ाइल से तर्क पारित कर सकते हैं, केवल रूट या आवश्यक उपयोगकर्ता द्वारा पहुँचा जा सकता है?

यह सांत्वना में पासवर्ड टाइप करने के लिए एक बड़ी संख्या नहीं है, लेकिन अंतिम सहारा ... अपनी पंक्ति को एक स्थान से शुरू करें ताकि यह इतिहास में प्रकट न हो।


एक शेल विकल्प था जो इसे सक्षम करता है, लेकिन मुझे लगता है कि यह डिफ़ॉल्ट रूप से सक्षम नहीं था।
हेनरिच 5991

export HISTCONTROL=ignorebothइतिहास में प्रवेश के लिए एक प्रमुख स्थान के साथ दोनों डुप्लिकेट और लाइनों की उपेक्षा करता है। इसे अपने .bashrc या .bash_profile में जोड़ें।
एंड्रियास

7

शायद यह काम करता है (?):

darkcoind masternode start `cat password.txt`

3
या यहां तक ​​कि darkcoind masternode start `head -1`, यदि आप मैन्युअल रूप से पासवर्ड दर्ज करना चाहते हैं।
19

14
पासफ़्रेज़ अभी भी psऔर इसी तरह की उपयोगिताओं के माध्यम से उपलब्ध है ।
voretaq7

1
एक प्लेनटेक्स्ट पासवर्ड से एक प्लेनटेक् ट पासवर्ड में ले .bash_historyजाना password.txtआपको लाभ देता है क्या, वास्तव में?
मिकी

1
@ मायकेबीबी: एक छोटी सी जीत है: आप अपने इतिहास को खोजते हुए इसे उजागर नहीं करेंगे, जबकि कोई आपके कंधे पर दिख रहा है।
एमवीजी

1
@ माइकाइब, आप हर बार उस फ़ाइल को बना और निकाल सकते हैं।
रियाद

4

दुर्भाग्यवश, यदि आपका darkcoindकमांड कमांड-लाइन तर्क के रूप में पासवर्ड की अपेक्षा करता है, तो यह उपयोगिताओं जैसे कि के माध्यम से उजागर किया जाएगा psडेवलपर्स को शिक्षित करने के लिए एकमात्र वास्तविक समाधान है ।

हालांकि psएक्सपोज़र अपरिहार्य हो सकता है, आप कम से कम पासवर्ड को शेल हिस्ट्री फ़ाइल में लिखे जाने से रोक सकते हैं।

$ xargs darkcoind masternode start

password

CtrlD

इतिहास फ़ाइल को केवल रिकॉर्ड होना चाहिए xargs darkcoind masternode start, पासवर्ड नहीं।


2
या फिर आप बैश उपयोग कर रहे हैं, डाल ignorespaceमें $HISTCONTROL, और फिर आप को रोका जा सकता है किसी भी एक स्थान के साथ आदेश लगाकर से खोल इतिहास में जाने से आदेश।
derobert

3

जैसा कि दूसरों ने कहा है, इतिहास से जानकारी छिपाने के लिए अपने शेल इतिहास नियंत्रण में देखें।

लेकिन एक बात अभी तक किसी ने भी सुझाई नहीं है /procकि hidepidपैरामीटर के साथ माउंट करना है । इस तरह शामिल करने के लिए अपनी /procलाइन को संशोधित करने का प्रयास करें:/etc/fstabhidepid

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults,hidepid=2        0       0

2

आप एक नई शेल प्रक्रिया से कमांड निष्पादित करके अपने शेल के इतिहास से पासवर्ड रख सकते हैं, जिसे आप तुरंत समाप्त कर देते हैं। उदाहरण के लिए:

bash$ sh
sh$ darkcoind masternode start 'correct horse battery staple'
sh$ exit
bash$

सुनिश्चित करें कि एक फ़ाइल में अपने इतिहास को बचाने के लिए shकॉन्फ़िगर नहीं किया गया है।

बेशक यह अन्य समस्याओं को संबोधित नहीं करता है, जैसे कि पासवर्ड में दिखाई दे रहा है ps। मेरा मानना ​​है कि darkcoindकार्यक्रम से जानकारी छुपाने के तरीके खुद-ब-खुद सामने आ जाते हैं ps, लेकिन यह केवल भेद्यता की खिड़की को छोटा करता है।


1
पासफ़्रेज़ अभी भी psऔर इसी तरह की उपयोगिताओं के माध्यम से उपलब्ध है ।
voretaq7

3
@ voretaq7: हां, जैसा कि मैंने अपने उत्तर के अंतिम पैराग्राफ में स्पष्ट रूप से स्वीकार किया है।
कीथ थॉम्पसन

3
वास्तव में - आप मेरी
तरफ से कोपोन कोपास्ता

2

बिटकॉइन के लिए, आधिकारिक डेवलपर उत्तर में दिए गए अजगर रैपर contrib/bitrpc/bitrpc.py( github ) का उपयोग करना है:

यह एक सुरक्षित तरीके से पासवर्ड के लिए पूछता है यदि आप walletpassphraseउदाहरण के लिए, कमांड का उपयोग करते हैं । इसमें इंटरैक्टिव कार्यक्षमता जोड़ने की कोई योजना नहीं है bitcoin-cli

तथा:

bitcoin-cli के रूप में रहेगा और इंटरैक्टिव कार्यक्षमता हासिल नहीं है।

स्रोत: # २३१18

अनलॉक बटुआ:

$ python bitrpc.py walletpassphrase

पासफ़्रेज़ बदलें:

$ python bitrpc.py walletpassphrasechange

https://github.com/bitcoin/bitcoin/tree/master/contrib/bitrpc

Darkcoin के लिए यह काम करता है:

https://github.com/darkcoin/darkcoin/tree/master/contrib/bitrpc

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.