浅谈RASP技术攻防之实战(环境配置与代码实现)
字数 1318 2025-08-18 11:38:36
RASP技术攻防实战:环境配置与代码实现
一、RASP技术概述
RASP(Runtime Application Self-Protection)是一种运行时应用自我保护技术,通过在应用程序运行时注入安全检测代码,实现对应用行为的监控和防护。本文将从实战角度介绍Java RASP的环境配置与基础实现。
二、项目初始化
1. 创建Maven项目结构
- 在IDEA中新建一个Maven项目,命名为
JavawebAgent - 删除默认的
src目录 - 右键新建Module,选择Maven项目:
- 第一个Module命名为
agent(ArtifactId) - 第二个Module命名为
test-struts2(测试web代码区域)
- 第一个Module命名为
最终目录结构:
JavawebAgent
├── agent
└── test-struts2
三、agent模块配置
1. pom.xml配置
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>5.1</version>
</dependency>
</dependencies>
<build>
<finalName>agent</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifestFile>src/main/resources/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>commons-io:commons-io:jar:*</include>
<include>org.ow2.asm:asm-all:jar:*</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
2. MANIFEST.MF文件配置
在resources目录下创建MANIFEST.MF文件,内容如下:
Manifest-Version: 1.0
Can-Retransform-Classes: true
Can-Redefine-Classes: true
Can-Set-Native-Method-Prefix: true
3. Maven自动打包配置
- 在IDEA右上角找到
Add Configurations - 点击
+,选择Maven - 配置:
- 工作目录:选择项目根目录
- 选择
agent模块 - 命令:
clean install
四、核心代码实现
1. Agent入口类
package cn.org.javaweb.agent;
import java.lang.instrument.Instrumentation;
public class Agent {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new AgentTransform());
}
}
2. AgentTransform类(实现字节码转换)
package cn.org.javaweb.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class AgentTransform implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
className = className.replace("/", ".");
try {
if (className.contains("ProcessBuilder")) {
System.out.println("Load class: " + className);
ClassReader classReader = new ClassReader(classfileBuffer);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new TestClassVisitor(classWriter);
classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
classfileBuffer = classWriter.toByteArray();
}
} catch (Exception e) {
e.printStackTrace();
}
return classfileBuffer;
}
}
3. TestClassVisitor类(ASM字节码操作)
package cn.org.javaweb.agent;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class TestClassVisitor extends ClassVisitor implements Opcodes {
public TestClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if ("start".equals(name) && "()Ljava/lang/Process;".equals(desc)) {
System.out.println(name + "方法的描述符是:" + desc);
return new AdviceAdapter(Opcodes.ASM5, mv, access, name, desc) {
@Override
public void visitCode() {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "java/lang/ProcessBuilder", "command", "Ljava/util/List;");
mv.visitMethodInsn(INVOKESTATIC, "cn/org/javaweb/agent/ProcessBuilderHook",
"start", "(Ljava/util/List;)V", false);
super.visitCode();
}
};
}
return mv;
}
}
4. ProcessBuilderHook类(命令执行拦截)
package cn.org.javaweb.agent;
import java.util.Arrays;
import java.util.List;
public class ProcessBuilderHook {
public static void start(List<String> commands) {
String[] commandArr = commands.toArray(new String[commands.size()]);
System.out.println(Arrays.toString(commandArr));
// 这里可以添加拦截逻辑
}
}
五、测试环境配置
1. Tomcat VM参数配置
在Tomcat配置的VM options中添加:
-Dfile.encoding=UTF-8
-noverify
-Xbootclasspath/p:/path/to/agent.jar
-javaagent:/path/to/agent.jar
注意将/path/to/agent.jar替换为实际的agent.jar路径。
2. 测试JSP页面
创建一个测试JSP页面cmd.jsp:
<%@ page import="java.io.InputStream" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<pre>
<%
Process process = Runtime.getRuntime().exec(request.getParameter("cmd"));
InputStream in = process.getInputStream();
int a = 0;
byte[] b = new byte[1024];
while ((a = in.read(b)) != -1) {
out.println(new String(b, 0, a));
}
in.close();
%>
</pre>
六、工作原理分析
-
Agent加载机制:
- 通过
premain方法在JVM启动时加载agent - 使用
InstrumentationAPI注册ClassFileTransformer
- 通过
-
字节码转换流程:
- 检测到
ProcessBuilder类加载时进行拦截 - 使用ASM框架修改字节码
- 在
start方法执行前插入自定义逻辑
- 检测到
-
命令执行拦截:
- 通过ASM获取
ProcessBuilder.command字段值 - 调用
ProcessBuilderHook.start()方法进行拦截处理 - 输出执行的命令参数
- 通过ASM获取
七、扩展思路
-
拦截功能实现:
- 在
ProcessBuilderHook.start()中添加拦截逻辑 - 需要获取当前HTTP请求的
response对象才能实现拦截
- 在
-
其他攻击点防护:
- 参考百度OpenRASPhook点设计
- 可防护SQL注入、文件操作、反序列化等漏洞
-
性能优化:
- 减少不必要的类转换
- 优化ASM字节码操作
八、学习建议
-
深入学习ASM:
- 理解Java字节码结构
- 掌握ASM Core API使用
-
参考资源:
通过本教程,您已经掌握了Java RASP的基本实现原理和实战方法,可以在此基础上进一步开发完整的安全防护功能。