शैल अंकगणितीय मूल्यांकन में असमान डेटा का उपयोग करने के सुरक्षा निहितार्थ


19

हाल ही में एक प्रश्न के लिए एक टिप्पणी में , स्टीफन चेज़लस ने उल्लेख किया है कि अंकगणित के दोहरे कोष्ठक के लिए सुरक्षा निहितार्थ हैं:

x=$((1-$x))

अधिकांश गोले पर।

मेरे Google कौशल में जंग लग रही है और मुझे कुछ भी नहीं मिल रहा है। डबल कोष्ठक अंकगणित के सुरक्षा निहितार्थ क्या हैं?

जवाबों:


24

समस्या उन मामलों में है जहां सामग्री $xको साफ नहीं किया गया है और इसमें ऐसे डेटा शामिल हैं जो संभावित रूप से ऐसे मामलों में हमलावर के नियंत्रण में हो सकते हैं जो शेल कोड अंत में एक विशेषाधिकार वृद्धि के संदर्भ में इस्तेमाल किया जा सकता है (उदाहरण के लिए एक स्क्रिप्ट द्वारा सेट की गई एक स्क्रिप्ट) अनुप्रयोग, एक सूडो स्क्रिप्ट या ऑफ-द-नेटवर्क डेटा (सीजीआई, डीएचसीपी हुक ...) को प्रत्यक्ष या अप्रत्यक्ष रूप से संसाधित करने के लिए उपयोग किया जाता है।

अगर:

x='(PATH=2)'

फिर:

x=$((1-$x)))

सेटिंग का साइड इफेक्ट PATHहै 2(एक रिश्तेदार पथ जो हमलावर के नियंत्रण में हो सकता है)। आप के PATHसाथ LD_LIBRARY_PATHया बदल सकते हैं IFS... ऐसा ही होता x=$((1-x))है bash, zsh या ksh में (डैश नहीं है और न ही यश है जो केवल वहाँ चर में संख्यात्मक स्थिरांक को स्वीकार करते हैं)।

ध्यान दें कि:

x=$((1-$x))

$xकुछ गोले के नकारात्मक मूल्यों के लिए ठीक से काम नहीं करेगा जो कि (POSIX के अनुसार वैकल्पिक) --(डीक्रिमेंट) ऑपरेटर को लागू करते हैं (जैसा x=-1कि, इसका मतलब है कि शेल को 1--1अंकगणितीय अभिव्यक्ति का मूल्यांकन करने के लिए पूछना )। अंकगणित मूल्यांकन के रूप में (पहले से नहीं) के "$((1-x))"रूप xमें विस्तारित समस्या नहीं है ।

में bash, zshऔर ksh(नहीं dashया yash), यदि xहै:

x='a[0$(uname>&2)]'

फिर उस कमांड का विस्तार $((1-$x))या $((1-x))जिसके कारण unameनिष्पादित किया जाता है (के लिए zsh, aएक सरणी चर की आवश्यकता होती है, लेकिन कोई psvarउस के लिए उदाहरण के लिए उपयोग कर सकता है)।

सारांश में, एक uninitialised नहीं उपयोग किसे करना चाहिए या गोले में गणित भाव में बाह्य डेटा (ध्यान दें कि अंकगणित मूल्यांकन करके किया जा सकता गैर स्वच्छ $((...))(उर्फ $[...]में bashया zsh), लेकिन यह भी में खोल के आधार पर let, [/ test, declare/typeset/export..., return, break, continue, exit, printf, printबिलिन, सरणी सूचकांकों, ((..))और [[...]]कुछ नाम के लिए निर्माण)।

यह जाँचने के लिए कि एक चर में शाब्दिक दशमलव पूर्णांक संख्या है, आप POSIXly का उपयोग कर सकते हैं:

case $var in
  ("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac

सावधान रहें कि [0-9]कुछ स्थानों में 0123456789 से अधिक मेल खाता [[:digit:]]है। ठीक होना चाहिए, लेकिन मैं इस पर दांव नहीं लगाऊंगा।

यह भी याद रखें कि अग्रणी शून्य के साथ संख्याओं को कुछ संदर्भों में अष्टक के रूप में माना जाता है ( 010कभी-कभी 10, कभी-कभी 8) और सावधान रहें कि उपरोक्त जांच उन संख्याओं के माध्यम से जाने देगी जो संभवतः आपके सिस्टम द्वारा समर्थित अधिकतम पूर्णांक (या जो भी आपके द्वारा दिए गए एप्लिकेशन से बड़े हैं) उस पूर्णांक का उपयोग करें, उदाहरण के लिए बैश 18446744073709551616 को 0 के रूप में मानते हैं कि 2 64 है )। तो आप उस मामले के विवरण में अतिरिक्त जांच जोड़ना चाहेंगे:

(0?* | -0?*)
  echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
  echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;

उदाहरण:

$ export 'x=psvar[0$(uname>&2)]'
$ ksh93 -c 'echo "$((x))"'
Linux
ksh93: psvar: parameter not set
$ ksh93 -c '[ x -lt 2 ]'
Linux
ksh93: [: psvar: parameter not set
$ bash -c 'echo "$((x))"'
Linux
0
$ bash -c '[[ $x -lt 2 ]]'
Linux
$ bash -c 'typeset -i a; export a="$x"'
Linux
$ bash -c 'typeset -a a=([x]=1)'
Linux
$ bash -c '[ -v "$x" ]'
Linux
$ mksh -c '[[ $x -lt 2 ]]'
Linux
$ zsh -c 'echo "$((x))"'
Linux
0
$ zsh -c 'printf %d $x'
Linux
0
$ zsh -c 'integer x'
Linux
$ zsh -c 'exit $x'
Linux

अधिक पढ़ने पर:


x='P=3'; : $(($x + 5))सेट हो जाएगा P8 के लिए, लेकिन x='P=3'; : $((x + 5))सेट हो जाएगा Pकरने के लिए 3(में zsh, kshया bash)। "ऐसा ही होता है $((x + 1))..." अभी सही नहीं है; यह पुराने के रूप में, के PATHलिए सेट हो जाएगा 2
22

@mosvy, राइट थैंक्स (और आपके पहले के एडिट के लिए)। अब ठीक हो गया।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.