Python eval的常见错误封装及利用原理详解

  

最近在代码评审的过程,发现挺多错误使用eval导致代码注入的问题,比较典型的就是把eval当解析dict使用,有的就是简单的使用eval,有的就是错误的封装了eval,供全产品使用,这引出的问题更严重,这些都是血淋淋的教训,大家使用的时候多加注意。
  

  

下面列举一个实际产品中的例子,详情见[bug83055] [1]:

        def删除(请求,obj):   查询=query2dict (request.POST)   eval ([' oper_type '])查询(查询,customer_obj)      

而查询就是邮政直接转换而来,是用户可直接控制的,假如用户在url参数中输入oper_type=__import__(“操作系统”)。系统(“睡5”)则可以执行命令睡眠,当然也可以执行任意系统命令或者任意可执行代码,危害是显而易见的,那我们来看看eval到底是做什么的,以及如何做才安全?

  


  

  

简单来说就是执行一段表达式

        在在在eval (“2 + 2”)   4      在在在eval(“”“{“名称”:“小明”,“知识产权”:“10.10.10.10”}" " ")   {“ip”:“10.10.10.10”,“名字”:“小明”}      在在在eval (“__import__ (os)系统(uname)”,{})   Linux   0   之前      

从这三段代码来看,第一个很明显做计算用,第二个把字符串类型数据转换成python的数据类型,这里是dict类型,这也是咱们产品中常犯的错误。第三个就是坏小子会这么干,执行系统命令。
  

  

eval可接受三个参数,eval(源(globals[,当地人]])→值
  

  

全局必须是路径,当地人则必须是键值对,默认取系统全局和当地人

  

<强>
  

  

(1)下面我们来看一段咱们某个产品代码中的封装函数,见(bug)[2],或者网络上搜索排名比较高的代码,如:

        def safe_eval (eval_str):   试一试:   #加入命名空间   safe_dict={}   safe_dict['真的']=True   safe_dict['假')=False   返回eval ({“__builtins__”:没有},eval_str safe_dict)   除了例外,e:   traceback.print_exc ()   回报”   之前      

在这里__builtins__置为空了,所以像__import__这是内置变量就没有了,这个封装函数就安全了吗?下面我一步步道来:

  
  ,

祝辞祝辞的在dir (__builtins__)
  [' ArithmeticError’,‘AssertionError’,‘AttributeError’,‘BaseException’,‘BufferError’,‘BytesWarning’,‘DeprecationWarning’,‘EOFError’,“省略”,‘EnvironmentError’,‘异常’,‘错误’,‘FloatingPointError’,‘FutureWarning’,‘GeneratorExit’,‘IOError的那么,‘ImportError’,‘ImportWarning’,‘IndentationError’,‘IndexError’,‘KeyError’,‘KeyboardInterrupt’,‘LookupError’,‘MemoryError’,‘NameError’,‘没有’,‘NotImplemented’,‘NotImplementedError’,‘OSError’,‘OverflowError’,‘PendingDeprecationWarning’,‘ReferenceError’,‘RuntimeError’,‘RuntimeWarning’,‘StandardError’,‘抛出StopIteration’,‘SyntaxError’,‘SyntaxWarning’,‘SystemError’,‘SystemExit’,‘TabError’,‘真正的’,‘TypeError’,‘UnboundLocalError’,‘UnicodeDecodeError’,
  

     

列表项   

  

‘UnicodeEncodeError’,‘UnicodeError’,‘UnicodeTranslateError’,‘UnicodeWarning’,‘UserWarning’,‘ValueError’,‘警告’,‘ZeroDivisionError’,‘_’,“调试”,“医生”,“进口”、“名称”,“包”,“abs”、“所有”,“任何”,“应用”,“basestring”、“本”、“bool”、“缓冲区”,“中bytearray”、“字节”,“可赎回”,“空空”、“classmethod”,“cmp”、“强迫”,“编译”,“复杂的”,“版权”、“信用”、“delattr”,“东西”,“dir”、“divmod”、“列举”,“eval”、“execfile”,“退出”、“文件”、“过滤器”,‘漂浮’,‘格式’,‘frozenset’,‘getattr’,‘全局’,‘hasattr’,“散”,“帮助”,“六角”、“id”,“输入”、“int”、“实习生”,‘isinstance’,‘issubclass’,‘iter’,‘兰’,“许可”,“列表”,“当地人”,“长”,“地图”,“马克斯”,“memoryview”,“分”,“下一个”,“对象”,“10月”,“开放”,“奥德”、“战俘”、“打印”、“财产”,“退出”、“范围”,“raw_input”、“减少”,“重新加载”,“repr”、“逆转”,“圆”,“设置”,“setattr”、“切”,“排序”,“staticmethod”、“力量”,“和”,“超级”,“元组”、“类型”、“unichr”,“unicode”、“var”、“xrange”、“zip”)

Python eval的常见错误封装及利用原理详解