प्रति-रनिंग के सुरक्षा निहितार्थ '...' *


27

जाहिर है, चल रहा है:

perl -n -e 'some perl code' *

या

find . ... -exec perl -n -e '...' {} +

( -pइसके बजाय उसी के साथ -n)

या

perl -e 'some code using <>' *

अक्सर इस साइट पर पोस्ट किए गए वन-लाइनर्स में सुरक्षा निहितार्थ पाए जाते हैं। क्या बात है? इससे कैसे बचा जाए?

जवाबों:


33

समस्या क्या है

सबसे पहले, कई उपयोगिताओं के लिए, आपके पास फ़ाइल नाम के साथ शुरू होने वाला मुद्दा होगा -। जब में:

sh -c 'inline sh script here' other args

अन्य आर्गों को पारित किया जाता है inline sh script; perlसमकक्ष के साथ ,

perl -e 'inline perl script here' other args

अन्य आर्ग और अधिक विकल्प के लिए के लिए स्कैन किए पर्ल पहले, इनलाइन स्क्रिप्ट के लिए नहीं। उदाहरण के लिए, यदि -eBEGIN{do something evil}वर्तमान निर्देशिका में एक फ़ाइल है ,

perl -ne 'inline perl script here;' *

(साथ या बिना -n) कुछ बुराई करेगा।

अन्य उपयोगिताओं की तरह, इसके लिए चारों ओर का काम अंत-विकल्प मार्कर ( --) का उपयोग करना है:

perl -ne 'inline perl script here;' -- *

लेकिन फिर भी, यह अभी भी खतरनाक है और इसके <>द्वारा उपयोग किए गए ऑपरेटर के लिए नीचे है -n/ -p

मुद्दे को perldoc perlopप्रलेखन में समझाया गया है।

उस विशेष ऑपरेटर का उपयोग इनपुट की एक पंक्ति (एक रिकॉर्ड, रिकॉर्ड डिफ़ॉल्ट रूप से रेखाएं) को पढ़ने के लिए किया जाता है, जहां वह इनपुट बारी-बारी से पारित किए गए प्रत्येक तर्क से आ रहा है @ARGV

में:

perl -pe '' a b

-pwhile (<>)कोड (यहां खाली) के चारों ओर एक लूप का अर्थ है ।

<>पहली बार खुलेगा a, एक समय में एक लाइन रिकॉर्ड करें जब तक कि फ़ाइल समाप्त न हो जाए और फिर खुले b...

समस्या यह है कि, फ़ाइल को खोलने के लिए, यह पहले, असुरक्षित रूप का उपयोग करता है open:

open ARGV, "the file as provided"

उस रूप के साथ, यदि तर्क है

  • "> afile", यह afileलेखन मोड में खुलता है,
  • "cmd|", यह चलता है cmdऔर इसे आउटपुट पढ़ता है।
  • "|cmd", आप इनपुट के लिए लिखने के लिए एक धारा खुला है cmd

उदाहरण के लिए:

perl -pe '' 'uname|'

नामक फ़ाइल की सामग्री का उत्पादन नहीं करता है uname|(पूरी तरह से मान्य फ़ाइल नाम btw), लेकिन unameकमांड का आउटपुट ।

यदि आप चला रहे हैं:

perl -ne 'something' -- *

और किसी ने rm -rf "$HOME"|वर्तमान निर्देशिका में (फिर एक पूरी तरह से वैध फ़ाइल नाम) नामक एक फ़ाइल बनाई है (उदाहरण के लिए क्योंकि वह निर्देशिका एक बार दूसरों द्वारा लिखी गई थी, या आपने एक डॉगी संग्रह निकाला है, या आपने कुछ डॉगी कमांड चलाया है, या किसी अन्य सॉफ्टवेयर में एक और भेद्यता का शोषण किया गया था), तो आप बड़ी मुसीबत में हैं। जिन क्षेत्रों में इस समस्या से अवगत होना महत्वपूर्ण है, वे सार्वजनिक क्षेत्रों में स्वचालित रूप से टूल प्रोसेसिंग फाइल हैं /tmp(या ऐसे उपकरण जिन्हें टूल कहा जा सकता है)।

फ़ाइलें बुलाया > foo, foo|, |fooएक समस्या है। लेकिन कुछ हद तक < fooऔर fooASCII रिक्ति वर्ण (अंतरिक्ष, टैब, newline, cr ...) के साथ-साथ उन फ़ाइलों को संसाधित नहीं किया जाएगा या गलत एक हो जाएगा।

यह भी सावधान रहें कि कुछ मल्टी-बाइट कैरेक्टर सेट (जैसे ǖBIG5-HKSCS) में कुछ अक्षर बाइट 0x7c के एन्कोडिंग में समाप्त होते हैं |

$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000  88  7c
        210   |
0000002

तो उस चारसेट का उपयोग करने वाले स्थानों में,

 perl -pe '' ./nǖ

उपयोगकर्ता के स्थान में उस फ़ाइल नाम की व्याख्या करने की कोशिश नहीं करेगा ./n\x88जैसा कि कमांड को चलाने की कोशिश perlकरेगा !

कैसे ठीक करें / आसपास काम करें

AFAIK, ऐसा कुछ भी नहीं है जिसे आप perlएक बार और सभी सिस्टम-वाइड के असुरक्षित डिफ़ॉल्ट व्यवहार को बदलने के लिए कर सकते हैं ।

सबसे पहले, समस्या केवल फ़ाइल नाम के प्रारंभ और अंत में वर्णों के साथ होती है। तो, जबकि perl -ne '' *या perl -ne '' *.txtएक समस्या है,

perl -ne 'some code' ./*.txt

क्योंकि सभी तर्कों अब के साथ शुरू नहीं कर रहा है ./और में अंत .txt(ऐसा नहीं -, <, >, |, अंतरिक्ष ...)। अधिक आम तौर पर, ग्लब्स के साथ उपसर्ग करना एक अच्छा विचार है ./। यह भी बुलाया फ़ाइलों के साथ समस्याओं से बचा जाता है -या -कई अन्य उपयोगिताओं के साथ शुरू होता है (और यहां, इसका मतलब है कि आपको अंत-विकल्प ( --) मार्कर की आवश्यकता नहीं है)।

मोड -Tचालू करने के लिए उपयोग करने taintसे कुछ हद तक मदद मिलती है। यह दुर्भावनापूर्ण फ़ाइल (केवल >और |मामलों, नहीं <या व्हॉट्सएप के लिए) का सामना होने पर कमांड को रद्द कर देगा ।

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

आप हर फ़ाइल पर कार्रवाई करने, उनके नाम की परवाह किए बिना चाहते हैं, तो आप उपयोग कर सकते हैं CPAN पर मॉड्यूल (दुर्भाग्य से आमतौर पर डिफ़ॉल्ट रूप से स्थापित नहीं)। यह एक बहुत छोटा मॉड्यूल है जो करता है:ARGV::readonly perl

sub import{
   # Tom Christiansen in Message-ID: <24692.1217339882@chthon>
   # reccomends essentially the following:
   for (@ARGV){
       s/^(\s+)/.\/$1/;   # leading whitespace preserved
       s/^/< /;       # force open for input
       $_.=qq/\0/;    # trailing whitespace preserved & pipes forbidden
   };
};

मूल रूप से, यह @ARGV " foo|"को उदाहरण के लिए बदलकर सुरक्षित करता है "< ./ foo|\0"

आप BEGINअपने perl -n/-pआदेश में एक बयान में ऐसा कर सकते हैं :

perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*

यहां हम इसे उस धारणा पर सरल करते हैं ./जिसका उपयोग किया जा रहा है।

कि (और का एक पक्ष प्रभाव ARGV::readonly), हालांकि वह यह है कि $ARGVमें your code hereपता चलता है कि NUL चरित्र अनुगामी।

अद्यतन 2015-06-03

perlv5.21.5 और इसके बाद के संस्करण में एक नया <<>>ऑपरेटर होता है जो इस तरह के व्यवहार करता है <>सिवाय इसके कि यह उस विशेष प्रसंस्करण को नहीं करेगा । तर्क केवल फ़ाइल नाम के रूप में माना जाएगा। तो उन संस्करणों के साथ, अब आप लिख सकते हैं:

perl -e 'while(<<>>){ ...;}' -- *

(यह मत भूलना --या उपयोग न करें ./*) इसके डर के बिना फाइलों पर ओवरराइटिंग या अप्रत्याशित कमांड चलाना।

-n/ फिर -pभी खतरनाक <>रूप का उपयोग करते हैं । और सावधान रहना सहानुभूति अभी भी पीछा किया जा रहा है, ताकि जरूरी नहीं है कि यह अविश्वसनीय निर्देशिकाओं में उपयोग करने के लिए सुरक्षित है।


2
आप उस पूरे दिन काम कर रहे हैं, मैं दांव लगाऊंगा। बहुत बढ़िया।
8

2
पर्ल के लिए अच्छा अपडेट, लेकिन यह अजीब है कि पर्ल देवों ने इसका उपयोग करने के लिए -P और -N विकल्पों को नहीं जोड़ा है (मौजूदा -p और -n को नहीं बदल सकते क्योंकि कुछ स्क्रिप्ट असुरक्षित व्यवहार पर भरोसा कर सकते हैं)
कैस

9

के अलावा @ स्टीफन Chazelas का जवाब , हम इस मुद्दे अगर हम का उपयोग के बारे में चिंता की जरूरत नहीं है -iऔर आदेश पंक्ति विकल्प:

$ perl -pe '' 'uname|'
Linux

$ perl -i -pe '' 'uname|'
Can't open uname|: No such file or directory.

क्योंकि -iविकल्प का उपयोग करते समय, प्रक्रिया से पहले फ़ाइल स्थिति की जांच करने के लिए स्टेट का perlउपयोग किया जाता है:

$ strace -fe trace=stat perl -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
Process 6106 attached
Linux
Process 6105 suspended
Process 6105 resumed
Process 6106 detached
--- SIGCHLD (Child exited) @ 0 (0) ---

$ strace -fe trace=stat perl -i -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("uname|", 0x785f40)                = -1 ENOENT (No such file or directory)
Can't open uname|: No such file or directory.

1
क्या statचेक और प्रभावी पर्ल प्रोसेसिंग के बीच एक संभावित दौड़ की स्थिति नहीं है ?
टॉटर

@ टोटर: मुझे नहीं लगता।
cuonglm

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