RASP技术实现

0x00 概念

运行时应用自我保护,RASP(Runtime Application Self-Protection)是一种植入到应用程序内部或其运行时环境的安全技术。它能够控制应用程序的执行流程,并且可以实时检测和阻止漏洞攻击行为。该技术可以用来通过自我保护的措施来阻止相关网络攻击,或在没有人为干预的情况下自动重新配置环境,以此来解决特定网络问题(威胁,故障等)。

WAF原理和RASP原理做比较:

WAF在边界进行规则匹配。

RASP技术在应用程序内部进行探测和规则分析,更为精准。优点:1.误报率低。2.可以防护0Day级别的漏洞攻击。缺点:1.对应用程序性能有消耗。理论上是5%~10%。

0x01 Java版本技术实现原理(OpenRASP分析)

RASP技术实现实质是在不接触应用源码的情况下,对函数进行Hook操作

而JVM提供了接口(Instrument机制),让我们操作字节码。而操作字节码用到的库,一般有ASM、Javassist等。ASM提供底层字节码操作、效率性能好。而Javassist库封装了底层操作,更加方便开发实现,百度的OpenRASP产品就是使用Javassist实现字节码修改的。

这里通过阅读OpenRASP源码(很多干货),来看看如何防护SSRF攻击的。

基于Instrument机制的字节码编织,会到rasp-boot的Agent类premain方法。

紧接着会进入EngineBootstart方法进行初始化,initTransformer(inst);就是对Java字节码进行修改的具体代码了。

这里会扫描com.baidu.openrasp.hook包下所有带注解@HookAnnotation的类,每个类负责Hook一个/多个Method。提取Method的参数,使用Javassist技术增加检测代码并植入到目标Class文件。

CustomClassTransformer类的transform方法是编织字节码的入口,加载类文件时,都会调用这个方法,判断是否时需要修改编织的类。如果是,则修改完返回字节码流。

我框出来的代码部分会调用每个Hook类的hookMethod方法。SSRF防护时,会Hook所有常见发送网络请求的函数。这一步主要获取请求参数,结合用户网络请求输入的参数,进行关联比对分析。

上图使用了Javassist库,在org/apache/commons/httpclient/URIparseUriReference方法后面添加了1行代码,调用CommonHttpClientHook.checkHttpConnection方法。参数$0$1表示调用栈里面的参数,也就是当前URI类的实例(Object)和第1个参数String original(即解析的URL)。

接着,将通过Hook函数获取的URL、HostName等重要信息放在Map中,供检测攻击使用。Checker代码大部分作为扩展在JS里面实现,而SSRF检测代码在Java中实现了。

可以看到,检测算法是:

  • 遍历每个request层面拦截到的用户输入参数(parameterMap),与拦截的URL比较。如果相同,则可判断是用户输入的URL到达了底层网络请求的API。
  • 检测URL对应的IP是否是内网地址。如果是,则判定为SSRF攻击。
  • 根据配置,攻击Block。可以通过Hook返回的Respone里面,都存储在ThreadLocal。

小结下,过程是:Java Instrument机制 -> Javassist库修改字节码Hook关键函数 -> 通过比对用户Request的参数和底层网络请求参数,检测攻击。

0x02 基于JVM-Sanbox的实现

OpenRASP开源实现已经很赞了,还有很多商业功能,用到实际业务中实践没问题。这里我为了完成相关研究测试,及平常简单使用。使用阿里的JVM-Sandbox快速简洁地实现了2个工具,分别用来禁用命令执行防护通用RCE/SQL注入攻击的RASP实现

Java禁用掉命令执行API,可以防护很多安全攻击。在2次的DDCTF题目中,我都用了这个,线上运行无bug。由于JVM-Sandbox提供了良好的API支持,代码优雅而简单:

命令执行,包括Runtime.exec都是走到java.lang.ProcessBuilderstart方法。运行过程中,只要知道进程号,就能拦截命令执行,效果如下:

RASP我实现了通用RCE检测以及参考OpenRASP算法实现SQL注入的检测。主要目的是研究和测试,RCE检测和拦截实现是针对性的分析Spring、Struts2框架历史漏洞,找到关键API进行Hook分析。与OpenRASP不同的是,针对性的加入了多层次监控(如:OGNL、SpEL语言层),整体当时框架设计是:

0x03 参考

Java动态编程初探——Javassist
https://github.com/baidu/openrasp
禁用命令执行
防护通用RCE/SQL注入攻击的RASP实现