Python Security Auditing (V): Runtime Code Analysis Tool
[Penetration Testing]
参考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 >'))
这样就实现到了底层数据的拦截和处理。
可以创建filter工厂实现waf、act和hook的组装,对开发者提供filter注册接口,对使用者提供patch接口,用户只需pip install
然后在项目代码中加入一条import
语句即可激活该审计工具。
写了个demo实现四种漏洞的检测(SSRF、文件读写、命令执行、SQLI),然而并没有什么实际需求,以后看情况再跟进。
有更优想法和建议请留言。