浅谈RASP技术攻防之实战[代码实现篇]

发布者:凌天labs
发布于:2019-05-08 17:41

本篇主讲RASP实现(简易版),所有的环境可参考: 浅谈RASP技术攻防之实战[环境配置篇]

 

代码上传GitHub地址:https://github.com/iiiusky/java_rasp_example

 

关于 ASM 中不同类不同方法之间的关系图如下

简易版RASP实现

创建入口类

在cn.org.javaweb.agent包下新建一个类。
内容如下:

 

创建Transform

然后我们再新建一个AgentTransform类,该类需要实现ClassFileTransformer的方法,内容如下:

 

build Agent配置

点击右上角的agent[clean,intall]进行build。

由上图可见我们的包的位置为

 

 

将改包的位置记录下来,然后点开tomcat配置(这边没有对idea如何配置tomcat进行讲解,不会的可以自行百度|谷歌)

 

 

在VM options处填写以下内容:

 

 

其中/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar的路径为你在上一步编译出来的agent的路径,注意替换。

 

这时候我们在启动tomcat,就可以看到我们在AgentTransform中写的打印包名已经生效了,如下图:

上图红框区域为tomcat启动的时候加载的所有类名。然后我们打开浏览器查看web是否正常。

 


可以看到web也正常启动了。

创建ClassVisitor类

然后我们新建一个TestClassVisitor类,需要继承ClassVisitor类并且实现Opcodes类,代码如下

 

对ProcessBuilder(命令执行)类进行hook用户执行的命令

≡≡ 使用transform对类名进行过滤

然后回到AgentTransform中,对transform方法的内容进行修改,transform方法代码如下:

 


简单介绍一下代码块内容

 

首先判断类名是否包含ProcessBuilder,如果包含则使用ClassReader对字节码进行读取,然后新建一个ClassWriter进行对ClassReader读取的字节码进行拼接,然后在新建一个我们自定义的ClassVisitor对类的触发事件进行hook,在然后调用classReader的accept方法,最后给classfileBuffer重新赋值修改后的字节码。

 

可能看起来比较绕,但是如果学会使用以后就比较好理解了。

≡≡ 创建测试环境

我们在tomcat中新建一个jsp,用来调用命令执行,代码如下:

 


可以看到就是一个简单的执行命令的代码;下面我们对就此更改过的内容进行build,看一下会输出点什么。

biuld完成,启动tomcat。

访问

 


可以看到已经成功执行命令,我们回到idea里面的控制台看一下输出了什么。

通过上图可以完整的看到一个执行命令所调用的所有调用链。

 

≡≡ 拿到用户所执行的命令

接下来我们看看尝试一下能否拿到所执行的命令
新建一个名为ProcessBuilderHook的类,然后在类中新建一个名字为start的静态方法,完整代码如下:

 


这个方法干啥用的我们一会在说,先看下面。

≡≡ 复写visitMethod方法

打开TestClassVisitor,对visitMethod方法进行更改。具体代码如下:

 


给大家解释下新增加的代码,从if判断开始

 

判断传入进来的方法名是否为start以及方法描述符是否为()Ljava/lang/Process;,如果是的话就新建一个AdviceAdapter方法,并且复写visitCode方法,对其字节码进行修改,

 


拿到栈顶上的this

 


拿到this里面的command

 


然后调用我们上面新建的ProcessBuilderHook类中的start方法,将上面拿到的this.command压入我们方法。

 

ProcessBuilderHook类的作用就是让这部分进行调用,然后转移就可以转入到我们的逻辑代码了。

 

我们再次编译一下,然后启动tomcat,访问cmd.jsp看看.

≡≡ 测试hook用户执行的命令参数是否拿到

访问

 

 


可以看到已经将当前目录下的内容打印了出来。
我们到idea中看看控制台输出了什么。

 

可以看到我们输入的命令

 


已经输出出来了,到此为止,我们拿到了要执行的命令.

总结

对于拿到要执行的命令以后怎么做,是需要拦截还是替换还是告警,这边就需要大家自己去实现了。当然,如果要实现拦截功能,还需要注意要获取当前请求中的的response,不然无法对response进行复写,也无法对其进行拦截。这边给大家提供一个思路,对应拦截功能,大家可以去hook请求相关的类,然后在危险hook点结合http请求上下文进行拦截请求。

 

对于其他攻击点的拦截,可以参考百度开源的OpenRasp进行编写hook点。

 

如需在Java中实现RASP技术,笔者建议好好了解一下ASM,这样对以后JAVA的运行机制也会有一定的了解,方便以后调试以及写代码。

参考

https://rasp.baidu.com/doc/hacking/architect/hook.html#java-server
https://github.com/anbai-inc/javaweb-codereview
https://static.javadoc.io/org.ow2.asm/asm/5.2/org/objectweb/asm/ClassReader.html
http://www.blogjava.net/vanadies10/archive/2011/02/23/344899.html
http://www.blogjava.net/DLevin/archive/2014/06/25/414292.html


声明:该文观点仅代表作者本人,转载请注明来自看雪