চলমান পার্ল - '...' * এর সুরক্ষা সম্পর্কিত প্রভাব


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

অন্যান্য আরগগুলি প্রথমে ইনলাইন স্ক্রিপ্টে নয়, আরও বেশি বিকল্পের জন্য স্ক্যান করা হয়েছে options সুতরাং, উদাহরণস্বরূপ, যদি -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

-pকোডটির while (<>)চারপাশে একটি লুপ বোঝায় (এখানে খালি)।

<>aফাইলটি শেষ হয়ে না যাওয়া এবং তারপরে খোলার আগে প্রথমে রেকর্ডগুলি একবারে এক লাইনে পড়তে হবে b...

সমস্যাটি হ'ল, ফাইলটি খুলতে, এটির প্রথম, অনিরাপদ ফর্মটি ব্যবহার করে open:

open ARGV, "the file as provided"

সেই ফর্মের সাথে যদি তর্ক হয়

  • "> afile", এটি afileলেখার মোডে খোলে ,
  • "cmd|", এটি রান করে cmdএবং এটির আউটপুট পড়ে।
  • "|cmd", আপনি ইনপুটটিতে লেখার জন্য একটি স্রোত খুলেছেন cmd

উদাহরণস্বরূপ:

perl -pe '' 'uname|'

কল করা ফাইলটির সামগ্রীর আউটপুট দেয় না uname|(পুরোপুরি বৈধ ফাইলের নাম বিটিডব্লিউ), তবে unameকমান্ডের আউটপুট ।

আপনি যদি চালাচ্ছেন:

perl -ne 'something' -- *

এবং কেউ rm -rf "$HOME"|বর্তমান ডিরেক্টরিতে (আবার একটি নিখুঁত বৈধ ফাইলের নাম) নামে একটি ফাইল তৈরি করেছেন (উদাহরণস্বরূপ কারণ সেই ডিরেক্টরিটি অন্যদের দ্বারা একবারে লেখার যোগ্য ছিল, বা আপনি একটি ডজি আর্কাইভ বের করেছেন, বা আপনি কিছু ডডি কমান্ড চালিয়েছেন, বা অন্য কোনও সফ্টওয়্যারের অন্য দুর্বলতা কাজে লাগানো হয়েছিল), তবে আপনি বড় সমস্যায় পড়েছেন। যে সমস্যাগুলিতে এই সমস্যাটি সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ সেগুলি হ'ল জনসাধারণের ক্ষেত্রে স্বয়ংক্রিয়ভাবে ফাইলগুলি প্রক্রিয়া করার /tmpসরঞ্জামগুলি (বা এমন সরঞ্জাম যা এই জাতীয় সরঞ্জামগুলির দ্বারা ডাকা যেতে পারে)।

ফাইল নামক > foo, foo|, |fooএকটি সমস্যা আছে। তবে কিছুটা হলেও < fooএবং fooশীর্ষস্থানীয় বা পিছনে থাকা ASCII ব্যবধান অক্ষরগুলি (স্থান, ট্যাব, নিউলাইন, cr ... সহ) এর পাশাপাশি সেই ফাইলগুলির প্রক্রিয়া করা হবে না বা ভুলটি হবে।

এছাড়াও সাবধান থাকুন যে কয়েকটি মাল্টি-বাইট অক্ষর সেটগুলিতে ( ǖবিআইজি 5-এইচএসসিএস-এর মতো) কিছু এনক্রোডিং বাইট 0x7 সিতে শেষ হয় |

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

সুতরাং সেই অক্ষর ব্যবহার করে লোকেলগুলিতে,

 perl -pe '' ./nǖ

./n\x88কমান্ডটি চালানোর চেষ্টা perlকরবে যেমন ব্যবহারকারীর লোকালে সেই ফাইলটির নাম ব্যাখ্যা করার চেষ্টা করা হয় না !

চারপাশে কীভাবে ঠিক করবেন / ঠিক করবেন

আফাইক, 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
   };
};

মূলত, এটি " foo|"উদাহরণস্বরূপ রূপান্তর করে @ আরজিভি স্যানিটাইজ করে "< ./ foo|\0"

BEGINআপনার perl -n/-pকমান্ডের একটি বিবৃতিতে আপনি এটি করতে পারেন :

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

এখানে আমরা এটি অনুমান ./করা হচ্ছে যা ব্যবহার করা হচ্ছে সরল ।

যে (এবং একটি পার্শ্ব প্রতিক্রিয়া ARGV::readonly) যদিও যে $ARGVমধ্যে your code hereঅনুষ্ঠান NUL চরিত্র trailing।

আপডেট 2015-06-03

perlv5.21.5 এবং তারপরে একটি নতুন <<>>অপারেটর রয়েছে যা এরকম আচরণ করে <>যে এটি বিশেষ প্রসেসিংটি করবে না । যুক্তিগুলি কেবল ফাইলের নাম হিসাবে বিবেচিত হবে। সুতরাং এই সংস্করণগুলির সাথে, আপনি এখন লিখতে পারেন:

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

ফাইলগুলি ওভাররাইট করা বা অপ্রত্যাশিত কমান্ডগুলি চালনার ভয় ছাড়াই (ভুলে যাওয়া --বা ব্যবহার করতে ভুলবেন না ./*)।

-n/ -pএখনও বিপজ্জনক <>ফর্ম ব্যবহার করুন । এবং সতর্কতা অবলম্বনগুলি এখনও অনুসরণ করা হচ্ছে, এর অর্থ এটি অবিশ্বস্ত ডিরেক্টরিগুলিতে ব্যবহার করা নিরাপদ নয়।


2
আপনি যে দিন দিন কাজ করেছিলাম, আমি বাজি থাকব। সাবাশ.
মাইকজার্ভ

2
পার্লের জন্য দুর্দান্ত আপডেট, তবে এটি আশ্চর্যের নয় যে পার্ল ডেভগুলি এর ব্যবহারের জন্য -P এবং -N বিকল্পগুলি যোগ করেনি (বিদ্যমান -p এবং -n পরিবর্তন করতে পারে না কারণ কিছু স্ক্রিপ্টগুলি নিরাপত্তাহীন আচরণের উপর নির্ভর করতে পারে)
ক্যাস

9

@ স্টাফেন চেজেলাসের উত্তর ছাড়াও , যদি আমরা -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সেই বিশেষ প্রক্রিয়াজাতকরণটি করা হয়নি।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.