9 XXE
概念
XML External Entity Injection,即xml外部实体注入漏洞,发生在应用程序解析XML输入时,美欧禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起DdoS攻击等危害
触发点
往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
xml
可扩展标记语言(Extensible Markup Language),不同于HTML(被设计用来显示数据),XML是用来传输和存储数据。XML没有预定义标签,允许自定义标签和文档结构,XML 被设计用来传输和存储数据。
XML的语法规则:
• XML 文档必须有一个根元素
• XML 元素都必须有一个关闭标签
• XML 标签对大小敏感
• XML 元素必须被正确的嵌套
• XML 属性值必须加引号
XML中5个预定义的实体引用
< >
> <
& &
' ‘
" “
DTD(文档类型定义)
作用:定义XML文档的合法构建模块
两种构建方式:内部DTD声明、外部DTD声明(外部实体攻击主要利用DTD的外部实体来进行注入的)
声明方式:
·内部DTD声明:<!DOCTYPE 根元素 [元素声明]>
·外部DTD声明:<!DOCTYPE 根元素 SYSTEM “文件名”>
内部声明方式
外部声明方式
DTD实体构造:
DTD实体同样有两种构建方式:
内部实体声明:<!ENTITY entity-name ‘entity-value’>
外部实体声明:<!ENTITY entity-name SYSTEM “URL/URL”>
实例:
外部实体注入:
<?xml version=”1.0”?> <!DOCTYPE hack[ <!ENTITY xxe SYSTEM “file://etc/password”> ]>
上述代码中,XML的外部实体“xxe”被赋予的值为:file:///etc/passwd,当解析xml文档时,xxe会被替换为file:///ect/passwd的内容。
参数实体+外部实体注入:
<?xml version=”1.0”? encoiding=”utf-8”> <!DOCTYPE hack[ <!ENTITY % name SYSTEM “file://etc/password”> %name; ]>
实体又分为一般实体和参数实体
1,一般实体的声明语法:<!ENTITY 实体名 "实体内容“>
引用实体的方式:&实体名;
2,参数实体只能在DTD中使用,参数实体的声明格式: <!ENTITY % 实体名 引用实体的方式:%实体名;
XXE漏洞攻击主要是利用了DTD引用外部实体导致的漏洞。
攻击思路
• 1. 引用外部实体远程文件读取(有回显)
<?php header("content-type:text/html;charset=utf-8"); date_default_timezone_set("PRC"); $data = file_get_contents('php://input'); $xml = simplexml_load_string($data); echo date('Y-m-d H:i:s',time())." "; echo $xml->login; ?>
simplexml_load_string() 函数转换形式良好的 XML 字符串为SimpleXMLElement 对象。
第一步:
第二步:修改post内容
• 2. Blind XXE(先做记录)
如果服务器没有回显,只能使用Blind XXE漏洞来构建一条外带数据(OOB)
通道来读取数据。所以,在没有回显的情况下如何来利用XXE
思路:
1. 客户端发送payload 1给web服务器
2. web服务器向vps获取恶意DTD,并执行文件读取payload2
3. web服务器带着回显结果访问VPS上特定的FTP或者HTTP
4. 通过VPS获得回显(nc监听端口)
• 3. php命令执行
php环境下,xml命令执行需要php装有expect扩展,但是该扩展默认没
有安装,所以一般来说,比较难利用,这里就只给出代码了
<?php $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "except://ifconfig"> ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>
XXE防御:
1、过滤用户提供的XML数据
2、过滤关键字:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
3、不允许XML中含有自己定义的DTD
4、使用开发语言提供的禁用外部实体的方法
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))