"এমন কোনও কমান্ড চালান যা অবিশ্বস্ত ডেটা কমান্ডগুলিতে পাস করবে যা আর্গুমেন্টকে আদেশ হিসাবে ব্যাখ্যা করে"


18

অনুসন্ধানকারীর ম্যানুয়াল থেকে:

উদাহরণস্বরূপ এই দুটি কমান্ডের মতো নির্মাণ

# risky
find -exec sh -c "something {}" \;
find -execdir sh -c "something {}" \;

খুব বিপজ্জনক। এর কারণ হ'ল '{।' ফাইলের আকারে প্রসারিত হয়েছে যার মধ্যে একটি সেমিকোলন বা শেল থেকে আলাদা অন্যান্য অক্ষর থাকতে পারে। উদাহরণস্বরূপ যদি কেউ ফাইল তৈরি করে /tmp/foo; rm -rf $HOMEতবে উপরের দুটি কমান্ড কারওর হোম ডিরেক্টরি মুছে ফেলতে পারে।

সুতরাং এই কারণেই এমন কোনও কমান্ড চালাবেন না যা অবিশ্বস্ত ডেটা (যেমন ফাই লেসের নাম) আদেশগুলিতে দেয় যা আর্গুমেন্টকে আরও ব্যাখ্যা করার জন্য আদেশ হিসাবে ব্যাখ্যা করে (উদাহরণস্বরূপ 'sh')।

শেলটির ক্ষেত্রে, এই সমস্যার জন্য একটি চৌকস কাজ রয়েছে:

# safer
find -exec sh -c 'something "$@"' sh {} \;
find -execdir sh -c 'something "$@"' sh {} \;

এই সমস্যাটি প্রতিটি সমস্যা এড়াতে গ্যারান্টিযুক্ত নয়, তবে শেল কমান্ডের পাঠ্যে আক্রমণকারীর পছন্দের ডেটা স্থাপনের চেয়ে এটি অনেক বেশি নিরাপদ।

  1. সমস্যার find -exec sh -c "something {}" \;প্রতিস্থাপনের ক্ষেত্রে {}কী প্রতিস্থাপনটি অব্যক্ত এবং একক স্ট্রিং হিসাবে বিবেচনা করা হয় না?
  2. সমাধানে find -exec sh -c 'something "$@"' sh {} \;,

    • প্রথমটি {}প্রতিস্থাপন করা হয়েছে, তবে যেহেতু {}অব্যক্ত নয় "$@", মূল কমান্ডের মতো একই সমস্যাও নেই? উদাহরণস্বরূপ, "$@"প্রসারিত হবে "/tmp/foo;", "rm", "-rf", এবং "$HOME"?

    • কেন {}পালানো বা উদ্ধৃত হয় না?

  3. আপনি কি অন্যান্য উদাহরণ দিতে পারেন (যদি এখনও sh -cপ্রযোজ্য তবে তা সহ বা এটি ছাড়াও; findযা প্রয়োজনীয় বা নাও হতে পারে) যেখানে একই ধরণের সমস্যা এবং সমাধান প্রয়োগ করা হয়, এবং যা ন্যূনতম উদাহরণ যা আমরা সমস্যার সাথে সমাধান করতে এবং সমাধানের দিকে মনোনিবেশ করতে পারি সামান্য বিভ্রান্তি সম্ভব? দেখুন উপায় কমান্ড `ব্যাশ -c` দ্বারা সঞ্চালিত আর্গুমেন্ট প্রদান

ধন্যবাদ।


উত্তর:


29

এটি সত্যই উদ্ধৃতি সম্পর্কিত নয়, বরং যুক্তি প্রক্রিয়াকরণের সাথে সম্পর্কিত।

ঝুঁকিপূর্ণ উদাহরণ বিবেচনা করুন:

find -exec sh -c "something {}" \;
  • এই ছয় শব্দের মধ্যে শেল, এবং বিভক্ত দ্বারা পার্স করা হয়: find, -exec, sh, -c, something {}(কোন কোট আর), ;। প্রসারিত করার মতো কিছুই নেই। শেলটি findসেই ছয়টি শব্দের সাথে আর্গুমেন্ট হিসাবে চলে।

  • যখন findপ্রক্রিয়া খুঁজে বের করে কিছু বলার থাকলে foo; rm -rf $HOME, এটা প্রতিস্থাপন {}সঙ্গে foo; rm -rf $HOMEরান এবং shআর্গুমেন্ট সহ sh, -cএবং something foo; rm -rf $HOME

  • shএখন দেখুন -cএবং ফলাফল হিসাবে বিশ্লেষণ করে something foo; rm -rf $HOME( প্রথম প্রথম অ-বিকল্প যুক্তি ) এবং ফলাফলটি কার্যকর করে।

নিরাপদ রূপটি বিবেচনা করুন:

find -exec sh -c 'something "$@"' sh {} \;
  • শেল রান findআর্গুমেন্ট সহ find, -exec, sh, -c, something "$@", sh, {}, ;

  • এখন যখন findখুঁজে বের করে foo; rm -rf $HOME, এটা প্রতিস্থাপন {}আবার, এবং রান shআর্গুমেন্ট সহ sh, -c, something "$@", sh, foo; rm -rf $HOME

  • shদেখেন -c, আর পার্স something "$@"কমান্ড চালানোর জন্য, এবং shএবং foo; rm -rf $HOMEঅবস্থানগত পরামিতি (যেমন থেকে শুরু$0 ), বিস্তৃতি "$@"করার foo; rm -rf $HOME একটি একক মান হিসাবে , এবং রান somethingএকক আর্গুমেন্ট সহ foo; rm -rf $HOME

আপনি এটি ব্যবহার করে দেখতে পারেন printf। একটি নতুন ডিরেক্টরি তৈরি করুন, এটি প্রবেশ করুন এবং চালান

touch "hello; echo pwned"

নীচে প্রথম বৈকল্পিক চলমান

find -exec sh -c "printf \"Argument: %s\n\" {}" \;

উত্পাদন করে

Argument: .
Argument: ./hello
pwned

যেখানে দ্বিতীয় বৈকল্পিক, হিসাবে চালান

find -exec sh -c 'printf "Argument: %s\n" "$@"' sh {} \;

উত্পাদন করে

Argument: .
Argument: ./hello; echo pwned

নিরাপদ রূপে, কেন {}পালানো বা উদ্ধৃত করা হয় না?
টিম

1
এটি সাধারণত উদ্ধৃত করা প্রয়োজন হয় না; এটির শেলটি কেবল উদ্ধৃত করা দরকার যেখানে এটির কিছু অন্য অর্থ রয়েছে এবং আমি মনে করি না আজকাল ব্যবহৃত প্রধান শেলগুলির সাথে এটিই ঘটেছে।
স্টিফেন কিট

Gnu.org/software/findutils/manual/html_mono/… থেকে : "এই দুটি নির্মাণ ( ;এবং {}) পালাতে হবে (একটি '\' দিয়ে) বা শেল দ্বারা সম্প্রসারণ থেকে তাদের রক্ষা করতে উদ্ধৃতি দেওয়া উচিত।" আপনি কি বোঝাতে চান যে এটি ব্যাশের জন্য ভুল?
টিম

3
আমি বলতে চাইছি এটি সাধারণ শাঁসের জন্য ভুল। পসিক্স দেখুন । findutilsম্যানুয়ালটিতে সেই নির্দিষ্ট বিবৃতিটি কমপক্ষে 1996-এর পূর্ববর্তী ... অবশ্যই এটি উদ্ধৃতিতে কোনও ক্ষতি করে না {}, হয় '{}'বা হিসাবে হয় "{}", তবে এটি প্রয়োজনীয় নয়।
স্টিফেন কিট

@ টিম আপনি একটি সাধারণ পরিস্থিতিটি অনুভব করছেন যেখানে আপনার অন্তর্দৃষ্টি এখনও হিসাবরক্ষণ করছে না যে এখানে দুটি খুব ভিন্ন ধরণের তর্ক-প্রক্রিয়াকরণ চলছে: কখন / কীভাবে শেল আর্গুমেন্টকে পাঠ্য রেখার বাইরে ফেলে দেয় (যা / কাটা অপারেটিং সিস্টেম আর্গুমেন্ট পাসিং (যেখানে কোটগুলি কেবলমাত্র নিয়মিত অক্ষর) থেকে পৃথক পৃথক। শেল কমান্ডে find some/path -exec sh -c 'something "$@"' {} \;আসলে আর্গুমেন্ট প্রসেসিং / পাসিংয়ের তিনটি স্তর রয়েছে, শেলটির দুটি এবং বেসিক কাঁচা অপারেটিং সিস্টেমের বিভিন্ন ধরণের একটি।
mtraceur

3

অংশ 1:

find কেবল পাঠ্য প্রতিস্থাপন ব্যবহার করে।

হ্যাঁ, আপনি যদি এটি উদ্বিগ্ন না করে থাকেন তবে:

find . -type f -exec sh -c "echo {}" \;

এবং আক্রমণকারী নামক একটি ফাইল তৈরি করতে সক্ষম হয়েছিল ; echo owned, তবে এটি কার্যকর করে

sh -c "echo ; echo owned"

যা চলমান শেল স্থাপিত হবে echoতারপর echo owned

তবে আপনি যদি উক্তিগুলি যোগ করেন, আক্রমণকারী কেবলমাত্র আপনার উদ্ধৃতি শেষ করতে পারে তারপরে একটি ফাইল তৈরি করে এর পরে দূষিত কমান্ডটি প্রয়োগ করতে পারে '; echo owned:

find . -type f -exec sh -c "echo '{}'" \;

যা শেল চলমান স্থাপিত হবে echo '', echo owned

(আপনি যদি একক উদ্ধৃতির জন্য ডাবল উক্তিগুলি অদলবদল করেন তবে আক্রমণকারী অন্যান্য ধরণের উদ্ধৃতিও ব্যবহার করতে পারে))


অংশ ২:

ইন find -exec sh -c 'something "$@"' sh {} \;, {}প্রাথমিকভাবে শেল দ্বারা ব্যাখ্যা করা হয় না, এটি সরাসরি দিয়ে কার্যকর করা হয় execve, সুতরাং শেল কোট যুক্ত করা কোনও উপকারে আসবে না।

find -exec sh -c 'something "$@"' sh "{}" \;

কোনও প্রভাব নেই, যেহেতু শেলটি চলার আগে ডাবল উক্তিটি ফেলা করে find

find -exec sh -c 'something "$@"' sh "'{}'" \;

উদ্ধৃতি যোগ করে যে শেলটি বিশেষভাবে আচরণ করে না, তাই বেশিরভাগ ক্ষেত্রে এর অর্থ কেবল কমান্ডটি যা চায় তা করবে না।

এটি প্রসারিত করতে হচ্ছে /tmp/foo;, rm, -rf, $HOMEএকটি সমস্যা হওয়ার কথা নয়, কারণ যারা আর্গুমেন্ট something, এবং somethingসম্ভবত কমান্ড চালানো তার আর্গুমেন্ট আচরণ করে না।


পার্ট 3:

আমি অনুমান অনুরূপ বিবেচনার কিছু উদাহরণস্বরূপ অবিশ্বস্ত ইনপুট নেয় এবং (অংশ) কমান্ড যেমন চালায়, জন্য আবেদন xargsএবং parallel


xargsশুধুমাত্র যদি বিপজ্জনক -Iবা -Jব্যবহার করা হয়। সাধারণ ক্রিয়াকলাপে এটি কেবল তালিকার শেষে যুক্তি যুক্ত করে, ঠিক -exec ... {} +তেমনভাবে।
চার্লস ডাফি

1
( parallel, বিপরীতে, ব্যবহারকারীর সুস্পষ্ট অনুরোধ ছাড়াই ডিফল্টরূপে একটি শেল চালিত হয়, অরক্ষিত পৃষ্ঠকে বাড়িয়ে তোলে ; এটি এমন একটি বিষয় যা অনেক বেশি আলোচনার বিষয় হয়ে দাঁড়িয়েছে ; বিশ্লেষণের জন্য unix.stackexchange.com/questions/349483/… দেখুন , এবং list.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html ) এর অন্তর্ভুক্ত লিঙ্কটি ।
চার্লস ডাফি

@ চার্লসডুফি আপনার অর্থ " দুর্বল পৃষ্ঠতল হ্রাস "। ওপি দ্বারা চিত্রিত আক্রমণটি জিএনইউ সমান্তরালের সাথে প্রকৃতপক্ষে ডিফল্টরূপে কাজ করে না
ওলে টাঙ

1
হ্যাঁ, আমি জানি যে আপনাকে এসএসএইচ জুড়ে সমতার জন্য এটি প্রয়োজন - যদি আপনি parallelকোনও সকেটের অন্য প্রান্তে কোনও রিমোট "রিসিভার" প্রক্রিয়া না করেন, সরাসরি শেল-কম করতে সক্ষম হন execv। আপনার জুতোতে যদি সরঞ্জামটি বাস্তবায়ন করা হয় তবে আমি যা করতাম তা হ'ল। একটি নন ইন্টারেক্টিভ প্রোগ্রামের বর্তমান মানটির উপর ভিত্তি করে আলাদা আচরণ SHELLকরা খুব কমই আশ্চর্যের নয়।
চার্লস ডাফি

1
হ্যাঁ - আমি ধরে রেখেছি যে পাইপগুলি এবং পুনঃনির্দেশগুলি অসম্ভব হওয়া উচিত যদি না ব্যবহারকারী স্পষ্টভাবে শেল শুরু করে, যার পর্যায়ে তারা কেবল শেলটির স্পষ্টভাবে আচরণ শুরু করে যা তারা স্পষ্টভাবে শুরু করেছিল। যদি কেউ কেবলমাত্র কী execvসরবরাহ করে তা সহজ, কম ও অবাক করা এবং একটি নিয়ম যা স্থান / রানটাইম পরিবেশের মধ্যে পরিবর্তন হয় না expect
চার্লস ডাফি

3

১. সমস্যার find -exec sh -c "something {}" \;প্রতিস্থাপনের ক্ষেত্রে {}কী প্রতিস্থাপনটি অব্যক্ত এবং একক স্ট্রিং হিসাবে বিবেচনা করা হয় না?

এক অর্থে, তবে উদ্ধৃতি এখানে সাহায্য করতে পারে না । ফাইলের পরিবর্তে প্রতিস্থাপিত হয়ে যাওয়া ফাইলের নামগুলিতে কোটগুলি সহ যে কোনও অক্ষর {}থাকতে পারে । উদ্ধৃতি দেওয়ার যে কোনও ফর্মই ব্যবহার করা হত, ফাইলের নাম একই হতে পারে এবং উদ্ধৃতিটির "ব্রেক আউট" থাকতে পারে।

২. ... তবে যেহেতু {}অব্যক্ত, তাইও "$@"মূল কমান্ডের মতো সমস্যা নেই? উদাহরণস্বরূপ, "$@"প্রসারিত হবে "/tmp/foo;", "rm", "-rf", and "$HOME"?

নং "$@"পৃথক শব্দ হিসাবে অবস্থানগত পরামিতিগুলিতে প্রসারিত হয় এবং সেগুলি আরও বিভক্ত করে না । এখানে, নিজের {}মধ্যে একটি আর্গুমেন্ট findএবং findবর্তমান ফাইলের নামটিও স্বতন্ত্র আর্গুমেন্ট হিসাবে পাস করে sh। এটি শেল স্ক্রিপ্টে ভেরিয়েবল হিসাবে সরাসরি উপলব্ধ, এটি শেল কমান্ড হিসাবে নিজেই প্রক্রিয়া করা হয় না।

... কেন {}পালানো বা উদ্ধৃত করা হয় না?

এটি বেশিরভাগ শেলগুলিতে হওয়ার দরকার নেই। আপনি যদি চালনা করেন তবে fishএটি হওয়া দরকার: fish -c 'echo {}'খালি লাইনটি প্রিন্ট করে। আপনি যদি এটি উদ্ধৃত করেন তবে তাতে কিছু যায় আসে না, শেলটি কেবল উদ্ধৃতিগুলি সরিয়ে দেবে।

৩. আপনি কি অন্যান্য উদাহরণ দিতে পারেন ...

যে কোনও সময় আপনি কোনও ফাইলের নাম (বা অন্য কোনও অনিয়ন্ত্রিত স্ট্রিং) প্রসারিত করার পরে কোনও স্ট্রিংয়ের অভ্যন্তরে থাকে যা কোনও ধরণের কোড (*) হিসাবে নেওয়া হয় , সেখানে স্বেচ্ছাসেবক কমান্ড কার্যকর হওয়ার সম্ভাবনা রয়েছে।

উদাহরণস্বরূপ, $fএটি পার্ল কোডটি সরাসরি প্রসারিত করে এবং যদি কোনও ফাইলনামে ডাবল উদ্ধৃতি থাকে তবে সমস্যা দেখা দেয়। ফাইলনামের উদ্ধৃতিটি পার্ল কোডের উদ্ধৃতিটি শেষ করবে এবং ফাইলের বাকী নামটি যে কোনও পার্ল কোড ধারণ করতে পারে:

touch '"; print "HELLO";"'
for f in ./*; do
    perl -le "print \"size: \" . -s \"$f\""
done

(ফাইলের নামটি কিছুটা অদ্ভুত হতে হবে যেহেতু পার্ল কোনও কোড চালানোর আগে পুরো কোডটিকে সামনের দিকে পার্স করে দেয়। সুতরাং আমাদেরকে একটি বিশ্লেষণ ত্রুটি এড়াতে হবে))

এটি এটি একটি আর্গুমেন্টের মাধ্যমে নিরাপদে পাস করার সময়:

for f in ./*; do
    perl -le 'print "size: " . -s $ARGV[0]' "$f"
done

(সরাসরি কোনও শেল থেকে অন্য শেলটি চালানো কোনও অর্থবোধ করে না, তবে আপনি যদি এটি করেন তবে এটি একই রকম find -exec sh ...)

(* কিছু ধরণের কোডে এসকিউএল অন্তর্ভুক্ত রয়েছে, সুতরাং বাধ্যতামূলক XKCD: https://xkcd.com/327/ প্লাস ব্যাখ্যা: https://www.explainxkcd.com/wiki/index.php/Little_Bobby_Tables )


1

আপনার উদ্বেগ হ'ল GNU সমান্তরাল উদ্ধৃতি ইনপুট:

touch "hello; echo pwned"
find . -print0 | parallel -0 printf \"Argument: %s\\n\" {}

এটি চলবে না echo pwned

এটি একটি শেল চালাবে, যাতে আপনি যদি আপনার আদেশটি প্রসারিত করেন, তবে হঠাৎ আপনি কোনও আশ্চর্য হয়ে উঠবেন না:

# This _could_ be run without spawining a shell
parallel "grep -E 'a|bc' {}" ::: foo
# This cannot
parallel "grep -E 'a|bc' {} | wc" ::: foo

স্প্যানিং-এ-শেল ইস্যু সম্পর্কে আরও তথ্যের জন্য দেখুন: https://www.gnu.org/software/parallel/parallel_design.html#Always-running-commands-in-a-hell


1
... যে বলেছিল, find . -print0 | xargs -0 printf "Argument: %s\n"ঠিক ততটাই নিরাপদ (বা বরং আরও বেশি, যেহেতু -print0নতুন লাইনের সাথে ফাইলের একটি নাম সঠিকভাবে পরিচালনা করে); সমান্তরালের উদ্ধৃতি এমন কোনও সমস্যার জন্য কাজ যা কোনও শেল উপস্থিত না থাকায় অস্তিত্ব নেই
চার্লস ডাফি

আপনি | wcকমান্ডটি যুক্ত করার সাথে সাথে এটিকে নিরাপদ করতে আপনাকে হুপসের মধ্য দিয়ে ঝাঁপিয়ে পড়তে হবে। GNU সমান্তরাল ডিফল্টরূপে নিরাপদ।
ওলে টাঞ্জ

আইটিওয়াইএম: এটি সাবধানতার সাথে সমস্ত কিছু উদ্ধৃত করার জটিল প্রক্রিয়া দ্বারা শেল ভাষার প্রতিটি কৌতুক coverাকতে চেষ্টা করে। এটি ভেরিয়েবলগুলিতে সঠিকভাবে ডেটা সঞ্চয় করার মতো নিরাপদ নয়, কোডের সাথে মিলে না। এখন, যদি এটি স্বয়ংক্রিয়ভাবে সেটি রূপান্তর ছিল foo {} | wcমধ্যে sh -c 'foo "$1" | wcSH {} `, যে বিভিন্ন হতে পারে।
ইলকচাচু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.