স্ট্রিং ভেরিয়েবলের সাথে শেল কমান্ডের সুরক্ষা


9

প্রোগ্রামিং ভাষার ভিতরে আমি একটি সাধারণ শেল কমান্ড কার্যকর করি

cd var; echo > create_a_file_here

সঙ্গে Var একটি পরিবর্তনশীল যে (আশা) একটি জায়গা যেখানে আমি ফাইল "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
কি প্রোগ্রামিং ভাষা? আপনি কি পসিক্স ব্যবহার করছেন sh, বা আপনার নিজস্ব প্রোগ্রামিং ভাষাটি একটি অনুরূপ বাক্য গঠন সহ তৈরি করছেন তবে যা varআপনাকে লেখার প্রয়োজনের পরিবর্তে প্রসারিত হয় cd "$var"? নাকি এই bashসাথে shopt -s cdable_vars? ওহ, আমি মনে করি আপনি বোঝাতে চাইছেন যে অন্য কোনও প্রোগ্রাম এই কমান্ডগুলি চালানোর জন্য একটি শেল কাঁটাচ্ছে। সুতরাং কেবল উদ্ধৃতি দিন var, তবে তা নিশ্চিত করুন যে এটিতে কোনও উদ্ধৃতি চরিত্রটি অন্তর্ভুক্ত নেই ...
পিটার কর্ডেস

@ পিটারকর্ডস যদি আপনি বাশ সম্পর্কে কথা বলছেন তবে একটি ডাবল উদ্ধৃত ভেরিয়েবল যা ডাবল উদ্ধৃতি যুক্ত রয়েছে ঠিক আছে। যেমন s='"'; echo "$s"প্রিন্ট "
wjandrea

@ ডব্লিউজেআন্দ্রিয়া: হ্যাঁ, তবে অবিশ্বস্ত ইনপুট থেকে পরিবর্তনশীল অ্যাসাইনমেন্ট তৈরি করার সময় এমন কোনও "ট্রাম্প কার্ড" উদ্ধৃতি নেই যে পরাস্ত করতে পারবেন না। ওহ, সমাধান: var=untrusted stringপিতামাতার প্রোগ্রামে করুন, অনুরোধ varকরার সময় ইতিমধ্যে সেট করা একটি পরিবেশের পরিবর্তনশীল sh। তারপরে আপনার প্রতিটি বার এটি প্রসারিত হওয়ার সাথে সাথে কেবল এটি উদ্ধৃত করা উচিত যা নির্ভরযোগ্যভাবে করা সম্ভব। আহ, আমি দেখতে পাচ্ছি যে ধারণাটি ইতিমধ্যে স্টাফেনের উত্তর> এর অংশ part <
পিটার কর্ডেস

উত্তর:


9

যদি আমি সঠিকভাবে বুঝতে পারি তবে varএটি আপনার প্রোগ্রামিং ভাষার একটি পরিবর্তনশীল।

আর তোমার প্রোগ্রামিং ভাষা, আপনি একটি স্ট্রিং এর সংযুক্তকরণের যে ব্যাখ্যা করা একটি শেল বলছি "cd ", যে পরিবর্তনশীল বিষয়বস্তু এবং "; echo > create_a_file_here"

তা হলে, হ্যাঁ, যদি বিষয়বস্তু varশক্তভাবে নিয়ন্ত্রণ না করা হয় তবে এটি একটি কমান্ড ইঞ্জেকশন দুর্বলতা।

আপনি শেলটির বাক্য গঠনতে ভেরিয়েবলের বিষয়বস্তুটি যথাযথভাবে চেষ্টা করতে এবং যথাযথভাবে উদ্ধৃত করতে পারেন তাই এটি cdবিল্টিনে একক যুক্তি হিসাবে পাস করার গ্যারান্টিযুক্ত ।

আরেকটি উপায় হ'ল সেই পরিবর্তনশীলটির বিষয়বস্তু অন্যভাবে পাস করা। একটি সুস্পষ্ট উপায় হ'ল এটি একটি পরিবেশের ভেরিয়েবলের মধ্যে পাস করা। উদাহরণস্বরূপ, সি তে:

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 && ....");

¹ দ্রষ্টব্য যে কেবল একটি 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])। সি এর পরিবর্তে system(), ব্যবহার করুন fork()এবং exec()(বা এটি করে এমন একটি গ্রন্থাগার সন্ধান করুন)।

আপনার যদি শেলটি ব্যবহার করতে হয়, কমান্ড লাইন আর্গুমেন্টগুলি উদ্ধৃত করুন বা স্টাফেনের উত্তরের মতো পরিবেশের মধ্য দিয়ে দিন । এছাড়াও, যদি আপনি নিজেকে বিশেষ অক্ষর সম্পর্কে উদ্বেজক খুঁজে, সঠিক সমাধান হয় না ফিল্টার করার জন্য (কালোতালিকা) বিপদজনক অক্ষর চেষ্টা করি, কিন্তু কেবল রাখা পরিচিত অক্ষর নিরাপদ হতে (পরিচ্ছন্ন তালিকা)।

কেবলমাত্র সেই চরিত্রগুলিকে মঞ্জুরি দিন যার কার্যাবলী আপনি জানেন, সেভাবে কিছু হারিয়ে যাওয়ার ঝুঁকি কম থাকে। শেষ ফলাফলটি হতে পারে আপনি কেবল অনুমতি দেওয়ার সিদ্ধান্ত নেন [a-zA-Z0-9_], তবে এটি কাজটি করার জন্য যথেষ্ট। আপনি এটিও পরীক্ষা করে দেখতে চাইতে পারেন যে আপনার লোকেল এবং টুলসেটে এর মতো äএবং এর öমধ্যে উচ্চারণযুক্ত অক্ষর নেই । এগুলি সম্ভবত কোনও শেল দ্বারা বিশেষ হিসাবে বিবেচনা করা হয় না, তবে আবার, তারা পাস করেছে কি না তা নিশ্চিত হওয়া ভাল।


1
এবং নিশ্চিত হয়ে নিন যে আপনি যেটির সাথে মেলে যা ব্যবহার [a-zA-Z0-9]করেন àতার মধ্যে এমন কিছু অন্তর্ভুক্ত হয় না যার মতো এনকোডিং bashকিছু লোকেলগুলিতে কিছু শেল (যেমন ) দ্বারাও ভুল ব্যাখ্যা করা যেতে পারে ।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলারা (আগ্রহের বাইরে :) তারা কি (এবং কেবল প্রভাবিত লোকেলের অধীনে?)
উইলফ

10

প্রোগ্রামিং ল্যাঙ্গুয়েজে শেল কমান্ড কার্যকর করার চেয়ে জিনিসগুলি করার আরও ভাল উপায় থাকা উচিত। উদাহরণস্বরূপ, cd varআপনার প্রোগ্রামিং ভাষার সমতুল্যটির সাথে প্রতিস্থাপনের chdir (var);বিষয়টি নিশ্চিত করা উচিত যে কোনও কৌশল varশুধুমাত্র অনিচ্ছাকৃত এবং সম্ভবত দূষিত পদক্ষেপের পরিবর্তে "ডিরেক্টরি খুঁজে পাওয়া যায় না" ত্রুটির ফলস্বরূপ।

এছাড়াও, আপনি ডিরেক্টরি পরিবর্তনের পরিবর্তে পরম পাথ ব্যবহার করতে পারেন। ডিরেক্টরি নাম, স্ল্যাশ এবং আপনি যে ফাইলের নামটি ব্যবহার করতে চান তা কেবল যুক্ত করুন।

সি তে, আমি এর মতো কিছু করতে পারি:

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