内部声明 DTD:
引用外部 DTD:
或
内部声明实体:
引用外部实体:
或
在输入框或URL的参数中输入一些 XML 标签,如:
,若页面回显出Have XXE
,那么说明这个标签被后台所调用,说明存在 XML 实体注入。
但是有的时候,这些注入点可能不是那么明显,如一些仅适用 JSON 去访问服务的客户端。我们可以通过修改 HTTP 请求,修改 Content-Type 头部字段等方法,然后去查看响应包,查看程序是否解析了发送的内容,如果解析了,则存在 XXE 攻击漏洞。
现实中存在的大多数 XXE 漏洞都是 Blind XXE,即不可见的,必须采用带外通道才能查看返回信息的记录。
① 读取任意文件
② 执行系统命令,但需要有 expect 插件
③ 扫描网站的端口以及是否存在某些目录或文件
④ 通过 http 协议发起 SSRF 攻击
]>
&test;
因为 PHP 中有 ,当 XML 解析时,遇到
这类的符号时,会将 PHP 当做 XML 去解析,所以会报错,故需要将其进行 base64 编码读出。
]>
&test
通过 PHP 协议的 filter 输出流读取 PHP,并经过 base64 编码,这样 XML 就不会去解析 PHP 中的 ,就不会报错,故可以成功读出 PHP 文件的源码内容。
]>
&test
根据页面返回的报错信息或内容来判断端口是否开启,可以通过 BurpSuite 抓包来查看。
通过此方法也可以来查看目录或者文件是否存在。
若想执行协议,则需要目标主机上安装了 expect 插件,并且做了相关配置。条件较苛刻,所以比较少见。
同时还有一点需要注意:所执行的命令不允许含有空格。
]>
&test
若服务器没有回显,那么只能使用 Blind XXE 来构建一条带外数据 (OOB) 通道来读取数据。
角色:
思路:
① 攻击者 发送给 被攻击者 Web 服务器的 XML:
%remote;
]>
Web 服务器收到这段 XML 代码后就会去解析。根据其外部实体中的 http 协议去攻击者的服务器上去请求 test.xml 文件。
有的时候 Web 端可能会解码,所以需要视情况将 XML 代码进行编码后再发送。
② Web 服务器 到 攻击者的服务器 上请求的 test.xml 文件代码:
">
%int;
%trick;
当 Web 服务器请求到 test.xml 文件,并到 Web 服务器上进行解析时,会先通过 file 协议读取到 Web 服务器 (本机) 的 /etc/passwd 文件的内容,并赋给参数实体 %payload。
然后再使用 http 协议,携带者刚刚请求得到的 %payload 的内容作为参数,去访问 攻击者的服务器。
这样在攻击者的服务器的日志中就会留下相应的请求信息,攻击者就可以通过浏览日志来获取相应的敏感信息。
注:带有 %
的实体是一个参数实体,只有参数实体才能在 DTD 使用,且只能在外部 DTD 中使用。
不同的语言有不同的禁用方式:
① PHP:
libxml_disable_entity_loader(true);
② JAVA:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
③ Python:
from lxml import etree:
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities = FALSE))
可以过滤一些关键字,如:、、SYSTEM、PUBLIC 等。