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
方法。
1 | /** |
紧接着会进入EngineBoot
的start
方法进行初始化,initTransformer(inst);
就是对Java字节码进行修改的具体代码了。 这里会扫描
com.baidu.openrasp.hook
包下所有带注解@HookAnnotation
的类,每个类负责Hook一个/多个Method。提取Method的参数,使用Javassist技术增加检测代码并植入到目标Class文件。 CustomClassTransformer
类的transform
方法是编织字节码的入口,加载类文件时,都会调用这个方法,判断是否时需要修改编织的类。如果是,则修改完返回字节码流。 我框出来的代码部分会调用每个Hook类的
hookMethod
方法。SSRF防护时,会Hook所有常见发送网络请求的函数。这一步主要获取请求参数,结合用户网络请求输入的参数,进行关联比对分析。 上图使用了Javassist库,在
org/apache/commons/httpclient/URI
的parseUriReference
方法后面添加了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支持,代码优雅而简单:
1 | @Http("/blockSystemExec") |
命令执行,包括Runtime.exec都是走到java.lang.ProcessBuilder
的start
方法。运行过程中,只要知道进程号,就能拦截命令执行,效果如下: RASP我实现了通用RCE检测以及参考OpenRASP算法实现SQL注入的检测。主要目的是研究和测试,RCE检测和拦截实现是针对性的分析Spring、Struts2框架历史漏洞,找到关键API进行Hook分析。与OpenRASP不同的是,针对性的加入了多层次监控(如:OGNL、SpEL语言层),整体当时框架设计是:
0x03 参考
Java动态编程初探——Javassist
https://github.com/baidu/openrasp
禁用命令执行
防护通用RCE/SQL注入攻击的RASP实现