python和java反射_关于python类型创建、反射(自醒)与反序列化

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

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

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

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

1 classA(object):2 def __reduce__(self):3 do_something()

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

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

1 classhuman1():2 def __init__(self):3 pass

4

5 classhuman2(object):6 def __init__(self):7 pass

8

9 h1 =human1()10 h2 =human2()11 printdir(h1)12 printdir(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 classmyclass1(object):2 def __init__(self,*args,**kwargs):3 do_something()

4 myclass2 =myclass15 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 deffunc():11 os.system("id")12 setattr(obj,"func",func)13 #调用可以obj.func()

14 deffunc(obj):15 this =obj16 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 classperson(object):2 defrun(self):3 importos4 os.system("id")5 getattr(person,"run")(person())6 person.__getattribute__(person,"run")(person())

2、对于对象:

1 classperson(object):2 def __init__(self,):3 pass

4 defrun(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等传输,会导致这类漏洞,需要特别注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值