抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

XML外部实体注入攻击&&2020-4-2知识补充

xml是可扩展标记语言(EXtensible Markup Language)的缩写。它与HTML类似同为w3c推荐标准,但是比HTML要严谨。因为它所有的标签一定要闭合。 同时它也可以用自己定义的标签,但是XML是不作为的标记语言,不像HTML,XML只是将数据结构化存储与传输。

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素

xml文档的构建模块

  • 元素
  • 属性
  • 实体
  • PCDATA
  • CDATA
  1. 元素是 XML 以及 HTML 文档的主要构建模块,元素可包含文本、其他元素或者是空的。

    1
    2
    <title>my blog</title> 
    <writer>r1ght0us is best</writer>
  2. 属性

    1
    2

    <img src="r1ght0us.gif" />
  3. 实体
    实体是用来定义普通文本的变量。实体引用是对实体的引用。

  4. PCDATA
    PCDATA 的意思是被解析的字符数据(parsed character data)。
    PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

  5. CDATA
    CDATA 的意思是字符数据(character data)。
    CDATA 是不会被解析器解析的文本。

DTD(文档类型定义)

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。

  1. 内部声明:<!DOCTYPE 根元素 [元素声明]>

完整实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?><!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
  1. 外部声明(引用外部DTD):<!DOCTYPE 根元素 SYSTEM "文件名">

ex: <!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>

完整实例:

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "http://www.test.com/note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

而note.dtd的内容为:

1
2
3
4
5
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

DTD实体

DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体

  1. 一般实体的声明语法: <!ENTITY 实体名 "实体内容“>
  2. 引用实体的方式:&实体名;
  3. 参数实体只能在DTD中使用,参数实体的声明格式:
    引用实体的方式:%实体名;
  4. 内部实体声明: ex:<!ENTITY eviltest "eviltest">

完整实例:

1
2
3
4
5
6
7
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "r1ght0us">
<!ENTITY BLOG "http://r1ght0us.xyz">
]>

<test>&writer;&BLOG;</test>
  1. 外部实体声明:<!ENTITY 实体名称 SYSTEM "URI">

完整实例:

1
2
3
4
5
6
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "https://github.com/r1ght0us">
<!ENTITY handsome SYSTEM "http://www.chenguanxin.com">
]>
<author>&writer;&handsome;</author>
  1. 关于XML的几个注意点:
  • 所有的XML标记必须要闭合标签
  • 所有的XML的标签对大小写敏感
  • XML的属性值必须要加引号
  • 在XML中的五个符号需要实体引用
实体引用 符号 中文解释
&lt; < 小于号
&gt; > 大于号
&amp; & 和号
&apos; 单引号
&quot; 双引号

XXE漏洞

如何构建XXE

  1. 直接通过DTD外部实体声明(针对有回显的情况)


下图为一个XXE-labs中的测试

  1. 外部文档类型定义(DTD)文件可被用于触发OOB XXE。攻击者将.dtd文件托管在VPS上,使远程易受攻击的服务器获取该文件并执行其中的恶意命令。(不进行回显)

    外部DTD的内容

    其中php是伪协议不必多说。大概说一下原理,因为实战中大部分都是不进行回显,那么我们可以让服务器主动请求攻击者的VPS。那么我们让服务器引用写在VPS的DTD然后他会将payload加载,然后带进并访问我们的VPS,然后我们的VPS查看access_log可以接受到payload返回信息
  2. 端口扫描

BP中的intruder模块设置如下

因为其连接特性,如果一个端口开放会进行很快的响应,如果未开放,会进行多次连接进行到一定次数才会显示连接失败。那么爆破可以根据其完成一次相应的时间。
由于网络延时 or 某些协议的特有的连接方式,会显示不是特别精确有一定的误差

爆破如下所示

防御XXE漏洞

1
2
php:
libxml_disable_entity_loader(true);
1
2
3
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
1
2
3
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

或者是将关键词 ex:DOCYPE,ENTITY进行过滤。

2020-4-2补充

  1. docx文档注入

下面是一个简单的示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
if(isset($_POST["submit"])) {
$target_file = getcwd()."/upload/".md5($_FILE["file"]["tmp_name"]);
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
try {
$result = @file_get_contents("zip://".$target_file."#docProps/core.xml");
$xml = new SimpleXMLElement($result, LIBXML_NOENT);
$xml->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
foreach($xml->xpath('//dc:title') as $title){
echo "Title '".$title . "' has been added.<br/>";
}
} catch (Exception $e){
echo "The file you uploaded is not a valid xml or docx file.";
}
} else {
echo "Sorry, there was an error uploading your file.";
}
}

攻击示例:

评论