Java代码审计安全篇-XXE(XML外部实体注入)漏洞

前言:

 堕落了三个月,现在因为被找实习而困扰,着实自己能力不足,从今天开始 每天沉淀一点点 ,准备秋招 加油

注意:

本文章参考qax的网络安全java代码审计,记录自己的学习过程,还希望各位博主 师傅 大佬 勿喷,还希望大家指出错误

XXE 漏洞:

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

利用方式:攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件),导致可加载恶意外部文件,利用file协议造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。

危害:任意文件读取,内网探测,攻击内网站点(结合SSRF),命令执行 ,dos攻击

XML (参考webgoat)

什么是 XML 实体?

XML 实体允许定义标记,在分析 XML 文档时,这些标记将被内容替换。通常有三种类型的实体:

  • 内部实体

  • 外部实体

  • 参数实体。

必须在文档类型定义 (DTD) 中创建一个实体,让我们从一个示例开始:

  正如你所看到的,一旦XML文档被解析器处理,它就会用定义的常量“Jo Smith”替换定义的实体。正如你所看到的,这有很多优点,因为你可以在一个地方更改为例如“约翰史密斯”。js js

在 Java 应用程序中,XML 可用于将数据从客户端获取到服务器,我们都熟悉 JSON API,我们也可以使用 xml 来获取信息。大多数情况下,框架会根据 xml 结构自动填充 Java 对象,例如:

例子:

让我们看一个 XXE 注入的例子,在上一节中我们看到 XML 实体可以按如下方式使用:

<span style="color:#333333"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#efefef"><code><span style="color:#557799"><?xml version="1.0" standalone="yes" ?></span>
<span style="color:#3344bb"><!DOCTYPE author [<!ELEMENT author (#PCDATA)></span><span style="color:#3344bb"><!ENTITY js "Jo Smith"></span>
<span style="color:#3344bb">]></span>
<span style="color:#007700"><author></span><span style="color:#880000"><strong>&js;</strong></span><span style="color:#007700"></author></span></code></span></span></span></span>
外部 DTD 声明

定义这些实体还可以在外部文件中定义另一个 DTD,例如:

<span style="color:#333333"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#efefef"><code><span style="color:#557799"><?xml version="1.0"?></span>
<span style="color:#3344bb"><!DOCTYPE note SYSTEM "email.dtd"></span>
<span style="color:#007700"><email></span><span style="color:#007700"><to></span>webgoat@webgoat.org<span style="color:#007700"></to></span><span style="color:#007700"><from></span>webwolf@webwolf.org<span style="color:#007700"></from></span><span style="color:#007700"><subject></span>Your app is great, but contains flaws<span style="color:#007700"></subject></span><span style="color:#007700"><body></span>Hi, your application contains some SQL injections<span style="color:#007700"></body></span>
<span style="color:#007700"></email></span></code></span></span></span></span>

可以定义如下:email.dtd

<span style="color:#333333"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#efefef"><code><!ELEMENT email (to,from,title,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT subject (#PCDATA)>
<!ELEMENT body (#PCDATA)></code></span></span></span></span>

如果 XML 解析器配置为允许外部 DTD 或实体,则可以使用以下命令更改以下 XML 代码片段:

<span style="color:#333333"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#efefef"><code><span style="color:#557799"><?xml version="1.0" encoding="utf-8"?></span>
<span style="color:#3344bb"><!DOCTYPE author [<!ENTITY js SYSTEM "file:///etc/passwd"></span>
<span style="color:#3344bb">]></span>
<span style="color:#007700"><author></span><span style="color:#880000"><strong>&js;</strong></span><span style="color:#007700"></author></span></code></span></span></span></span>

现在会发生什么?我们从本地文件系统定义了一个包含,XML 解析器将加载文件,并将在引用实体的任何位置添加内容。假设 XML 消息返回给用户,该消息将是:

额外的文档类型定义 (DOCTYPE) 是您始终可以添加到 xml 文档中的内容,如果启用了解析器设置以允许处理外部实体,则查找 XXE 注入的良好开端。

靶场训练 

我们直接进入靶场环境

1. 参考Drunkbaby师傅审计思路

我们随便输入一个评论然后抓包得到:

它会直接会被处理为XML数据,并且经过测试发现没有进行任何的检查或者过滤,reponse返回sorry,意思就是失败那根据这个,我们可以将xml数据中添加XML entity,并采用file:///的方式获取根目录的文件(linux系统就可以读取/etc/passwd等)

paylaod:

<?xml version="1.0"?><!DOCTYPE root [<!ENTITY root SYSTEM "file:///C:/">]><comment><text>&root;</text></comment>

 其中root可以换成其他字符串,但是不要违反XML的命名要求。得到下面就说明成功

这时候c盘文件目录全部被读取泄露 

我们审计一下源代码 

@PostMapping(path = "xxe/simple", consumes = ALL_VALUE, produces = APPLICATION_JSON_VALUE)@ResponseBodypublic AttackResult createNewComment(HttpServletRequest request, @RequestBody String commentStr) {String error = "";try {var comment = comments.parseXml(commentStr);comments.addComment(comment, false);if (checkSolution(comment)) {return success(this).build();}} catch (Exception e) {error = ExceptionUtils.getStackTrace(e);}return failed(this).output(error).build();}

我们主要看下面代码

 var comment = comments.parseXml(commentStr);
//var comment = comments.parseXml(commentStr);: 解析传入的XML字符串commentStr,并将结果存储在名为comment的变量中。这里使用了一个名为comments的对象(类型未知)的parseXml方法来执行解析操作。

跳转到 Comments.parseXml 去,主要描述了 parseXml 如何处理 commentStr。 

关注下面两行

var jc = JAXBContext.newInstance(Comment.class);  
var xif = XMLInputFactory.newInstance();
  • 前置知识:JAXB 作为 JDK 的一部分,能便捷地将 Java 对象与 XML 进行相互转换。
  • JAXBContext 是整个 JAXB API 的入口。主要用来构建 JAXB 实例newInstance()
  • Marshaller接口,将Java对象序列化为XML数据。
  • Unmarshaller接口,将XML数据反序列化为Java对象。

接下来要讲的是产生 XXE 的代码块原因

var unmarshaller = jc.createUnmarshaller();  
return (Comment) unmarshaller.unmarshal(xsr);

此处创建一个 Unmarshaller 对象。返回的值是 XML 经过unmarshal 方法处理的值。由于 unmarshal 在执行过程中解析了 XML(这里类似于反序列化的意思),导致 XXE 注入。

当把 XML 格式的字符串传递给 Unmarshaller 接口转变成 Java 对象时,会解析一遍 XML,如果传入的值可控就会导致 XXE 注入攻击。

将接受的XML格式评论解析为评论的对象

 comments.addComment(comment, false);//将解析后的评论对象comment添加到名为comments的对象(类型未知)中,以便将其保存到评论列表中。第二个参数false表示该评论不是管理员评论。if (checkSolution(comment)) {return success(this).build();}

就是这里就没对接受的参数进行过滤或者禁用 就直接开始进行check,然后攻击者就可以构造恶意的代码进行攻击

2. REST框架XXE

我们也继续输入1得到

抓包发现 发送的请求不是xml格式 而是json格式 

我们修改为json格式得到报错 

根据XML解析器的不同,您可能会得到更好的错误消息,在这种情况下,消息有点神秘,这意味着我们没有发送有效的xml。

 我们使用上一关的paylaod继续读取C盘

成功读取C盘内容 

审计:

ContentTypeAssignment.java

public AttackResult createNewUser(HttpServletRequest request,@RequestBody String commentStr,@RequestHeader("Content-Type") String contentType) {AttackResult attackResult = failed(this).build();if (APPLICATION_JSON_VALUE.equals(contentType)) {comments.parseJson(commentStr).ifPresent(c -> comments.addComment(c, true));attackResult = failed(this).feedback("xxe.content.type.feedback.json").build();}if (null != contentType && contentType.contains(MediaType.APPLICATION_XML_VALUE)) {String error = "";try {Comment comment = comments.parseXml(commentStr);comments.addComment(comment, false);if (checkSolution(comment)) {attackResult = success(this).build();}} catch (Exception e) {error = ExceptionUtils.getStackTrace(e);attackResult = failed(this).feedback("xxe.content.type.feedback.xml").output(error).build();}}return attackResult;

并没有对Content-Type 进行严格的过滤。 然后也是使用了parsexml函数 跟上提一样

3.XXE DOS攻击

使用相同的 XXE 攻击,我们可以对服务器执行 DOS 服务攻击。此类攻击的一个例子是:

<?xml version="1.0"?>
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

当 XML 解析器加载此文档时,它会看到它包含一个根元素“lolz”,其中包含文本“&lol9;”。但是,“&lol9;”是一个已定义的实体,它扩展为包含十个“&lol8;”字符串的字符串。每个“&lol8;”字符串都是一个定义的实体,可扩展为十个“&lol7;”字符串,依此类推。在处理完所有实体扩展后,这个小的(< 1 KB)的 XML 块实际上将占用近 3 GB 的内存。

修复(参考百度开发者中心):

  1. 验证输入数据:对所有输入数据进行严格的验证和过滤,确保没有恶意的内容被注入到应用程序中。对所有用户输入进行适当的验证和清理,可以有效地防止攻击者利用XXE漏洞进行攻击。
  2. 禁用外部实体引用:在处理XML数据时,禁用或限制对外部实体的引用。这可以通过配置XML解析器来实现,确保应用程序不会加载外部实体,从而减少被攻击的风险。
  3. 使用安全的XML解析器:选择经过安全加固的XML解析器,并遵循最佳实践来使用它们。这些解析器通常具有内置的安全功能,能够检测和防范XXE攻击。
  4. 限制实体大小:设置合理的实体大小限制,防止攻击者通过大量数据来耗尽资源或触发拒绝服务攻击。
  5. 日志记录和监控:启用详细的日志记录和监控机制,以便及时发现和响应任何可疑的活动。通过监控应用程序的行为和异常模式,可以快速检测并应对潜在的XXE攻击。
  6. 定期更新和维护:保持系统和应用程序的最新状态,及时修复已知的安全漏洞。定期更新和维护可以确保您的系统不受最新的XXE攻击威胁。
  7. 安全培训和意识提升:对开发人员和运维人员进行安全培训,提高他们对XXE漏洞的认识和防范意识。只有当整个团队都意识到安全问题并采取相应的防护措施时,才能更有效地防止XXE攻击。
  8. 使用Web应用防火墙(WAF):部署一个有效的Web应用防火墙可以提供额外的防护层,监测并阻止恶意请求和已知的攻击模式。WAF可以帮助识别并拦截包含XXE漏洞的恶意请求,保护应用程序免受攻击。
  9. 代码审查和安全测试:实施严格的代码审查和安全测试流程,确保应用程序在开发阶段就避免了潜在的安全风险。通过专业的安全测试工具和团队,可以检测出应用程序中存在的XXE漏洞以及其他安全问题。
  10. 数据加密和保护:对敏感数据进行加密存储和传输,降低数据泄露的风险。即使攻击者能够利用XXE漏洞获取敏感信息,加密措施也可以使数据难以被利用。

源码地址

 https://github.com/WebGoat/WebGoat/tree/main/src/main/java/org/owasp/webgoat/lessons/xxe

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Bean的生命周期流程

前言 Java 中的公共类称之为Java Bean&#xff0c;而 Spring 中的 Bean 指的是将对象的生命周期&#xff0c;交给Spring IoC 容器来管理的对象。所以 Spring 中的 Bean 对象在使用时&#xff0c;无需通过 new 来创建对象&#xff0c;只需要通过 DI&#xff08;依赖注入&#x…

【Java设计模式】二十一、访问者模式

文章目录 1、访问者模式2、案例&#xff1a;宠物喂食3、总结 1、访问者模式 封装一些作用于某种容器中各个元素的操作。相关角色&#xff1a; 抽象访问者&#xff1a;定义了对每一类元素访问的行为。方法个数等于具体元素类的个数&#xff0c;方法形参是可访问的元素。具体访…

固态硬盘有缓存和没缓存有什么区别

固态硬盘&#xff08;SSD&#xff09;已经成为现代计算机的重要组成部分&#xff0c;它们提供了比传统机械硬盘更快的读写速度&#xff0c;从而显著提升了操作系统的运行速度和应用程序的加载效率。 其中&#xff0c;缓存&#xff08;Cache&#xff09;是固态硬盘中一个重要的…

留学生课设|R语言|研究方法课设

目录 INSTRUCTIONS Question 1. Understanding Quantitative Research Question 2. Inputting data into Jamovi and creating variables (using the dataset) Question 3. Outliers Question 4. Tests for mean difference Question 5. Correlation Analysis INSTRUCTIO…

idea如何使用,从激活开始

idea到期后激活使用 如何使用 点击阅读 idea分享

边缘计算与物联网的核心 —— 低功耗芯片

一、低功耗芯片 在边缘计算与物联网&#xff08;IoT&#xff09;中&#xff0c;低功耗芯片扮演了至关重要的角色&#xff0c;主要体现在以下几个方面&#xff1a; 延长设备寿命&#xff1a;物联网设备通常需要部署在难以更换电池或不方便进行频繁维护的环境中&#xff0c;比如…

【FPGA】DDR3学习笔记(二)丨从SDRAM到DDR3的IP核设计

本篇文章包含的内容 一、DDR SDRAM1.1 基本概述1.2 工作时序&#xff08;以读取为例&#xff09; 二、DDR2 SDRAM2.1 基本概述2.2 工作时序 三、DDR3 SDRAM3.1 基本概述3.2 硬件设计3.3 读写时序3.4 MIG IP核设计3.5 读写代码设计 开发板&#xff1a;正点原子的达芬奇开发板&am…

PlantUML Integration 编写短信服务类图

PlantUML Integration 写一个类图&#xff0c;主要功能为 1、编写一个serviceSms短信服务类&#xff1b; 2、需要用到短信的地方统一调用基建层的服务即可&#xff1b; 3、可以随意切换、增加短信厂商&#xff0c;不需要更改场景代码&#xff0c;只需要更改application.yml 里面…

【OpenCV】手写字符分割

OpenCV 是一个开源的计算机视觉&#xff08;Computer Vision&#xff09;与机器学习软件库&#xff0c;提供了多种图像处理算法与接口。在 OCR 技术中&#xff0c;字符分割用于提取图像中的文字信息&#xff0c;可以应用于车牌识别、身份证识别、文档扫描等场景。本文主要记录如…

【Flutter学习笔记】9.6 动画切换组件(AnimatedSwitcher)

参考资料&#xff1a;《Flutter实战第二版》9.6 动画切换组件&#xff08;AnimatedSwitcher&#xff09; 9.6.1 AnimatedSwitcher AnimatedSwitcher 可以同时对其新、旧子元素添加显示、隐藏动画&#xff0c;在需要切换新旧元素的场景广泛使用。也就是说在AnimatedSwitcher的子…

Java操作Sql语句 出现迭代死循环 (Bug排查)

目录 1. 问题所示2. 原理分析3. 解决方法4. 彩蛋1. 问题所示 Java执行Sql语句来查询一些数据的时候 虽说数据量很大,但是查询过程中一直迭代查询 截图如下所示: 2. 原理分析 至于迭代死循环,可能是不满足的条件也进入查询(本身我的数据量就很大) 主要可能引起的两个原…

Python数学建模-2.3函数(下)

2.3.2模块的导入与使用 模块在Python中是一个包含Python定义和语句的文件&#xff0c;通常用来组织代码&#xff0c;使得代码更易于管理和复用。下面&#xff0c;我将详细讲解Python函数中模块的使用知识。 1. 模块的导入 在Python中&#xff0c;你可以使用import语句来导入…