क्या यह संभव है कि `फाइंड -एक्सक श-सी` का सुरक्षित रूप से उपयोग किया जाए?


29

मैं कुछ फ़ाइलों में उपयोग findकरने की कोशिश कर रहा हूं echo 0, लेकिन जाहिर तौर पर यह केवल साथ काम करता है sh -c:

find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' \;

लेकिन मेरे sh -cसाथ प्रयोग करने find -execसे मुझे बहुत बेचैनी होती है क्योंकि मैं समस्याओं के उद्धरण पर संदेह करता हूं। मैंने इसके साथ थोड़ा सा सामना किया और जाहिर तौर पर मेरे संदेह जायज थे:

  • मेरा परीक्षण सेटअप:

    martin@dogmeat ~ % cd findtest 
    martin@dogmeat ~/findtest % echo one > file\ with\ spaces
    martin@dogmeat ~/findtest % echo two > file\ with\ \'single\ quotes\'
    martin@dogmeat ~/findtest % echo three > file\ with\ \"double\ quotes\"
    martin@dogmeat ~/findtest % ll
    insgesamt 12K
    -rw-rw-r-- 1 martin martin 6 Sep 17 12:01 file with "double quotes"
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with 'single quotes'
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with spaces
  • का उपयोग करते हुए find -execबिना sh -cसमस्याओं के बिना काम करने के लिए लगता है - यहाँ कोई आवश्यक उद्धृत:

    martin@dogmeat ~ % find findtest -type f -exec cat {} \;
    one
    two
    three
  • लेकिन जब मैं उपयोग कर रहा हूँ तो sh -c {}किसी प्रकार के उद्धरण की आवश्यकता प्रतीत होती है:

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c 'cat {}' \;
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: spaces: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: single quotes: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: double quotes: No such file or directory
  • डबल कोट्स तब तक काम करते हैं जब तक कि किसी फ़ाइल नाम में डबल कोट्स न हों:

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c 'cat "{}"' \;
    one
    two
    cat: findtest/file with double: No such file or directory
    cat: quotes: No such file or directory
  • सिंगल कोट्स तब तक काम करते हैं जब तक कि किसी फाइल के नाम में सिंगल कोट्स न हों:

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c "cat '{}'" \;
    one
    cat: findtest/file with single: No such file or directory
    cat: quotes: No such file or directory
    three

मुझे ऐसा कोई समाधान नहीं मिला है जो सभी मामलों में काम करता हो। वहाँ कुछ है जो मैं देख रहा हूँ, या स्वाभाविक असुरक्षित sh -cमें उपयोग कर रहा हूँ find -exec?

जवाबों:


40

{}शेल कोड में कभी भी एम्बेड न करें ! यह एक कमांड इंजेक्शन भेद्यता बनाता है। ध्यान दें कि के लिए cat "{}"यह है, न केवल के बारे में "अक्षर, \, `, $भी एक समस्या हैं (उदाहरण के लिए कहा जाता है एक फ़ाइल पर विचार ./$(reboot)/accept_ra)।

(वैसे, कुछ findकार्यान्वयन आपको ऐसा नहीं करने देंगे, और POSIX व्यवहार को अनिर्दिष्ट छोड़ देता है जब {}तर्क में अपने दम पर नहीं है find)

यहां, आप फ़ाइल नामों को अलग-अलग तर्कों के रूप में पास करना चाहते हैं sh( कोड तर्क में नहीं ), और shइनलाइन स्क्रिप्ट ( कोड तर्क) में स्थितीय मापदंडों का उपयोग करके उन्हें संदर्भित करने के लिए:

find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} \;

या, shप्रति फ़ाइल एक चलाने से बचने के लिए :

find . -name accept_ra -exec sh -c 'for file do
  echo 0 > "$file"; done' sh {} +

एक ही लागू होता है xargs -I{}या zshकी zargs -I{}। न लिखें:

<list.txt xargs -I {} sh -c 'cmd> {}'

जो एक कमांड इंजेक्शन भेद्यता के साथ उसी तरह होगा जैसे कि findऊपर, लेकिन:

<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh

जिसमें shप्रति फ़ाइल चलाने से बचने और list.txtकिसी भी फ़ाइल में त्रुटि न होने का भी लाभ होता है।

साथ zshकी zargs, तो आप शायद लागू करने के बजाय एक समारोह का उपयोग करना चाहें sh -c:

do-it() cmd > $1
zargs ./*.txt -- do-it

ध्यान दें कि ऊपर दिए गए दूसरे उदाहरण में सभी shइनलाइन स्क्रिप्ट में हैं $0। आप प्रासंगिक कुछ (जैसे का उपयोग करना चाहिए shया find-sh), नहीं चीजों की तरह _, -, --या खाली स्ट्रिंग, में मूल्य के रूप में $0खोल के त्रुटि संदेश के लिए प्रयोग किया जाता है:

$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} \;
inline-sh: ./accept_ra: Permission denied

GNU parallelअलग तरीके से काम करता है। इसके साथ, आप उपयोग नहीं करना चाहते हैं sh -cक्योंकि parallelपहले से ही एक शेल चलाता है और शेल के {}लिए सही सिंटैक्स में उद्धृत तर्क से बदलने की कोशिश करता है

<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'

thats दूसरा sh, प्लेसहोल्डर किसी तरह का हो रहा है यह भी काम करता है, तो द्वारा प्रतिस्थापित _उदाहरण के लिए - यदि आप बैश आंतरिक कॉल करना चाहते हैं बहुत उपयोगी: find /tmp -name 'fil*' -exec bash -c 'printf "%q\n" "$1"' _ {} \;। लेकिन क्या किसी को पता है कि यह दस्तावेज कहां है?
फ्लोरियन फिदा

1
@FlorianFida खोल करने के लिए पहला तर्क हो जाता है $0। (आमतौर पर खोल के नाम आप इस परिदृश्य में इसे छोड़ करने के लिए तो यह अपनी सामान्य स्थितीय तर्कों में से एक भोजन नहीं करता जरूरत के लिए दस्तावेज़। -cइस का उल्लेख है।
Etan Reisner


1
@phk, यह argv[0]यहाँ नहीं है, यह सिर्फ $0स्क्रिप्ट का है। स्वेन का पृष्ठ यहां गलत है, rयह शेल को एक प्रतिबंधित मोड में प्रवेश नहीं करेगा जहां तक ​​यह बता सकता है और zshमोड के आधार पर परिवर्तन नहीं करेगा $0(exec -a rksh ksh -c 'cd /')एक प्रतिबंधित चलाएगा ksh, लेकिन नहीं ksh -c 'cd /' rksh)।
स्टीफन चेज़लस

1
स्टीफन, अगर आपको कोई आपत्ति नहीं है, तो क्या आपका कोई जवाब है जो बताता है कि "शेल कोड में {} एम्बेड क्यों नहीं किया गया है"? मैं आपके सभी उत्तरों को ढूंढने के बावजूद चला गया, लेकिन एक नहीं मिला, हालांकि मैं कसम खा सकता हूं कि मैंने कुछ सामान देखा था जो आपने इस विषय के बारे में लिखा था, लेकिन याद नहीं कर सकते कि क्या यह एक उत्तर था, चैट में टिप्पणी या किसी अन्य साइट पर compunix जैसी। ... तो / जब आप समय है, तो आप "कभी एम्बेड {}" ओर से विस्तार हो रहा मन होगा या आपको लगता है कि हम एक समर्पित क्यू जैसे होना चाहिए है "का उपयोग करने का सुरक्षा निहितार्थ findके साथ -exec sh -cऔर एम्बेडिंग {}खोल कोड में" ?
don_crissti
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.