├── src
├── main
│ ├── java
│ │ └── xbear
│ │ │ └── javaopenrasp
│ │ │ ├── filters
│ │ │ ├── SecurityFilterI.java
│ │ │ ├── sql
│ │ │ │ ├── MySQLFilter.java
│ │ │ │ ├── SQLServerFilter.java
│ │ │ │ └── SQLWallProviders.java
│ │ │ └── rce
│ │ │ │ ├── DeserializationFilter.java
│ │ │ │ ├── OgnlFilter.java
│ │ │ │ └── PrcessBuilderFilter.java
│ │ │ ├── util
│ │ │ ├── Console.java
│ │ │ ├── StackTrace.java
│ │ │ └── Reflections.java
│ │ │ ├── Agent.java
│ │ │ ├── visitors
│ │ │ ├── rce
│ │ │ │ ├── OgnlVisitor.java
│ │ │ │ ├── ProcessBuilderVisitor.java
│ │ │ │ ├── DeserializationVisitor.java
│ │ │ │ ├── OgnlVisitorAdapter.java
│ │ │ │ ├── DeserializationVisitorAdapter.java
│ │ │ │ └── ProcessBuilderVisitorAdapter.java
│ │ │ └── sql
│ │ │ │ ├── MySQLVisitorAdapter.java
│ │ │ │ ├── SQLServerVisitorAdapter.java
│ │ │ │ ├── MySQLVisitor.java
│ │ │ │ └── SQLServerVisitor.java
│ │ │ ├── ClassTransformer.java
│ │ │ └── config
│ │ │ └── Config.java
│ └── resources
│ │ └── main.config
└── test
│ └── java
│ └── xbear
│ └── openjavarasp
│ └── AppTest.java
├── .gitignore
├── README.md
├── .classpath
├── pom.xml
└── LICENSE
/src/main/java/xbear/javaopenrasp/filters/SecurityFilterI.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters;
2 |
3 | /**
4 | * Created by xbear on 2016/11/13.
5 | */
6 | public interface SecurityFilterI {
7 | public boolean filter(Object forCheck);
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | pom.xml.tag
3 | pom.xml.releaseBackup
4 | pom.xml.versionsBackup
5 | pom.xml.next
6 | release.properties
7 | dependency-reduced-pom.xml
8 | buildNumber.properties
9 | .mvn/timing.properties
10 | *.iml
11 | *.old
12 | .idea
13 | .DS_Store
14 | classes
15 | .project
16 | .settings/
17 | */.classpath
18 | */.gitignore
19 | */.project
20 | .gitignore
21 | antx.properties
22 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/util/Console.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.util;
2 |
3 | import java.io.PrintStream;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 |
7 | /**
8 | * Created by xbear on 2016/11/13.
9 | */
10 | public class Console {
11 |
12 | private static PrintStream ps = System.out;
13 |
14 | private static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
15 |
16 | public static void log(String msg) {
17 | if (msg != null && !msg.equals("")) {
18 | ps.println("[javaopenrasp][" + df.format(new Date()) + "]:" + msg);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java Open Rasp(Runtime Application Self-Protection)
2 | # A Java Rasp Demo
3 |
4 | ### Supported Vulnerabilites
5 |
6 | ## RCE
7 |
8 | 1. deserialize vulnerability
9 |
10 | 2. danger ognl expressions
11 |
12 | 3. ProcessBuilder log
13 |
14 | ## Sql Ingection
15 |
16 | 1. MySQL
17 |
18 | 2. SQLServer
19 |
20 | ### How to use:
21 |
22 | add "-javaagent:/path/javaopenrasp.jar" to your jvm arguments
23 |
24 | # Java Open Rasp
25 |
26 | 这是一个java rasp的验证性demo,已验证rasp的原理及实现
27 |
28 | ### 实现的保护点
29 |
30 | ## RCE
31 |
32 | 1. 反序列化漏洞
33 |
34 | 2. Ognl表达式执行
35 |
36 | 3. ProcessBuilder log
37 |
38 | ## SQL注入
39 |
40 | 1. MySql注入保护
41 |
42 | 2. SQLServer注入保护
43 |
44 | ## 使用方法
45 | 编译后,将"-javaagent:/path/javaopenrasp.jar"添加至JVM的启动参数
46 |
47 | E-Mail: xiongxbear@gmail.com
48 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/Agent.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp;
2 |
3 | import xbear.javaopenrasp.config.Config;
4 | import xbear.javaopenrasp.util.Console;
5 |
6 | import java.lang.instrument.Instrumentation;
7 | import java.lang.instrument.UnmodifiableClassException;
8 |
9 | /**
10 | * Created by xbear on 2016/11/13.
11 | */
12 | public class Agent {
13 |
14 | public static void premain(String agentArgs, Instrumentation inst)
15 | throws ClassNotFoundException, UnmodifiableClassException {
16 | Console.log("init");
17 | init();
18 | inst.addTransformer(new ClassTransformer());
19 | }
20 |
21 | private static boolean init() {
22 | Config.initConfig();
23 | return true;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/xbear/openjavarasp/AppTest.java:
--------------------------------------------------------------------------------
1 | package xbear.openjavarasp;
2 |
3 | import junit.framework.Test;
4 | import junit.framework.TestCase;
5 | import junit.framework.TestSuite;
6 |
7 | /**
8 | * Unit test for simple App.
9 | */
10 | public class AppTest
11 | extends TestCase {
12 | /**
13 | * Create the test case
14 | *
15 | * @param testName name of the test case
16 | */
17 | public AppTest(String testName) {
18 | super(testName);
19 | }
20 |
21 | /**
22 | * @return the suite of tests being tested
23 | */
24 | public static Test suite() {
25 | return new TestSuite(AppTest.class);
26 | }
27 |
28 | /**
29 | * Rigourous Test :-)
30 | */
31 | public void testApp() {
32 | assertTrue(true);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/OgnlVisitor.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 |
7 | /**
8 | * Created by xbear on 2016/11/13.
9 | */
10 | public class OgnlVisitor extends ClassVisitor {
11 |
12 | public String className;
13 |
14 | public OgnlVisitor(ClassVisitor cv, String className) {
15 | super(Opcodes.ASM5, cv);
16 | this.className = className;
17 | }
18 |
19 | @Override
20 | public MethodVisitor visitMethod(int access, String name, String desc,
21 | String signature, String[] exceptions) {
22 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
23 | if ("parseExpression".equals(name) && "(Ljava/lang/String;)Ljava/lang/Object;".equals(desc)) {
24 | mv = new OgnlVisitorAdapter(mv, access, name, desc);
25 | }
26 | return mv;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/ProcessBuilderVisitor.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 |
7 | /**
8 | * Created by xbear on 2016/11/13.
9 | */
10 | public class ProcessBuilderVisitor extends ClassVisitor {
11 |
12 | public String className;
13 |
14 | public ProcessBuilderVisitor(ClassVisitor cv, String className) {
15 | super(Opcodes.ASM5, cv);
16 | this.className = className;
17 | }
18 |
19 | @Override
20 | public MethodVisitor visitMethod(int access, String name, String desc,
21 | String signature, String[] exceptions) {
22 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
23 | if ("start".equals(name) && "()Ljava/lang/Process;".equals(desc)) {
24 | mv = new ProcessBuilderVisitorAdapter(mv, access, name, desc);
25 | }
26 | return mv;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/DeserializationVisitor.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 |
7 | /**
8 | * Created by xbear on 2016/11/13.
9 | */
10 | public class DeserializationVisitor extends ClassVisitor {
11 | public String className;
12 |
13 | public DeserializationVisitor(ClassVisitor cv, String className) {
14 | super(Opcodes.ASM5, cv);
15 | this.className = className;
16 | }
17 |
18 | @Override
19 | public MethodVisitor visitMethod(int access, String name, String desc,
20 | String signature, String[] exceptions) {
21 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
22 | if ("resolveClass".equals(name) && "(Ljava/io/ObjectStreamClass;)Ljava/lang/Class;".equals(desc)) {
23 | mv = new DeserializationVisitorAdapter(mv, access, name, desc);
24 | }
25 | return mv;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/util/StackTrace.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.util;
2 |
3 | /**
4 | * Created by xbear on 2016/11/13.
5 | */
6 | public class StackTrace {
7 |
8 | public static String getStackTrace() {
9 |
10 | Throwable ex = new Throwable();
11 | StackTraceElement[] stackElements = ex.getStackTrace();
12 | StringBuilder retStack = new StringBuilder();
13 |
14 | if (stackElements.length >= 3) {
15 | for (int i = 2; i < stackElements.length; i++) {
16 | retStack.append(stackElements[i].getClassName() + "@" + stackElements[i].getMethodName() + "\r\n");
17 | }
18 | } else {
19 | for (int i = 0; i < stackElements.length; i++) {
20 | retStack.append(stackElements[i].getClassName() + "@" + stackElements[i].getMethodName() + "\r\n");
21 | }
22 | }
23 |
24 | return retStack.toString();
25 | }
26 |
27 | public static String getCaller() {
28 |
29 | Throwable ex = new Throwable();
30 | StackTraceElement[] stackElements = ex.getStackTrace();
31 |
32 | if (stackElements.length >= 3) {
33 | return stackElements[2].getClassName() + "@" + stackElements[1].getMethodName();
34 | } else {
35 | return stackElements[1].getClassName() + "@" + stackElements[1].getMethodName();
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/OgnlVisitorAdapter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.Label;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 | import org.objectweb.asm.commons.AdviceAdapter;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class OgnlVisitorAdapter extends AdviceAdapter {
12 | public OgnlVisitorAdapter(MethodVisitor mv, int access, String name, String desc) {
13 | super(Opcodes.ASM5, mv, access, name, desc);
14 | }
15 |
16 | @Override
17 | protected void onMethodEnter() {
18 |
19 | Label l30 = new Label();
20 | mv.visitLabel(l30);
21 | mv.visitVarInsn(ALOAD, 0);
22 | mv.visitMethodInsn(INVOKESTATIC, "xbear/javaopenrasp/filters/rce/OgnlFilter", "staticFilter", "(Ljava/lang/Object;)Z", false);
23 | Label l31 = new Label();
24 | mv.visitJumpInsn(IFNE, l31);
25 | Label l32 = new Label();
26 | mv.visitLabel(l32);
27 | mv.visitTypeInsn(NEW, "ognl/OgnlException");
28 | mv.visitInsn(DUP);
29 | mv.visitLdcInsn("invalid class in ognl expression because of security");
30 | mv.visitMethodInsn(INVOKESPECIAL, "ognl/OgnlException", "", "(Ljava/lang/String;)V", false);
31 | mv.visitInsn(ATHROW);
32 | mv.visitLabel(l31);
33 |
34 | }
35 |
36 | @Override
37 | public void visitMaxs(int maxStack, int maxLocals) {
38 | super.visitMaxs(maxStack, maxLocals);
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/sql/MySQLFilter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.sql;
2 |
3 | import com.alibaba.druid.wall.WallCheckResult;
4 | import com.alibaba.druid.wall.WallProvider;
5 | import xbear.javaopenrasp.config.Config;
6 | import xbear.javaopenrasp.filters.SecurityFilterI;
7 | import xbear.javaopenrasp.util.Console;
8 | import xbear.javaopenrasp.util.StackTrace;
9 |
10 | /**
11 | * Created by xbear on 2016/11/13.
12 | */
13 | public class MySQLFilter implements SecurityFilterI {
14 | @Override
15 | public boolean filter(Object forCheck) {
16 | String sql = ((String) forCheck).trim();
17 | WallProvider provider = SQLWallProviders.getProvider("mysql");
18 |
19 | Console.log("prepare to exec sql:" + sql);
20 | String mode = (String) Config.moudleMap.get("com/mysql/jdbc/StatementImpl").get("mode");
21 |
22 | switch (mode) {
23 | case "check":
24 | Console.log("check: " + sql);
25 | WallCheckResult result = provider.check(sql);
26 | if (result.getViolations().size() > 0) {
27 | for (int i = 0; i < result.getViolations().size(); i++) {
28 | Console.log("Warning: " + result.getViolations().get(i).getMessage());
29 | }
30 | return false;
31 | }
32 | return true;
33 | case "log":
34 | default:
35 | Console.log("exc sql: " + sql);
36 | Console.log("log stack trace:\r\n" + StackTrace.getStackTrace());
37 | return true;
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/sql/SQLServerFilter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.sql;
2 |
3 | import com.alibaba.druid.wall.WallCheckResult;
4 | import com.alibaba.druid.wall.WallProvider;
5 | import xbear.javaopenrasp.config.Config;
6 | import xbear.javaopenrasp.filters.SecurityFilterI;
7 | import xbear.javaopenrasp.util.Console;
8 | import xbear.javaopenrasp.util.StackTrace;
9 |
10 | /**
11 | * Created by xbear on 2016/11/13.
12 | */
13 | public class SQLServerFilter implements SecurityFilterI {
14 | @Override
15 | public boolean filter(Object forCheck) {
16 | String sql = ((String) forCheck).trim();
17 | WallProvider provider = SQLWallProviders.getProvider("mysql");
18 |
19 | Console.log("prepare to exec sql:" + sql);
20 | String mode = (String) Config.moudleMap.get("com/microsoft/jdbc/base/BaseStatement").get("mode");
21 |
22 | switch (mode) {
23 | case "check":
24 | Console.log("check: " + sql);
25 | WallCheckResult result = provider.check(sql);
26 | if (result.getViolations().size() > 0) {
27 | for (int i = 0; i < result.getViolations().size(); i++) {
28 | Console.log("Warning: " + result.getViolations().get(i).getMessage());
29 | }
30 | return false;
31 | }
32 | return true;
33 | case "log":
34 | default:
35 | Console.log("exc sql: " + sql);
36 | Console.log("log stack trace:\r\n" + StackTrace.getStackTrace());
37 | return true;
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/DeserializationVisitorAdapter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.Label;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 | import org.objectweb.asm.commons.AdviceAdapter;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class DeserializationVisitorAdapter extends AdviceAdapter {
12 | public DeserializationVisitorAdapter(MethodVisitor mv, int access, String name, String desc) {
13 | super(Opcodes.ASM5, mv, access, name, desc);
14 | }
15 |
16 | @Override
17 | protected void onMethodEnter() {
18 | mv.visitTypeInsn(NEW, "xbear/javaopenrasp/filters/rce/DeserializationFilter");
19 | mv.visitInsn(DUP);
20 | mv.visitMethodInsn(INVOKESPECIAL, "xbear/javaopenrasp/filters/rce/DeserializationFilter", "", "()V", false);
21 | mv.visitVarInsn(ASTORE, 2);
22 | mv.visitVarInsn(ALOAD, 2);
23 | mv.visitVarInsn(ALOAD, 1);
24 | mv.visitMethodInsn(INVOKEVIRTUAL, "xbear/javaopenrasp/filters/rce/DeserializationFilterr", "filter", "(Ljava/lang/Object;)Z", false);
25 |
26 | Label l92 = new Label();
27 | mv.visitJumpInsn(IFNE, l92);
28 | mv.visitTypeInsn(NEW, "java/io/IOException");
29 | mv.visitInsn(DUP);
30 | mv.visitLdcInsn("invalid class in deserialization because of security");
31 | mv.visitMethodInsn(INVOKESPECIAL, "java/io/IOException", "", "(Ljava/lang/String;)V", false);
32 | mv.visitInsn(ATHROW);
33 | mv.visitLabel(l92);
34 |
35 | }
36 |
37 | @Override
38 | public void visitMaxs(int maxStack, int maxLocals) {
39 | super.visitMaxs(maxStack, maxLocals);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/rce/DeserializationFilter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.rce;
2 |
3 | import xbear.javaopenrasp.config.Config;
4 | import xbear.javaopenrasp.filters.SecurityFilterI;
5 | import xbear.javaopenrasp.util.Console;
6 | import xbear.javaopenrasp.util.StackTrace;
7 |
8 | import java.io.ObjectStreamClass;
9 |
10 | /**
11 | * Created by xbear on 2016/11/13.
12 | */
13 | public class DeserializationFilter implements SecurityFilterI {
14 |
15 | @Override
16 | public boolean filter(Object forCheck) {
17 | String moudleName = "java/io/ObjectInputStream";
18 | ObjectStreamClass desc = (ObjectStreamClass) forCheck;
19 | String className = desc.getName();
20 | String mode = (String) Config.moudleMap.get(moudleName).get("mode");
21 | switch (mode) {
22 | case "block":
23 | Console.log("block: " + className);
24 | return false;
25 | case "white":
26 | if (Config.isWhite(moudleName, className)) {
27 | Console.log("pass: " + className);
28 | return true;
29 | }
30 | Console.log("block:" + className);
31 | return false;
32 | case "black":
33 | if (Config.isBlack(moudleName, className)) {
34 | Console.log("block: " + className);
35 | return false;
36 | }
37 | Console.log("pass: " + className);
38 | return true;
39 | case "log":
40 | default:
41 | Console.log("pass: " + className);
42 | Console.log("log stack trace:\r\n" + StackTrace.getStackTrace());
43 | return true;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/sql/SQLWallProviders.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.sql;
2 |
3 | import com.alibaba.druid.wall.WallProvider;
4 | import com.alibaba.druid.wall.spi.MySqlWallProvider;
5 | import com.alibaba.druid.wall.spi.SQLServerWallProvider;
6 | import xbear.javaopenrasp.util.Console;
7 |
8 | import java.util.Map;
9 | import java.util.concurrent.ConcurrentHashMap;
10 |
11 | /**
12 | * Created by xbear on 2016/11/13.
13 | */
14 | public class SQLWallProviders {
15 |
16 | private static Map providerMap = new ConcurrentHashMap();
17 |
18 | public static WallProvider getProvider(String dbType) {
19 | switch (dbType.trim()) {
20 | case "mysql":
21 | if (!providerMap.containsKey("mysql")) {
22 | providerMap.put("mysql", new MySqlWallProvider());
23 | setConfig(providerMap.get("mysql"));
24 | }
25 | return providerMap.get("mysql");
26 | case "sqlserver":
27 | if (!providerMap.containsKey("sqlserver")) {
28 | providerMap.put("sqlserver", new SQLServerWallProvider());
29 | setConfig(providerMap.get("sqlserver"));
30 | }
31 | return providerMap.get("sqlserver");
32 | default:
33 | if (!providerMap.containsKey("mysql")) {
34 | providerMap.put("mysql", new MySqlWallProvider());
35 | setConfig(providerMap.get("mysql"));
36 | }
37 | return providerMap.get("mysql");
38 | }
39 | }
40 |
41 | private static void setConfig(WallProvider provider) {
42 | provider.getConfig().setCommentAllow(false);
43 | //set you want
44 | Console.log(provider.getBlackList().toString());
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/rce/ProcessBuilderVisitorAdapter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.rce;
2 |
3 | import org.objectweb.asm.Label;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 | import org.objectweb.asm.commons.AdviceAdapter;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class ProcessBuilderVisitorAdapter extends AdviceAdapter {
12 | public ProcessBuilderVisitorAdapter(MethodVisitor mv, int access, String name, String desc) {
13 | super(Opcodes.ASM5, mv, access, name, desc);
14 | }
15 |
16 | @Override
17 | protected void onMethodEnter() {
18 | mv.visitTypeInsn(NEW, "xbear/javaopenrasp/filters/rce/PrcessBuilderFilter");
19 | mv.visitInsn(DUP);
20 | mv.visitMethodInsn(INVOKESPECIAL, "xbear/javaopenrasp/filters/rce/PrcessBuilderFilter", "", "()V", false);
21 | mv.visitVarInsn(ASTORE, 1);
22 | mv.visitVarInsn(ALOAD, 1);
23 | mv.visitVarInsn(ALOAD, 0);
24 | mv.visitFieldInsn(GETFIELD, "java/lang/ProcessBuilder", "command", "Ljava/util/List;");
25 | mv.visitMethodInsn(INVOKEVIRTUAL, "xbear/javaopenrasp/filters/rce/PrcessBuilderFilter", "filter", "(Ljava/lang/Object;)Z", false);
26 |
27 | Label l92 = new Label();
28 | mv.visitJumpInsn(IFNE, l92);
29 | mv.visitTypeInsn(NEW, "java/io/IOException");
30 | mv.visitInsn(DUP);
31 | mv.visitLdcInsn("invalid character in command because of security");
32 | mv.visitMethodInsn(INVOKESPECIAL, "java/io/IOException", "", "(Ljava/lang/String;)V", false);
33 | mv.visitInsn(ATHROW);
34 | mv.visitLabel(l92);
35 |
36 | }
37 |
38 | @Override
39 | public void visitMaxs(int maxStack, int maxLocals) {
40 | super.visitMaxs(maxStack, maxLocals);
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/sql/MySQLVisitorAdapter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.sql;
2 |
3 | import org.objectweb.asm.Label;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 | import org.objectweb.asm.commons.AdviceAdapter;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class MySQLVisitorAdapter extends AdviceAdapter {
12 | public MySQLVisitorAdapter(MethodVisitor mv, int access, String name, String desc) {
13 | super(Opcodes.ASM5, mv, access, name, desc);
14 | }
15 |
16 | @Override
17 | protected void onMethodEnter() {
18 | mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
19 | mv.visitLdcInsn("Already in sql");
20 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
21 |
22 | mv.visitTypeInsn(NEW, "xbear/javaopenrasp/filters/sql/MySQLFilter");
23 | mv.visitInsn(DUP);
24 | mv.visitMethodInsn(INVOKESPECIAL, "xbear/javaopenrasp/filters/sql/MySQLFilter", "", "()V", false);
25 | mv.visitVarInsn(ASTORE, 3);
26 | mv.visitVarInsn(ALOAD, 3);
27 | mv.visitVarInsn(ALOAD, 1);
28 | mv.visitMethodInsn(INVOKEVIRTUAL, "xbear/javaopenrasp/filters/sql/MySQLFilter", "filter", "(Ljava/lang/Object;)Z", false);
29 |
30 | Label l92 = new Label();
31 | mv.visitJumpInsn(IFNE, l92);
32 | mv.visitTypeInsn(NEW, "java/sql/SQLException");
33 | mv.visitInsn(DUP);
34 | mv.visitLdcInsn("invalid sql because of security");
35 | mv.visitMethodInsn(INVOKESPECIAL, "java/sql/SQLException", "", "(Ljava/lang/String;)V", false);
36 | mv.visitInsn(ATHROW);
37 | mv.visitLabel(l92);
38 |
39 | }
40 |
41 | @Override
42 | public void visitMaxs(int maxStack, int maxLocals) {
43 | super.visitMaxs(maxStack, maxLocals);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/sql/SQLServerVisitorAdapter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.sql;
2 |
3 | import org.objectweb.asm.Label;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 | import org.objectweb.asm.commons.AdviceAdapter;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class SQLServerVisitorAdapter extends AdviceAdapter {
12 | public SQLServerVisitorAdapter(MethodVisitor mv, int access, String name, String desc) {
13 | super(Opcodes.ASM5, mv, access, name, desc);
14 | }
15 |
16 | @Override
17 | protected void onMethodEnter() {
18 | mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
19 | mv.visitLdcInsn("Already in sql");
20 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
21 |
22 | mv.visitTypeInsn(NEW, "xbear/javaopenrasp/filters/sql/SQLServerFilter");
23 | mv.visitInsn(DUP);
24 | mv.visitMethodInsn(INVOKESPECIAL, "xbear/javaopenrasp/filters/sql/SQLServerFilter", "", "()V", false);
25 | mv.visitVarInsn(ASTORE, 3);
26 | mv.visitVarInsn(ALOAD, 3);
27 | mv.visitVarInsn(ALOAD, 1);
28 | mv.visitMethodInsn(INVOKEVIRTUAL, "xbear/javaopenrasp/filters/sql/SQLServerFilter", "filter", "(Ljava/lang/Object;)Z", false);
29 |
30 | Label l92 = new Label();
31 | mv.visitJumpInsn(IFNE, l92);
32 | mv.visitTypeInsn(NEW, "java/sql/SQLException");
33 | mv.visitInsn(DUP);
34 | mv.visitLdcInsn("invalid sql because of security");
35 | mv.visitMethodInsn(INVOKESPECIAL, "java/sql/SQLException", "", "(Ljava/lang/String;)V", false);
36 | mv.visitInsn(ATHROW);
37 | mv.visitLabel(l92);
38 |
39 | }
40 |
41 | @Override
42 | public void visitMaxs(int maxStack, int maxLocals) {
43 | super.visitMaxs(maxStack, maxLocals);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/rce/OgnlFilter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.rce;
2 |
3 | import xbear.javaopenrasp.config.Config;
4 | import xbear.javaopenrasp.filters.SecurityFilterI;
5 | import xbear.javaopenrasp.util.Console;
6 | import xbear.javaopenrasp.util.StackTrace;
7 |
8 | /**
9 | * Created by xbear on 2016/11/13.
10 | */
11 | public class OgnlFilter implements SecurityFilterI {
12 |
13 | public static boolean staticFilter(Object forCheck) {
14 | String moudleName = "ognl/Ognl";
15 | String ognlExpression = (String) forCheck;
16 | Console.log("prepare to parse ognlExpression:" + ognlExpression);
17 | String mode = (String) Config.moudleMap.get("ognl/Ognl").get("mode");
18 | switch (mode) {
19 | case "block":
20 | Console.log("block" + ognlExpression);
21 | return false;
22 | case "white":
23 | if (Config.isWhite(moudleName, ognlExpression)) {
24 | Console.log("parse ognlExpression:" + ognlExpression);
25 | return true;
26 | }
27 | Console.log("block" + ognlExpression);
28 | return false;
29 | case "black":
30 | if (Config.isBlack(moudleName, ognlExpression)) {
31 | Console.log("block parse ognlExpression" + ognlExpression);
32 | return false;
33 | }
34 | Console.log("exec command:" + ognlExpression);
35 | return true;
36 | case "log":
37 | default:
38 | Console.log("parse ognlExpression" + ognlExpression);
39 | Console.log("log stack trace:\r\n" + StackTrace.getStackTrace());
40 | return true;
41 | }
42 | }
43 |
44 | @Override
45 | public boolean filter(Object forCheck) {
46 | return true;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/filters/rce/PrcessBuilderFilter.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.filters.rce;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import xbear.javaopenrasp.config.Config;
5 | import xbear.javaopenrasp.filters.SecurityFilterI;
6 | import xbear.javaopenrasp.util.Console;
7 | import xbear.javaopenrasp.util.StackTrace;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * Created by xbear on 2016/11/13.
13 | */
14 | public class PrcessBuilderFilter implements SecurityFilterI {
15 |
16 | @Override
17 | public boolean filter(Object forCheck) {
18 | String moudleName = "java/lang/ProcessBuilder";
19 | List commandList = (List) forCheck;
20 | String command = StringUtils.join(commandList, " ").trim().toLowerCase();
21 | Console.log("prepare to exec command:" + command);
22 | String mode = (String) Config.moudleMap.get(moudleName).get("mode");
23 | switch (mode) {
24 | case "block":
25 | Console.log("block" + command);
26 | return false;
27 | case "white":
28 | if (Config.isWhite(moudleName, command)) {
29 | Console.log("exec command:" + command);
30 | return true;
31 | }
32 | Console.log("block" + command);
33 | return false;
34 | case "black":
35 | if (Config.isBlack(moudleName, command)) {
36 | Console.log("block command exec" + command);
37 | return false;
38 | }
39 | Console.log("exec command:" + command);
40 | return true;
41 | case "log":
42 | default:
43 | Console.log("exc commond" + command);
44 | Console.log("log stack trace:\r\n" + StackTrace.getStackTrace());
45 | return true;
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/util/Reflections.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.util;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 |
5 | import java.lang.reflect.Constructor;
6 | import java.lang.reflect.Field;
7 | import java.lang.reflect.InvocationTargetException;
8 |
9 | /**
10 | * Created by xbear on 2016/11/13.
11 | */
12 | public class Reflections {
13 |
14 | public static Field getField(final Class> clazz, final String fieldName) throws Exception {
15 | Field field = clazz.getDeclaredField(fieldName);
16 | if (field != null)
17 | field.setAccessible(true);
18 | else if (clazz.getSuperclass() != null)
19 | field = getField(clazz.getSuperclass(), fieldName);
20 | return field;
21 | }
22 |
23 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
24 | final Field field = getField(obj.getClass(), fieldName);
25 | field.set(obj, value);
26 | }
27 |
28 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
29 | final Field field = getField(obj.getClass(), fieldName);
30 | return field.get(obj);
31 | }
32 |
33 | public static Constructor> getFirstCtor(final String name) throws Exception {
34 | final Constructor> ctor = Class.forName(name).getDeclaredConstructors()[0];
35 | ctor.setAccessible(true);
36 | return ctor;
37 | }
38 |
39 | @SuppressWarnings("unchecked")
40 | public static T createVisitorIns(final String name, ClassVisitor cv, String className)
41 | throws Exception, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
42 | Constructor> ctor = Class.forName(name).getDeclaredConstructor(new Class[]{ClassVisitor.class, String.class});
43 | ctor.setAccessible(true);
44 | return (T) ctor.newInstance(new Object[]{cv, className});
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/sql/MySQLVisitor.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.sql;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 |
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | /**
11 | * Created by xbear on 2016/11/13.
12 | */
13 | public class MySQLVisitor extends ClassVisitor {
14 |
15 | private static final Set methodName = new HashSet() {{
16 | add("executeQuery");
17 | add("execute");
18 | add("executeUpdate");
19 | add("addBatch");
20 | }};
21 | private static final Set descName = new HashSet() {{
22 | add("(Ljava/lang/String;I)I");
23 | add("(Ljava/lang/String;[Ljava/lang/String;)I");
24 | add("(Ljava/lang/String;[I)I");
25 | add("(Ljava/lang/String;)Ljava/sql/ResultSet;");
26 | add("(Ljava/lang/String;)Z");
27 | add("(Ljava/lang/String;I)Z");
28 | add("(Ljava/lang/String;[Ljava/lang/String;)Z");
29 | add("(Ljava/lang/String;[I)Z");
30 | add("(Ljava/lang/String;[I)J");
31 | add("(Ljava/lang/String;[Ljava/lang/String;)J");
32 | add("(Ljava/lang/String;I)J");
33 | add("(Ljava/lang/String;)J");
34 | add("(Ljava/lang/String;)I");
35 | }};
36 | public String className;
37 |
38 | public MySQLVisitor(ClassVisitor cv, String className) {
39 | super(Opcodes.ASM5, cv);
40 | this.className = className;
41 | }
42 |
43 | @Override
44 | public MethodVisitor visitMethod(int access, String name, String desc,
45 | String signature, String[] exceptions) {
46 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
47 | if (methodName.contains(name) && descName.contains(desc)) {
48 | mv = new MySQLVisitorAdapter(mv, access, name, desc);
49 | }
50 | return mv;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/visitors/sql/SQLServerVisitor.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.visitors.sql;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 | import org.objectweb.asm.Opcodes;
6 |
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | /**
11 | * Created by xbear on 2016/11/13.
12 | */
13 | public class SQLServerVisitor extends ClassVisitor {
14 |
15 | private static final Set methodName = new HashSet() {{
16 | add("executeQuery");
17 | add("execute");
18 | add("executeUpdate");
19 | add("addBatch");
20 | }};
21 | private static final Set descName = new HashSet() {{
22 | add("(Ljava/lang/String;I)I");
23 | add("(Ljava/lang/String;[Ljava/lang/String;)I");
24 | add("(Ljava/lang/String;[I)I");
25 | add("(Ljava/lang/String;)Ljava/sql/ResultSet;");
26 | add("(Ljava/lang/String;)Z");
27 | add("(Ljava/lang/String;I)Z");
28 | add("(Ljava/lang/String;[Ljava/lang/String;)Z");
29 | add("(Ljava/lang/String;[I)Z");
30 | add("(Ljava/lang/String;[I)J");
31 | add("(Ljava/lang/String;[Ljava/lang/String;)J");
32 | add("(Ljava/lang/String;I)J");
33 | add("(Ljava/lang/String;)J");
34 | add("(Ljava/lang/String;)I");
35 | }};
36 | public String className;
37 |
38 | public SQLServerVisitor(ClassVisitor cv, String className) {
39 | super(Opcodes.ASM5, cv);
40 | this.className = className;
41 | }
42 |
43 | @Override
44 | public MethodVisitor visitMethod(int access, String name, String desc,
45 | String signature, String[] exceptions) {
46 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
47 | if (methodName.contains(name) && descName.contains(desc)) {
48 | mv = new SQLServerVisitorAdapter(mv, access, name, desc);
49 | }
50 | return mv;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/ClassTransformer.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp;
2 |
3 | import org.objectweb.asm.ClassReader;
4 | import org.objectweb.asm.ClassVisitor;
5 | import org.objectweb.asm.ClassWriter;
6 | import xbear.javaopenrasp.config.Config;
7 | import xbear.javaopenrasp.util.Reflections;
8 |
9 | import java.lang.instrument.ClassFileTransformer;
10 | import java.lang.instrument.IllegalClassFormatException;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.security.ProtectionDomain;
13 |
14 | /**
15 | * Created by xbear on 2016/11/13.
16 | */
17 | public class ClassTransformer implements ClassFileTransformer {
18 |
19 | public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined,
20 | ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
21 | byte[] transformeredByteCode = classfileBuffer;
22 |
23 | if (Config.moudleMap.containsKey(className)) {
24 | try {
25 | ClassReader reader = new ClassReader(classfileBuffer);
26 | ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
27 | ClassVisitor visitor = Reflections.createVisitorIns((String) Config.moudleMap.get(className).get("loadClass"), writer, className);
28 | reader.accept(visitor, ClassReader.EXPAND_FRAMES);
29 | transformeredByteCode = writer.toByteArray();
30 | } catch (ClassNotFoundException e) {
31 | e.printStackTrace();
32 | } catch (NoSuchMethodException e) {
33 | e.printStackTrace();
34 | } catch (InstantiationException e) {
35 | e.printStackTrace();
36 | } catch (IllegalAccessException e) {
37 | e.printStackTrace();
38 | } catch (InvocationTargetException e) {
39 | e.printStackTrace();
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | return transformeredByteCode;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/resources/main.config:
--------------------------------------------------------------------------------
1 | {
2 | "moudle":
3 | [
4 | {
5 | "moudleName": "java/lang/ProcessBuilder",
6 | "loadClass": "xbear.javaopenrasp.visitors.rce.ProcessBuilderVisitor",
7 | "mode": "log",
8 | "whiteList":[],
9 | "blackList":
10 | [
11 | "calc", "etc", "var", "opt", "apache", "bin", "passwd", "login", "cshrc", "profile", "ifconfig", "tcpdump", "chmod",
12 | "cron", "sudo", "su", "rm", "wget", "sz", "kill", "apt-get", "find"
13 | ]
14 | },
15 | {
16 | "moudleName": "java/io/ObjectInputStream",
17 | "loadClass": "xbear.javaopenrasp.visitors.rce.DeserializationVisitor",
18 | "mode": "black",
19 | "whiteList":[],
20 | "blackList":
21 | [
22 | "org.apache.commons.collections.functors.InvokerTransformer",
23 | "org.apache.commons.collections.functors.InstantiateTransformer",
24 | "org.apache.commons.collections4.functors.InvokerTransformer",
25 | "org.apache.commons.collections4.functors.InstantiateTransformer",
26 | "org.codehaus.groovy.runtime.ConvertedClosure",
27 | "org.codehaus.groovy.runtime.MethodClosure",
28 | "org.springframework.beans.factory.ObjectFactory"
29 | ]
30 | },
31 | {
32 | "moudleName": "ognl/Ognl",
33 | "loadClass": "xbear.javaopenrasp.visitors.rce.OgnlVisitor",
34 | "mode": "black",
35 | "whiteList":[],
36 | "blackList":
37 | [
38 | "ognl.OgnlContext",
39 | "ognl.TypeConverter",
40 | "ognl.MemberAccess",
41 | "_memberAccess",
42 | "ognl.ClassResolver",
43 | "java.lang.Runtime",
44 | "java.lang.Class",
45 | "java.lang.ClassLoader",
46 | "java.lang.System",
47 | "java.lang.ProcessBuilder",
48 | "java.lang.Object",
49 | "java.lang.Shutdown",
50 | "java.io.File",
51 | "javax.script.ScriptEngineManager",
52 | "com.opensymphony.xwork2.ActionContext",
53 | ]
54 | },
55 | {
56 | "moudleName": "com/mysql/jdbc/StatementImpl",
57 | "loadClass": "xbear.javaopenrasp.visitors.sql.MySQLVisitor",
58 | "mode": "check",
59 | "whiteList":[],
60 | "blackList":[]
61 | },
62 | {
63 | "moudleName": "com/microsoft/jdbc/base/BaseStatement",
64 | "loadClass": "xbear.javaopenrasp.visitors.sql.SQLServerVisitor",
65 | "mode": "check",
66 | "whiteList":[],
67 | "blackList":[]
68 | }
69 | ]
70 | }
--------------------------------------------------------------------------------
/src/main/java/xbear/javaopenrasp/config/Config.java:
--------------------------------------------------------------------------------
1 | package xbear.javaopenrasp.config;
2 |
3 | import java.io.*;
4 | import java.util.Collection;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.concurrent.ConcurrentHashMap;
8 | import java.util.concurrent.CopyOnWriteArrayList;
9 |
10 | import com.alibaba.druid.support.json.JSONUtils;
11 |
12 | import xbear.javaopenrasp.util.Console;
13 |
14 | /**
15 | * Created by xbear on 2016/11/13.
16 | */
17 | public class Config {
18 |
19 | public static Map> moudleMap = new ConcurrentHashMap>();
20 |
21 | @SuppressWarnings({ "rawtypes", "unchecked" })
22 | public static boolean initConfig() {
23 | String configStr = readConfig("/main.config");
24 | if (configStr == null) {
25 | Console.log("init failed because of config file error");
26 | return false;
27 | }
28 |
29 | Map configMap = (Map) JSONUtils.parse(configStr);
30 | List