动态代码审计的用处
- 大型项目代码结构复杂
- 有些危险的功能隐藏较深(危险的定时计划任务、sqlite数据库任意创建导致任意文件覆盖……)
- 提高效率,希望通过一些黑盒的方法比较快速的找到漏洞。
常见漏洞分类
- 数据库操作
- 敏感函数的调用和传参
- 文件读写操作
- 网络访问操作
正文目录
- 数据库general log 日志
- hook关键函数
- 结合auditd
- http盲攻击
- fuzzing
数据库日志
general-log是记录所有的操作日志,不过他会耗费数据库5%-10%的性能,所以一般没什么特别需要,大多数情况是不开的,例如一些sql审计和代码审计等,那就是打开来使用了
Mysql通过命令行的方式打开general log:
set global general_log_file=''; set global general_log=on;
Postgresql 通过编辑配置文件打开general log:
编辑:postgresql.conf
log_directory = 'pg_log' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_statement = 'all'
打开之后用burp向web api发送一些包含sql注入的畸形数据
利用Linux的grep指令过滤出sql执行中的ERROR关键字,就可以很快的找到sql注入漏洞
Hook关键函数
根据基于python的自动化代码审计和pyekaboo这两个文章的启发而来
Python对象可以被轻易的改变,通过设置PYTHONPATH这个环境变量,使python在加载string这个模块的时候优先加载我自定义的string模块,下图演示的是劫持string模块的upper函数
之后我的思路是,通过劫持python的函数,把输入到危险函数的参数输出到日志中,最后调用正常的python函数
这样就可以劫持我们认为敏感的函数
劫持模块的demo:
import imp import sys class _InstallFcnHook(object): def __init__(self,fcn): self._fcn=fcn def _pre_hook(self,*args,**kwargs): print "hook:"+str(args) return (args,kwargs) def __call__(self,*args,**kwargs): (_hook_args,_hook_kwargs)=self._pre_hook(*args,**kwargs) retval=self._fcn(*_hook_args,**_hook_kwargs) return retval fd,pathname,desc=imp.find_module(__name__,sys.path[::-1]) mod =imp.load_module(__name__,fd,pathname,desc) system=_InstallFcnHook(system)
这就意味着我们可以劫持危险的函数,把参数输出到日志里面,通过日志信息,可以判断这些参数是否可以被输入控制。通过这种方式可以方便找到ssti、pickle反序列化漏洞和命令执行漏洞等其他的漏洞
而且这些可以很方面的拓展到其他的模块中
- cd hook/ #进入到hook模块所在目录
- cp os.py xxx.py #把os模块复制一份,xxx模块是你想hook的模块
- 编辑xxx.py :注释掉原来被hook的函数,添加想要hook的函数,下面的示例是hook了subprocess模块中check_call函数
Ps:需要填一些坑:
-
修改启动代码从shell中启动python web
因为有一些python web是从wsgi中启动的,这些只要简单修改启动代码就可以从WSGI方式启动切换到shell启动 -
从内存中删掉已加载的模块
一些模块通过import动态导入,需要在动态导入后通过del modules删掉被装载的模块 -
关闭调试选项
例如在flask启动时将debug选项设置为false,否则会产生两个python进程 -
其他问题
Python web性能下降、代码不兼容、有些模块无法被hook,其中python的内置函数open就无法通过这样的方式被hook。
结合Auditd
网上有很多方法去获取python web的文件读写操作,其中有一种是在文件读写函数前面添加装饰器,但是我觉得那种方法太过于烦琐,且不能覆盖到所有的文件读写操作,那怎么不通过修改原始代码去获取文件读写操作?
可以利用Auditd:
auditd(或 auditd 守护进程)是Linux审计系统中用户空间的一个组件,其可以记录Linux中文件,进程等操作,且安装方便
CentOS 默认安装
Ubuntu 安装:apt-get install auditd
只要简单的配置就可以监视一些文件操作
sudo auditctl -a exclude,always -F msgtype!=PATH -F msgtype!=SYSCALL #记录文件操作 sudo auditctl -a always,exit -F arch=b64 -S execve -k rule01_exec_command #记录所有的shell指令的执行 sudo auditctl -a always,exit -F pid=$mypid #记录指定进程文件操作
只要发送一些包含目录跳转的畸形数据给webapi,如有任意文件读取的漏洞就可以很快的发现。
因为Auditd日志中包含大量其他的日志,通过grep和关键字高亮工具(https://github.com/paoloantinori/hhighlighter)进行查看日志(grep过滤PATH,高亮name)
这样就可以找到:
- 任意文件上传
- 任意文件创建
- 任意文件读取
- 任意文件删除
http盲攻击
怎么解决诸如ssrf等网络操作的问题?
ssrf攻击可以让黑客越过防火墙来探测或者攻击一个大型企业的内网
那么在动态代码审计过程中就可以通过构造特定的poc,来探测代码中是否有对应的漏洞
可以构造请求dns解析的数据
1.命令执行的常见形式
Ping –c 1 xxx.pw
2.ssrf的常见形式
url=http://xxx.pw
3.xxe的常见形式
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xdsec [ <!ELEMENT methodname ANY > <!ENTITY xxe SYSTEM "http://xxxx.pw/text.txt" >]> <methodcall> <methodname>&xxe;</methodname> </methodcall>
通过dns日志的记录可以很快找到诸如ssrf、xxe、命令执行等,包括可以找到一些隐藏的比较深的定时计划任务的中漏洞
fuzzing
做完上面的一些工作之后,我在想如何提高我的工作效率,毕竟我们部门产品众多,但是代码审计这个工作只有我一个在做。我把正常数据,畸形数据,poc数据,等其他数据全发给web api,然后在审计数据库日志,危险函数日志,auditd日志,dns日志,web报错日志,希望能从日志中发现潜藏的漏洞
利用burp的intruder这个功能就可以实现,测试用例可以使用wooyun提供的fuzzing数据
Ps:还是有几个自己需要处理的问题
- 需要根据自己的业务类型制定自己的测试用例
- 自己要想办法处理产生的大量的日志
- 其他问题
未来要做的事情
- 自动化部署客户端
- 开发一个日志处理平台
- 尽可能的覆盖更多的漏洞类型
- 丰富测试用例
- 开源 ( https://github.com/niexinming/python_hook)