2012-05-18 10 views
7

मुझे एहसास है कि इस सवाल से पहले पूछा गया है, हालांकि यह मामला थोड़ा अलग है।एक पायथन वेब सर्वर पर गणितीय उपयोगकर्ता कोड निष्पादित करना, सबसे आसान सुरक्षित तरीका क्या है?

मैं एक पायथन छविबोर्ड (web.py का उपयोग करके) चलाने के लिए चाहता हूं, जो उपयोगकर्ताओं को कोड सबमिट करके नई छवियां उत्पन्न करने की अनुमति देगा। कोड एक भी समारोह है कि एक्स, एक पिक्सेल के y निर्देशांक लेता है और आर, जी, बी मान, जैसे रिटर्न के रूप में हो जाएगा:

def simpleGradient(xrel,yrel): 
    r = xrel*256 
    g = yrel*256 
    b = 0 
    return [r,g,b] 

केवल एक बहुत छोटा वाक्य रचना के लिए आवश्यक है, और यह जरूरी नहीं है कि अजगर होना चाहिए। सीमित क्षेत्र के साथ exec का उपयोग करना बहुत असुरक्षित प्रतीत होता है, और पीपीपी या वीएम का उपयोग करना अनावश्यक रूप से जटिल लगता है (मैं इन सबके लिए बिल्कुल नया हूं)।

इसे सैंडबॉक्सिंग करने की बजाय, क्या कोड को बहुत छोटी भाषा में निष्पादित करने का एक पाइथोनिक तरीका है? या तो अजगर का एक उप-समूह (पार्सिंग और श्वेतसूची?), या एक गणित उन्मुख भाषा जिसे मैं एम्बेड कर सकता हूं?

+2

मैं वास्तव में एक पीपीपी सैंडबॉक्स का उपयोग करता हूं। –

+0

मैंने पढ़े कई अन्य उत्तरों को इसके खिलाफ मतदान किया ... इसलिए मैंने वास्तव में पीपीपी में नहीं देखा है - मैं इसे देखता हूं धन्यवाद – SudoNhim

+0

महान सवाल, शायद पीपीपी जवाब है। आज लूआ की तुलना में पाइथन थोड़ी कम हो सकती है, इस बारे में आज बात कर रही थी। –

उत्तर

2

यह वह समाधान है जिसके साथ मैं गया था। इस दृष्टिकोण की सुरक्षा की चर्चा के लिए, देखें

arifwn के लिए धन्यवाद, मैं पायथन के ast (सार वाक्य रचना पेड़) मॉड्यूल की खोज में मिला है। यह मॉड्यूल पेड़ को पार करने के लिए कक्षा ast.NodeVisitor प्रदान करता है। यह कोड एक वाक्यविन्यास परीक्षक बनाने के लिए NodeVisitor उप-वर्ग बनाता है जो मूल गणित के लिए आवश्यक कोड को श्वेतसूची में डाल देता है। फ़ंक्शन कॉल और नाम विशेष रूप से निगरानी की जाती हैं, क्योंकि केवल कुछ फ़ंक्शंस की अनुमति होनी चाहिए और केवल अप्रयुक्त नामों की अनुमति होनी चाहिए।

import ast 

allowed_functions = set([ 
    #math library 
    'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 
    'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 
    'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 
    'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 
    'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 
    'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc', 
    #builtins 
    'abs', 'max', 'min', 'range', 'xrange' 
    ]) 

allowed_node_types = set([ 
    #Meta 
    'Module', 'Assign', 'Expr', 
    #Control 
    'For', 'If', 'Else', 
    #Data 
    'Store', 'Load', 'AugAssign', 'Subscript', 
    #Datatypes 
    'Num', 'Tuple', 'List', 
    #Operations 
    'BinOp', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'Compare' 
    ]) 

safe_names = set([ 
    'True', 'False', 'None' 
    ]) 


class SyntaxChecker(ast.NodeVisitor): 

    def check(self, syntax): 
     tree = ast.parse(syntax) 
     self.passed=True 
     self.visit(tree) 

    def visit_Call(self, node): 
     if node.func.id not in allowed_functions: 
      raise SyntaxError("%s is not an allowed function!"%node.func.id) 
     else: 
      ast.NodeVisitor.generic_visit(self, node) 

    def visit_Name(self, node): 
     try: 
      eval(node.id) 
     except NameError: 
      ast.NodeVisitor.generic_visit(self, node) 
     else: 
      if node.id not in safe_names and node.id not in allowed_functions: 
       raise SyntaxError("%s is a reserved name!"%node.id) 
      else: 
       ast.NodeVisitor.generic_visit(self, node) 

    def generic_visit(self, node): 
     if type(node).__name__ not in allowed_node_types: 
      raise SyntaxError("%s is not allowed!"%type(node).__name__) 
     else: 
      ast.NodeVisitor.generic_visit(self, node) 

if __name__ == '__main__': 
    x = SyntaxChecker() 
    while True: 
     try: 
      x.check(raw_input()) 
     except Exception as e: 
      print e 

ध्यान दें कि यह कोड का केवल गणितीय भाग को स्वीकार करने के लिए बनाया गया है, समारोह परिभाषा और वापसी कथन प्रदान की जाती हैं।

सभी आवश्यक सुरक्षित संरचनाओं को श्वेतसूची और विशेष रूप से आवश्यक असुरक्षित संरचनाओं को श्वेतसूची में डालने की यह विधि, पाइथन के कई उपयोगी सबसेट बनाने के लिए संशोधित की जा सकती है; उपयोगकर्ता स्क्रिप्ट के लिए उत्कृष्ट!

ध्यान दें कि इसे सुरक्षित रूप से निष्पादित करने के लिए, यह समय समाप्ति के साथ अपने स्वयं के धागे में होना चाहिए, नाम टकराव को कम करने और उपयोगकर्ता कोड एक अनंत लूप या इसी तरह उत्पन्न करता है।

+0

यह एक स्टैंडअलोन सवाल आईएमओ होना चाहिए। – TryPyPy

+0

क्षमा करें। मैं किसी ऐसे व्यक्ति को जानता हूं जो उम्मीद कर सकता है कि वह मेरे लिए जांच करे; अगर उसे यह ठीक लगता है तो मैं इसे उत्तर की तरह अधिक सुधारने के लिए पुन: स्वरूपित करूंगा। (अन्यथा मैं इसे हटा दूंगा)। – SudoNhim

+0

मेरा मतलब था: यदि आप इस उत्तर को एक नए प्रश्न में परिवर्तित करते हैं तो आपको और अधिक आंखें मिलेंगी (और शायद नए सुझाव) :) – TryPyPy