你驻足于春色中,于那独一无二的春色之中.
一直想用Python的上层覆盖机制HOOK关键函数来实现一个RASP,最近有时间收集了这方面的一些资料。
RASP (Runtime application self-protection),运行时应用自我保护。很早之前提出的一个防御概念,将防御注入到应用程序中,不需要修改原有应用的业务代码即可实现对原有应用的防护。
详细概念参考绿盟的这篇讲解:
http://blog.nsfocus.net/rasp-tech/#RASP-2
Python HOOK 函数劫持打算通过 Python 动态分析中用到的命名空间覆盖的机制,对危险函数及类操作进行中转重写。其实相当于
相应的技术参考下面篇技术:
模块函数 hook 可以直接通过覆盖劫持的方式进行,这种情况适用于面向过程以函数为主的模块。
示例如下,这里为了环境方便,直接在 umarfarook882 的一个 web demo 上进行修改测试(其实他在视频里已经展示了自己针对不同语言实现的RASP,但是 github 上只放出了测试环境,并未提供RASP代码)。
首先是一个命令执行的测试页面,现在我们希望不修改代码,直接在应用中内嵌防御模块。
命令执行的实现代码如下:
1 | def post(self): |
通过 hook 关键 os 函数 popen,可以实现一个针对命令执行的防御,详细代码如下:
1 |
|
其中 _InstallFcnHook 类实现了对应模块函数的劫持,_load_and_regisqter_as 函数则相当于是一个重定向的加载,加载完成后,对相应的函数进行覆盖。
而RASP就可以在覆盖的过程中,对整个应用调用前和调用后的参数进行获取,进而进行判断和阻断。这里需要注意的是,由于原来的代码使用 popen 来做命令执行的复现,因此这里劫持时需要返回一个 file 对象,又由于 os 模块自带 open 的机制和 io.open 不同,所以需要我们使用 io.open 重新生成一个 file 对象,在命中过滤规则时重写原有的 file 对象,也就是下面这段代码。
1 | def _post_hook(self, retval, *args, **kwargs): |
我们先判断传递进来的命令是否命中规则(作为demo,这里仅以 whoami 为例),如果命中规则,就更改返回对象。这里选择了在命令执行后阻断结果回显,还有许多命令显然需要在执行前进行阻断,因此这一类操作就需要在 _pre_hook 中编写相应的防御代码。
(由于最新的一篇论文阅读笔记发布,该部分实验未完待续~~)