स्ट्रिंग चर के साथ शेल कमांड का संरक्षण


9

एक प्रोग्रामिंग भाषा के भीतर, मैं एक साधारण शेल कमांड निष्पादित करता हूं

cd var; echo > create_a_file_here

साथ वर एक चर कि (उम्मीद) एक जगह है जहाँ मैं फ़ाइल "create_a_file_here" बनाना चाहते हैं निर्देशिका की एक स्ट्रिंग है किया जा रहा है। अब यदि कोई इस कोड की लाइन को देखता है, तो उदाहरण के लिए इसे असाइन करना संभव है:

var = "; rm -rf /"

चीजें बहुत बदसूरत हो सकती हैं। उपरोक्त मामले से बचने के लिए स्ट्रिंग खोज करने के लिए हो सकता है हो सकता है एक तरह से वर की तरह कुछ विशेष वर्ण के लिए ';' शेल कमांड निष्पादित करने से पहले, लेकिन मुझे संदेह है कि यह संभवतः सभी कारनामों को कवर करता है।

क्या किसी को यह सुनिश्चित करने का एक अच्छा तरीका पता है कि "सीडी संस्करण" केवल एक निर्देशिका को बदलता है और कुछ नहीं?


4
आप शेल को कैसे लागू कर सकते हैं, इसके आधार पर, आप varएक तर्क के रूप में भी पास कर सकते हैं । उदाहरण के लिए बुला shतर्क के साथ -c, 'cd "$1"; echo > create_a_file_here', 'sh', varकाम करता है और कोई भी परिवर्तन की जरूरत नहीं है var'sh'तर्क के रूप में पारित कर दिया है $0
ipsec

1
क्या प्रोग्रामिंग भाषा? क्या आप POSIX का उपयोग कर रहे हैं sh, या एक समान सिंटैक्स के साथ अपनी स्वयं की प्रोग्रामिंग भाषा बना रहे हैं , लेकिन varआपको लिखने की आवश्यकता के बजाय विस्तार होता है cd "$var"? या यह bashसाथ है shopt -s cdable_vars? ओह, मुझे लगता है कि आप का मतलब है कि कुछ अन्य कार्यक्रम इन कमांडों को चलाने के लिए एक शेल की तलाश करते हैं। तो बस बोली var, लेकिन सुनिश्चित करें कि इसमें एक उद्धरण चरित्र ही शामिल नहीं है ...
पीटर कॉर्डेस

@PeterCordes यदि आप बैश के बारे में बात कर रहे हैं, तो एक दोहरे उद्धरण वाला चर जिसमें एक डबल उद्धरण है, ठीक है। जैसे s='"'; echo "$s"प्रिंट "
वेजेंड्रिया

@JAndrea: हाँ, लेकिन कोई "ट्रम्प कार्ड" उद्धरण नहीं है जिसे अविश्वासित इनपुट से वैरिएबल असाइनमेंट बनाते समय हराया नहीं जा सकता है। ओह, समाधान: var=untrusted stringमूल कार्यक्रम में करते हैं, इसलिए varएक पर्यावरण चर है जो पहले से ही सेट किया जाता है sh। फिर आपको इसे हर बार इसे विस्तारित करने की आवश्यकता है, जो कि मज़बूती से करना संभव है। आह, मैं देख रहा हूं कि यह विचार पहले से ही स्टीफन के जवाब का हिस्सा है। <
पीटर कॉर्डेस

जवाबों:


9

अगर मैं सही ढंग से समझूं, varतो आपकी प्रोग्रामिंग लैंग्वेज में परिवर्तनशील है।

और आपकी प्रोग्रामिंग भाषा में, आप एक स्ट्रिंग की व्याख्या करने के लिए एक शेल पूछ रहे हैं "cd ", जो उस चर की सामग्री और, का है "; echo > create_a_file_here"

यदि हां, तो, यदि की सामग्री को varकसकर नियंत्रित नहीं किया जाता है, तो यह एक कमांड इंजेक्शन भेद्यता है।

आप कोशिश कर सकते हैं और शेल के सिंटैक्स में वेरिएंट की सामग्री को ठीक से उद्धृत कर सकते हैं, इसलिए यह cdबिलिन के एक एकल तर्क के रूप में पारित होने की गारंटी है ।

एक अन्य तरीका उस चर की सामग्री को दूसरे तरीके से पास करना होगा। एक स्पष्ट तरीका यह होगा कि एक पर्यावरण चर में पारित किया जाए। उदाहरण के लिए, C में:

char *var =  "; rm -rf /";
setenv("DIR", var, 1);
system("CDPATH= cd -P -- \"$DIR\" && echo something > create_a_file_here");

इस बार, आप जिस कोड की व्याख्या करने के लिए शेल पूछते हैं, वह निश्चित है, फिर भी हमें इसे शेल के सिंटैक्स में ठीक से लिखने की आवश्यकता है (यहां एक पॉस-आज्ञाकारी शेल माना जाता है):

  • शेल वेरिएबल एक्सपेंशन को स्प्लिट + ग्लोब को रोकने के लिए उद्धृत किया जाना चाहिए
  • आप की जरूरत -Pके लिए cdएक सरल करने के लिएchdir()
  • आपको (या कुछ गोले में) शुरू होने के साथ --समस्याओं से बचने के लिए विकल्पों के अंत को चिह्नित करने की आवश्यकता हैvar-+
  • हम CDPATHपर्यावरण में होने की स्थिति में खाली स्ट्रिंग पर सेट करते हैं
  • हम केवल echoकमांड चलाते हैं यदि cdसफल रहा।

एक शेष समस्या है (कम से कम): यदि यह varहै -, तो इसे निर्देशिका में chdir नहीं कहा जाता है, -लेकिन पिछली निर्देशिका में (जैसा कि संग्रहीत है $OLDPWD) और OLDPWD=- CDPATH= cd -P -- "$DIR"इसके चारों ओर काम करने की गारंटी नहीं है। तो आपको कुछ इस तरह की आवश्यकता होगी:

system(
  "case $DIR in\n"
  " (-) CDPATH= cd -P ./-;;\n"
  " (*) CDPATH= cd -P -- \"$DIR\";;\n"
  "esac && ....");

Doing ध्यान दें कि सिर्फ एक system(concat("cd \"", var, "\"; echo..."));करना ही रास्ता नहीं है, आप बस समस्या को आगे बढ़ाएंगे।

उदाहरण के लिए, var = "$(rm -rf /)"अभी भी एक समस्या होगी।

बॉर्न जैसे गोले के लिए पाठ को उद्धृत करने का एकमात्र विश्वसनीय तरीका एकल उद्धरण का उपयोग करना है और स्ट्रिंग में होने वाले एकल उद्धरण का भी ध्यान रखना है। उदाहरण के लिए, को चालू char *var = "ab'cd"करें char *escaped_var = "'ab'\\''cd'"। यही है, सभी 'को बदलें '\''और पूरी चीज़ को अंदर लपेटें '...'

यही कारण है कि अभी भी मानता है कि कि उद्धृत स्ट्रिंग बैकटिक भीतर नहीं किया जाता है, और आप अभी भी आवश्यकता होगी --, -P, &&, CDPATH=...


12

सरल समाधान: अपने प्रोग्राम से शेल को कॉल न करें। बिल्कुल भी।

यहां आपका उदाहरण तुच्छ है, निर्देशिका को बदलना और फ़ाइलें बनाना जो भी प्रोग्रामिंग भाषा में आसान होना चाहिए। लेकिन यहां तक ​​कि अगर आपको बाहरी कमांड चलाने की आवश्यकता है, तो आमतौर पर इसे शेल के माध्यम से करने की कोई आवश्यकता नहीं है।

इसलिए, उदाहरण के लिए, पायथन में, चलाने के बजाय os.system("somecmd " + somearg), उपयोग करें subprocess.run(["somecmd", somearg])। C के बजाय system(), का उपयोग करें fork()और exec()(या ऐसा पुस्तकालय ढूंढें जो इसे करता है)।

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

केवल उन वर्णों को अनुमति दें जिनके कार्यों को आप जानते हैं, इस तरह से कुछ गायब होने का कम जोखिम है। अंतिम परिणाम यह हो सकता है कि आप केवल अनुमति देने का निर्णय लेते हैं [a-zA-Z0-9_], लेकिन यह काम पूरा करने के लिए पर्याप्त हो सकता है। आप यह भी जांचना चाहेंगे कि आपके स्थान और टूलसेट में उच्चारण अक्षर जैसे äऔर öउस में शामिल नहीं हैं । उन्हें शायद किसी भी शेल द्वारा विशेष नहीं माना जाता है, लेकिन फिर से, यह सुनिश्चित करना बेहतर है कि वे पास हैं या नहीं।


1
और सुनिश्चित करें कि आप जो कुछ भी उपयोग करते [a-zA-Z0-9]हैं, àउसके खिलाफ ऐसी चीजें शामिल नहीं हैं, जिनके एन्कोडिंग को bashकुछ स्थानों में कुछ गोले (जैसे ) द्वारा गलत तरीके से समझा जा सकता है।
स्टीफन चेजलस

@ स्टीफनचेलजेलस (रुचि से बाहर) क्या वे (और सिर्फ उन प्रभावित स्थानों के नीचे हैं?)
विल्फ

10

एक प्रोग्रामिंग भाषा के भीतर, शेल कमांड निष्पादित करने की तुलना में चीजों को करने के बेहतर तरीके होने चाहिए। उदाहरण के लिए, cd varअपनी प्रोग्रामिंग भाषा के समकक्ष के साथ प्रतिस्थापित chdir (var);करना सुनिश्चित करना चाहिए कि varअनायास और संभवतः दुर्भावनापूर्ण कार्यों के बजाय "निर्देशिका नहीं मिली" त्रुटि में केवल परिणाम के मूल्य के साथ किसी भी चालबाजी ।

इसके अलावा, आप निर्देशिकाओं को बदलने के बजाय निरपेक्ष पथों का उपयोग कर सकते हैं। बस निर्देशिका नाम, स्लेश और उस फ़ाइलनाम को संक्षिप्त करें जिसका आप उपयोग करना चाहते हैं।

C में, मैं कुछ ऐसा कर सकता हूं:

char filepath[PATH_MAX];  /* alternative constant: MAXPATHLEN */

/* Join directory name in var and the filename, guarding against exceeding PATH_MAX */
snprintf (filepath, PATH_MAX, "%s/%s", var, "create_a_file_here");

/* create an empty file/truncate an existing one */
fclose (fopen (filepath, "w") );

निश्चित रूप से आपकी प्रोग्रामिंग भाषा कुछ ऐसा ही कर सकती है?


आपके उत्तर के लिए धन्यवाद, लेकिन दुर्भाग्य से मुझे बैश कमांड के साथ वर्कअराउंड का उपयोग करना होगा। मैंने चर को उद्धृत करते हुए परीक्षण किया - जैसा कि मुरू ने सुझाव दिया - और यह काम करने लगता है!
ES___
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.