zoukankan      html  css  js  c++  java
  • 关于python类型创建、反射(自醒)与反序列化

    一、反序列化漏洞与新式类

    在pickle和cPickle以及shelve这三个序列化类中,想要构造反序列化漏洞执行命令或者代码,都需要用到新式类。

    shelve其实底层就是调用的pickle和cPickle,不过是在此基础上加了一层封装罢了。

    而且要用到__reduce__这个魔法函数:

    1 class A(object):
    2     def __reduce__(self):
    3         do_something()

    这个魔法函数当反序列化时候对返回一个元祖,其中第一个是可调用的对象,第二个是可调用对象的参数对象,这个返回值在反序列化时候会被执行。

    为什么必须是新式类呢,看一下这个代码就知道了

     1 class human1():
     2     def __init__(self):
     3         pass
     4 
     5 class human2(object):
     6     def __init__(self):
     7         pass
     8 
     9 h1 = human1()
    10 h2 = human2()
    11 print dir(h1)
    12 print dir(h2)
    13 
    14 """
    15 ['__doc__', '__init__', '__module__']
    16 ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    17 """

    因为经典类默认是没有__reduce__的,新式类默认有,目的就是为了帮助pickle,你重写才有意义。

    当然类本事也可以作为参数,也可序列化反序列化,但是还没找到哪一个内置函数会在类本身被反序列话的时候运行,就像对于实例来说的__reduce__一样。

    二、关于python的反射特性和自醒特性:

    大家都知道在java中关于invoker的相关东西,为java反序列化构造反射链立下了汗马功劳,在python中也有类似的功能设计。

    这里要涉及到python的一个模块:inspect,起作用与java的反射特点类似。

    首先看一下类和实例的创建

     1、对于类:

    1 class myclass1(object):
    2     def __init__(self,*args,**kwargs):
    3         do_something()
    4 myclass2 = myclass1
    5 myclass3 = myclass1.__class__
    6 myclass4 = pickle.loads(pickle.dumps(myclass1))
    7 myclass5 = getattr(sys.modules[__name__],'myclass1'

    2、对于实例:

    1 a = myclass1(1)
    2 a = eval("{0}({1})".format("myclass1","2"))
    3 a = cPickle.loads(cPickle.dumps(myclass1))(2)
    4 a = getattr(sys.modules[__name__],'myclass1')(3)

    上面的都成创建实例。

    注:python的eval是代码执行的函数,类似php

    1 eval("os.system('id')")

    当然还有一种方法创建实例和类就是globals()[myclass1]()创建类,globals()[myclass1]()(5)创建实例。

    3、下面正式来讲反射,三要素,获取类,获取方法、执行

    3.1、获取类:

    3.1.1、获取本身的类:

    1 #对象实例obj
    2 obj.__class__

    3.1.2、获取父类

    1 #实例对象obj,类myclass
    2 #一层继承:返回tuple
    3 obj.__class__.__bases__
    4 myclass.__bases__
    5 #多层继承:
    6 obj.__class__.__bases__[0].__bases__
    7 myclass.__bases__[0].__bases__

    3.2、获取属性和方法:

    3.2.1、获取方法名字:

    1 #obj实例对象名称或者类名称
    2 dir(obj)

    3.2.1 验证存在性与获取属性方法

     1 #obj为实例或者类对象
     2 #判断是否存在
     3 hasattr(obj,"run")
     4 #获取:
     5 getattr(obj,"run")
     6 #返回属性或者函数对象可以调用
     7 #设置:
     8 setattr(obj,"flag","1")
     9 #obj.flag = 1
    10 def func():
    11     os.system("id")
    12 setattr(obj,"func",func)
    13 #调用可以obj.func()
    14 def func(obj):
    15     this = obj
    16     do_something(this)
    17 setattr(obj,"func",func)
    18 obj.func(obj)

    3.3调用:

    1 #调用属性:
    2 getattr(obj,"name")
    3 #调用方法:
    4 getattr(obj,"func")()

    知道了2中的种种,其实python也是可以构造自己的反射链的。

    三、反序列化与getattribute和getattr函数

    之前的博客提到了pyyaml的反序列化漏洞就是由getattr()引起的,获得了函数并执行,导致了被攻击。

    在返序列化中遇到getattribute,他是getattr的新式类版本,下面来看对于类和对象上这两个函数的区别

    1 对于类:

    1 class person(object):
    2     def run(self):
    3         import os
    4         os.system("id")
    5 getattr(person,"run")(person())
    6 person.__getattribute__(person,"run")(person())

    2、对于对象:

    1 class person(object):
    2     def __init__(self,):
    3         pass
    4     def run(self):
    5         os.system("id")
    6 p = person()
    7 print getattr(p,"run")()
    8 print p.__getattribute__("run")()

    以上都可以导致命令执行,或者代码执行。

    这样python的反序列化其实就和java的差不多了,java有很多中间件,都是大项目,如果python也有这样的组件家族的话相信,会有复杂的反射链和多种利用方式,从目前来看,对于python发序列化漏洞比较多的还是web,所以使用base64和xml等传输,会导致这类漏洞,需要特别注意。

  • 相关阅读:
    位记录——Windows 7已安装Sublime Text 3、cynwin、SublimeClang
    尺度空间(Scale space)理论
    D3DXMatrixMultiply 函数
    素数推断算法(高效率)
    去除win7 64位系统桌面图标小箭头
    Bag标签之中的一个行代码实行中文分词实例1
    7个最好的免费杀毒软件下载
    利用Excel批量高速发送电子邮件
    Hibernate Criterion
    IOS新手教程(二)-控制流
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/8483863.html
Copyright © 2011-2022 走看看