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


10

एक फ़ंक्शन डेटा के साथ (या कुछ खतरनाक के रूप में) f()का उपयोग करता है eval()जो मैंने local_fileअपने प्रोग्राम को चलाने वाली मशीन पर बनाया और संग्रहीत किया है :

import local_file

def f(str_to_eval):
    # code....
    # .... 
    eval(str_to_eval)    
    # ....
    # ....    
    return None


a = f(local_file.some_str)

f() मेरे द्वारा प्रदान किए गए तार के बाद से इसे चलाना सुरक्षित है।

हालांकि, अगर मैं कभी भी इसे असुरक्षित (जैसे उपयोगकर्ता इनपुट) चीजों के लिए उपयोग करने का फैसला करता हूं तो चीजें बहुत गलत हो सकती हैं । इसके अलावा, अगर local_fileस्टॉप लोकल हो रहा है, तो यह एक भेद्यता पैदा करेगा, क्योंकि मुझे उस मशीन पर भरोसा करने की आवश्यकता होगी जो उस फ़ाइल को भी प्रदान करती है।

मुझे यह कैसे सुनिश्चित करना चाहिए कि मैं यह कभी नहीं भूलूंगा कि यह फ़ंक्शन उपयोग करने के लिए असुरक्षित है (जब तक कि विशिष्ट मानदंड पूरा नहीं किए जाते हैं)।

नोट: eval()खतरनाक है और आमतौर पर कुछ सुरक्षित द्वारा प्रतिस्थापित किया जा सकता है।


1
मैं आमतौर पर "आप ऐसा नहीं करना चाहिए" कहने के बजाय उन सवालों के साथ जाना पसंद करते हैं, लेकिन मैं इस मामले में एक अपवाद बनाऊंगा। मैं काफी निश्चित हूं कि ऐसा कोई कारण नहीं है कि आपको ईवैल का इस्तेमाल करना चाहिए। ये फ़ंक्शंस PHP-Python जैसी भाषाओं के साथ शामिल हैं, एक तरह की प्रूफ-ऑफ़-कॉन्सेप्ट के रूप में कि व्याख्या की गई भाषाओं के साथ कितना किया जा सकता है। यह मौलिक रूप से समझ से बाहर है कि आप कोड बना सकते हैं जो कोड बनाता है, लेकिन आप किसी फ़ंक्शन में उसी तर्क को कोड नहीं कर सकते। पायथन की संभावना में कॉलबैक और फ़ंक्शन बाइंडिंग हैं जो आपको ऐसा करने की अनुमति देगा
user1122069

1
" मुझे उस मशीन पर भरोसा करने की आवश्यकता होगी जो उस फ़ाइल को भी प्रदान करती है " - आपको हमेशा उस मशीन पर भरोसा करने की आवश्यकता होती है जिस पर आप अपना कोड निष्पादित कर रहे हैं।
बरगी

फ़ाइल में एक टिप्पणी यह ​​कहते हुए डालें "यह स्ट्रिंग स्पष्ट हो जाती है, कृपया यहाँ दुर्भावनापूर्ण कोड न डालें"?
user253751

@immibis एक टिप्पणी पर्याप्त नहीं होगी। मेरे पास निश्चित रूप से एक विशाल "चेतावनी: यह फ़ंक्शन फ़ंक्शन के डॉक्स में eval ()" का उपयोग करता है, लेकिन मैं इसके बजाय कुछ अधिक सुरक्षित पर भरोसा करूंगा। उदाहरण के लिए (सीमित समय के कारण) मैं हमेशा किसी फ़ंक्शन के डॉक्स को पुन: प्राप्त नहीं कर रहा हूं। न ही मुझे लगता है कि मुझे होना चाहिए। उसके जवाब में मर्फी से जुड़े तरीकों की तरह तेज़ (यानी अधिक कुशल) कुछ जानना असुरक्षित है ।
फरमी विरोधाभास

@Fermiparadox जब आप प्रश्न से बाहर निकालते हैं तो यह उपयोगी उदाहरण के बिना बन जाता है। क्या आप अब ऐसे फ़ंक्शन के बारे में बात कर रहे हैं जो जानबूझकर निरीक्षण के कारण असुरक्षित है, जैसे कि एसक्यूएल मापदंडों से बचना नहीं। क्या आपका मतलब है कि उत्पादन वातावरण के लिए टेस्ट कोड सुरक्षित नहीं है? वैसे भी, अब मैं अमोन के जवाब पर आपकी टिप्पणी पढ़ता हूं - मूल रूप से आप देख रहे थे कि अपने फ़ंक्शन को कैसे सुरक्षित किया जाए।
user1122069

जवाबों:


26

"सुरक्षित" इनपुट को सजाने के लिए एक प्रकार को परिभाषित करें। अपने फ़ंक्शन में f(), यह तर्क दें कि इस प्रकार का तर्क है या कोई त्रुटि है। एक शार्टकट को परिभाषित न करने के लिए पर्याप्त स्मार्ट बनें def g(x): return f(SafeInput(x))

उदाहरण:

class SafeInput(object):
  def __init__(self, value):
    self._value = value

  def value(self):
    return self._value

def f(safe_string_to_eval):
  assert type(safe_string_to_eval) is SafeInput, "safe_string_to_eval must have type SafeInput, but was {}".format(type(safe_string_to_eval))
  ...
  eval(safe_string_to_eval.value())
  ...

a = f(SafeInput(local_file.some_str))

जबकि इसे आसानी से दरकिनार किया जा सकता है, लेकिन दुर्घटना से ऐसा करना कठिन हो जाता है। लोग इस तरह के ड्रैकियन प्रकार की जांच की आलोचना कर सकते हैं, लेकिन वे इस बिंदु को याद करेंगे। चूँकि SafeInputप्रकार केवल एक डेटा टाइप है और ऑब्जेक्ट-ओरिएंटेड क्लास नहीं है जिसे उप-वर्गित किया जा सकता है, इसके साथ type(x) is SafeInputटाइप संगतता के लिए जाँच करने की तुलना में टाइप पहचान के लिए जाँच करना अधिक सुरक्षित है isinstance(x, SafeInput)। चूँकि हम एक विशिष्ट प्रकार को लागू करना चाहते हैं, स्पष्ट प्रकार को अनदेखा करना और सिर्फ अंतर्निहित बतख टाइपिंग करना भी यहाँ संतोषजनक नहीं है। अजगर के पास एक प्रकार की प्रणाली है, इसलिए संभव गलतियों को पकड़ने के लिए इसका उपयोग करें!


5
हालांकि एक छोटे से बदलाव की आवश्यकता हो सकती है। assertस्वचालित रूप से हटा दिया जाता है क्योंकि मैं अनुकूलित अजगर कोड का उपयोग करूँगा। जैसे कुछ if ... : raise NotSafeInputErrorचाहिए होगा।
फर्मी विरोधाभास

4
यदि आप किसी भी तरह से इस सड़क से नीचे जा रहे हैं, तो मैं दृढ़ताeval() से एक विधि को आगे बढ़ाने की सलाह दूंगा SafeInput, ताकि आपको एक स्पष्ट प्रकार की जांच की आवश्यकता न हो। विधि को कुछ नाम दें जो आपके किसी अन्य वर्ग में उपयोग नहीं किया गया है। इस तरह, आप अभी भी परीक्षण उद्देश्यों के लिए पूरी बात का मजाक उड़ा सकते हैं।
केविन

@ केविन: जैसा evalकि स्थानीय चर तक पहुंच है, यह देखते हुए यह हो सकता है कि कोड इस बात पर निर्भर करता है कि यह चर को कैसे परिवर्तित करता है। Eval को दूसरी विधि में ले जाने से, यह अब स्थानीय चरों को बदलने की क्षमता नहीं रखेगा।
सोजेरड जॉब पोस्टम्यूस

एक और कदम यह हो सकता है कि SafeInputकंस्ट्रक्टर को स्थानीय फ़ाइल का नाम / हैंडल लेना चाहिए और यह सुनिश्चित करना चाहिए कि डेटा वास्तव में स्थानीय फ़ाइल से आता है।
ओवेन

1
मुझे अजगर के साथ बहुत अनुभव नहीं है, लेकिन क्या अपवाद को फेंकना बेहतर नहीं है? अधिकांश भाषाओं में दावा किया जा सकता है और सुरक्षा के लिए डिबगिंग के लिए अधिक (जैसा कि मैं उन्हें समझता हूं)। अपवाद और कंसोल से बाहर निकलने की गारंटी है कि अगला कोड नहीं चलाया जाएगा।
user1122069

11

जैसा कि जोएल ने एक बार बताया था, गलत कोड गलत दिखते हैं (नीचे दिए गए खंड को "असली समाधान" पर स्क्रॉल करें, या बेहतर अभी तक इसे पूरी तरह से पढ़ें; यह इसके लायक है, भले ही यह फ़ंक्शन नामों के बजाय चर को संबोधित करता है)। इसलिए मैं विनम्रतापूर्वक सुझाव देता हूं कि आप अपने फंक्शन का नाम बदलकर कुछ इस तरह रखें f_unsafe_for_external_use()- आप शायद खुद कुछ संक्षिप्त योजना के साथ आएंगे।

संपादित करें: मुझे लगता है कि अमोन का सुझाव एक बहुत अच्छा है, एक ही विषय पर OO आधारित भिन्नता :-)


0

@Amon द्वारा सुझाव को लागू करते हुए, आप यहां रणनीति पैटर्न के संयोजन के साथ-साथ विधि ऑब्जेक्ट पैटर्न के बारे में भी सोच सकते हैं।

class AbstractFoobarizer(object):
    def handle_cond(self, foo, bar):
        """
        Handle the event or something.
        """
        raise NotImplementedError

    def run(self):
        # do some magic
        pass

और फिर एक 'सामान्य' कार्यान्वयन

class PrintingFoobarizer(AbstractFoobarizer):
    def handle_cond(self, foo, bar):
        print("Something went very well regarding {} and {}".format(foo, bar))

और एक व्यवस्थापक-इनपुट-eval कार्यान्वयन

class AdminControllableFoobarizer(AbstractFoobarizer):
    def handle_cond(self, foo, bar):
        # Look up code in database/config file/...
        code = get_code_from_settings()
        eval(code)

(नोट: एक वास्तविक दुनिया-ईश उदाहरण के साथ, मैं एक बेहतर उदाहरण देने में सक्षम हो सकता हूं)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.