cdxy.me
Footprints on cyber security and Python

参考Skywolf原理构建Python审计工具,运行时动态获取底层函数的IO数据,并以类似WAF的规则匹配来判断漏洞是否触发。

Hook Functions

比如这样一段存在SSRF的代码:

from urllib import request
request.urlopen(input("url >"))

我们可以修改源码中的urlopen函数,添加一个判断逻辑,如果检测到输入为内网地址,就向我们的report平台报告一个漏洞。

进一步考虑函数封装关系:

requests/urllib -> httplib(Py2)/http.client(Py3) -> socket

我们选择hook socket.getaddrinfo 函数,判断其输出结果即可完成对上述函数的安全性检验。

按照这种方式,内部Hook关键函数,外部辅以黑盒扫描,即可实现某些漏洞的自动化检测。

Monkey Patch

如果直接在C或者Python层次修改源码,稳定性、可控性、工作量和源码更新都是问题。

因此我考虑在运行时动态Hook底层函数。

Python命名空间是开放的,所有类和函数都是object,Monkey patch就是在运行时修改代码,实现hot patch的一种手段。

如我们熟知的gevent

from gevent import monkey
mokey.patch_all()

Sample Code

hook系统函数的实现

  • module:模块名.
  • func:要hook的函数.
  • act:处理拦截的数据.
  • hook_arg,hook_result:判断拦截输入数据还是输出数据.

其中wrapper包裹了原生函数,并使用setattr替换掉原生函数,和装饰器类似。

def hook_func(module, func, act, hook_arg, hook_result):
    try:
        if hook_arg or hook_result:
            old_module = __import__(module)
            old_function = getattr(old_module, func)

            def wrapper(*args, **kwargs):
                if hook_arg:
                    a = list(args)
                    k = [v for k, v in enumerate(kwargs)]
                    values = a.extend(k) if k else a
                    act(values)

                result = old_function(*args, **kwargs)

                if hook_result:
                    act(result)

                return result

            setattr(old_module, func, wrapper)
        else:
            pass
    except (ImportError, AttributeError):
        pass

简单示例:patch原生的open函数来判断是否存在任意文件读取:

def check_file_path(values):
    if any('../' in path for path in values):
        raise Exception('Insecure filepath found!')

def monkey_patch():
    hook_func('builtins', 'open', check_file_path, hook_arg=True, hook_result=False)

if __name__ == '__main__':
    monkey_patch()
    open(input('enter your path >'))

这样就实现到了底层数据的拦截和处理。

2016-11-16161750.png

可以创建filter工厂实现waf、act和hook的组装,对开发者提供filter注册接口,对使用者提供patch接口,用户只需pip install然后在项目代码中加入一条import语句即可激活该审计工具。

写了个demo实现四种漏洞的检测(SSRF、文件读写、命令执行、SQLI),然而并没有什么实际需求,以后看情况再跟进。

有更优想法和建议请留言。