
环境已经关了,这里主要说下思路
拿到题目,很容易发现一个任意文件读取
读取根目录flag,权限不够,发现根目录有/readflag
那么思路就是要rce或者其他有执行/readflag得操作了
由题目知道是 tomcat java的
读源码
搭建过tomcat的师傅们知道tomcat一般的默认路径
挨个读取文件
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/util/Secr3t.class
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/servlet
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/controller
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/entity
/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/util
主要是这三个文件
SerAndDe.class
User.class
HelloWorldServlet.class
然后去反编译
@WebServlet(name = "HelloServlet", urlPatterns = {"/evi1"})
/* loaded from: file(5) */
public class HelloWorldServlet extends HttpServlet {
    private volatile String name = "m4n_q1u_666";
    private volatile String age = "666";
    private volatile String height = "180";
    User user;
    public void init() throws ServletException {
        this.user = new User(this.name, this.age, this.height);
    }
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String reqName = req.getParameter("name");
        if (reqName != null) {
            this.name = reqName;
        }
        if (Secr3t.check(this.name)) {
            Response(resp, "no vnctf2022!");
        } else if (Secr3t.check(this.name)) {
            Response(resp, "The Key is " + Secr3t.getKey());
        }
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String key = req.getParameter("key");
        String text = req.getParameter("base64");
        if (!Secr3t.getKey().equals(key) || text == null) {
            Response(resp, "KeyError");
            return;
        }
        if (this.user.equals((User) SerAndDe.deserialize(Base64.getDecoder().decode(text)))) {
            Response(resp, "Deserialize…… Flag is " + Secr3t.getFlag().toString());
        }
    }
    private void Response(HttpServletResponse resp, String outStr) throws IOException {
        ServletOutputStream out = resp.getOutputStream();
        out.write(outStr.getBytes());
        out.flush();
        out.close();
    }
}public class SerAndDe {
    private SerAndDe() {
    }
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream bos = null;
        try {
            try {
                bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                oos.writeObject(object);
                byte[] b = bos.toByteArray();
                if (oos != null) {
                    try {
                        oos.close();
                    } catch (IOException ex) {
                        System.out.println("io could not close:" + ex.toString());
                    }
                }
                if (bos != null) {
                    bos.close();
                }
                return b;
            } catch (IOException e) {
                System.out.println("serialize Exception:" + e.toString());
                if (oos != null) {
                    try {
                        oos.close();
                    } catch (IOException ex2) {
                        System.out.println("io could not close:" + ex2.toString());
                        return null;
                    }
                }
                if (bos != null) {
                    bos.close();
                }
                return null;
            }
        } catch (Throwable th) {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException ex3) {
                    System.out.println("io could not close:" + ex3.toString());
                    throw th;
                }
            }
            if (bos != null) {
                bos.close();
            }
            throw th;
        }
    }
    public static Object deserialize(byte[] bytes) {
        ByteArrayInputStream bais;
        try {
            bais = null;
            try {
                bais = new ByteArrayInputStream(bytes);
                Object readObject = new ObjectInputStream(bais).readObject();
                if (bais != null) {
                    try {
                        bais.close();
                    } catch (IOException ex) {
                        System.out.println("LogManage Could not serialize:" + ex.toString());
                    }
                }
                return readObject;
            } catch (IOException | ClassNotFoundException e) {
                System.out.println("deserialize Exception:" + e.toString());
                if (bais != null) {
                    try {
                        bais.close();
                    } catch (IOException ex2) {
                        System.out.println("LogManage Could not serialize:" + ex2.toString());
                        return null;
                    }
                }
                return null;
            }
        } catch (Throwable th) {
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException ex3) {
                    System.out.println("LogManage Could not serialize:" + ex3.toString());
                    throw th;
                }
            }
            throw th;
        }
    }
}
public class User implements Serializable {
    private String name;
    private String age;
    private transient String height;
    public User(String name, String age, String height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return this.age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public String getHeight() {
        return this.height;
    }
    public void setHeight(String height) {
        this.height = height;
    }
    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        this.height = (String) s.readObject();
    }
    @Override // java.lang.Object
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof User)) {
            return false;
        }
        User user = (User) obj;
        if (!user.getAge().equals(this.age) || !user.getHeight().equals(this.height) || !user.getName().equals(this.name)) {
            return false;
        }
        return true;
    }
    @Override // java.lang.Object
    public String toString() {
        return "User{name='" + this.name + "', age='" + this.age + "', height='" + this.height + "'}";
    }
}java代码审计
可以知道得先得到一个key doGet 方法那里得到key
直接读key是行不通得


然后这里要设法绕过

乍一看是决定无法成功得
经过师傅提示 ,跟java线程安全有关系,burpsuite开两个intruder


然后去爆破,等个几分钟 响应包中发现得到key
之后 去 doPost 方法 设法得到flag

这里反序列化必须满足条件
新建一个t3目录

根据原先得目录结构 新建这几个文件


对t3文件夹 直接 右键 idea打开

文件--项目结构设置


模块标记为源
直接把 User和 SerAndDe得代码 拷贝进去
写一个main

然后是漫长得改bug
SerAndDe中bug很多

通过idea提示 等等 终于改完bug
运行之后 发现 还不行

注意到 User中得
private transient String height;https://blog.csdn.net/qq_42843172/article/details/107193866
transient关键字:游离的,被该关键字修饰的变量不参与序列化
所有这里还得重写 User中得
readObject 和 writeObject 方法

然后再次运行main就成功了

post传入key和 base64即可

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。